Reading out analog signals with the help of an ADC

With the Dwengo library you can easily read out analog sensors that are connected to channel AN0-AN4 without having to worry about all the technical details. On this page we go into more detail about how you can setup the build-in ADC module (Analog Digital Convertor) yourself and how you can use all the available ADC channels. On the PIC18F4550 there are up to 13 pins that can be used to read out analog sensors. The analog digital conversion has an accuracy of 10 bits.

The following libraries need to be loaded in order to use the ADC module:

  1. #include <p18f4550.h>
  2. #include <adc.h>
  3. #include <delays.h>

After the initialization of the ADC module with OpenADC(), you can read out analog values of a sensor. Some important parameters need to be given to the OpenADC() function:

  • ADC_FOSC_64: setups the ADC conversion clock, also known as TAD = ADC_FOSC_64/FOSC. According the PIC18F4550 data sheet External link one TAD has a value between 0.7 us and 25 us. Since we setup FOSC with the help of the configuration bits to 48 MHz we get a TAD of 1.33 us, nicely within the specified limits.
  • ADC_RIGHT_JUST: only the least significant bits are used. However, when using the function ReadADC() this has no influence and all 10 bits are returned.
  • ADC_6_TAD: acquisition time, a minimal time of 1.4 us is required to obtain a good ADC. By using 6 TADs we certainly comply to this requirement.
  • ADC_INT_OFF: do not use ADC based interrupts.
  • ADC_VREFPLUS_VDD: the positive voltage of the microcontroller (5 V) is used a the positive voltage reference.
  • ADC_VREFMINUS_VSS: the negative voltage of the microcontroller (the ground, 0 V) is used as the negative voltage reference.
  • 0b1010: with this you can indicate which pins of port A you want to use for connecting analog sensors on (see register 21-2 in the PIC18F4550 data sheet External link ). With 0b1010 you indicate that AN0-AN4 will be used for analog digital conversion. With the value 0b0010 you would indicate that you will use all the 13 ANx-pins.
  1. /*
  2.   ADC_FOSC_64: conversion clock, table 21-1, 1TAD = 1,33 us (has to be between 0,7 us and 25 us)
  3.   ADC_RIGHT_JUST: least significant bits
  4.   ADC_6_TAD: acquisition time, 6 TAD's used for good conversion, minimal 1,4 us required
  5.   ADC_CH0: default channel you read out, we chose AN0.
  6.   ADC_INT_OFF: no adc-interrupts
  7.   ADC_VREFPLUS_VDD and ADC_VREFMINUS_VSS: use PIC ground and source as voltage reference
  8.   0b1010: pins AN0-AN4 configured as analog input pins
  9.   */
  10. OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_6_TAD,
  11. ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS,
  12. 0b1010); // Configuring ADC

Finally we come to reading out the actual sensor. We will read out the sensor continuously, as long as the Dwengo board is powered on, and write out the detected value to the display.

Reading out an analog sensor is typically done in 5 steps:

  1. Chose the channel (or the port) you want to read out. We chose for AN0. Note that this is the default port we read out is setup with the function OpenADC(). So actually we could skip this step in our example. However, this step is important if you want to read out multiple sensors on the Dwengo board.
  2. Wait until the correct channel is selected by the microcontroller. Since the pins are loaded, this can take some time, hence it is advised a short while.
  3. Start the conversion.
  4. Wait until the value is read out.
  5. Read out the value and store it in a variable. With the function ReadADC() you read out all 10 bits. So you get a value between 0 and 1023. The value 0 corresponds to 0 V and the value 1023 with 5 V. This corresponds to our initialization of the ADC module with the parameters ADC_VREFPLUS_VDD and ADC_VREFMINUS_VSS. Note that the analog digital conversion happens linear, so the value 512 corresponds with 2.5 V.
  1. SetChanADC(ADC_CH0); // choose ADC channel (override ADC_CH0)
  2. Delay10TCYx(150); // wait a bit
  3. ConvertADC(); // start conversion
  4. while(BusyADC()); // wait for conversion
  5. data = ReadADC(); // read result

With the help of CloseADC() the ADC module can be closed, which is useful if you only want to use some pins temporarily for analog to digital conversion (and after the analog to digital conversion use the pins directly as digital inputs or outputs).