Proton Tutorial - Analogue To Digital Conversion (ADC)

Many PIC's have the ability to perform analogue to digital conversions, and in this example the 16F877 is used. It doesn't take any extra components, although a pull down resistor is always good to keep the conversions as accurate as possible, though not needed in some cases. Here's an example:

adc

 

Simulation

 

This example has 2 inputs that are going to be used for ADC's, and an LCD to relay information to the user. ADC needs some settings defined before its use, the compiler will assign default settings if you don't specify them in your program, but its a handy thing to know.

DECLARE ADIN_RES 10 ' 10-bit result required
 DECLARE ADIN_TAD FRC ' RC OSC chosen
 DECLARE ADIN_STIME 50 ' Allow 50us sample time 

 

ADIN_RES specifies the resolution of the ADC result, 8 bit allows for values from 0-255 and 10 bit allows 0-1023. 10 bit is usally a good option, as it provides much better accuracy and each increment would be the equivalent of 0.0048V, compared to 8 bit reolution whose increments would be the equivalent of 0.009V.

ADIN_TAD defines the clock source that the ADC uses. FRC indicates that the internal RC Osc is used for the operation, and is guaranteed to work every time. Other options are available, but can degrade the ADC performance . So if accuracy is not important you could use the external Osc and achieve much faster results. See the programmer help file for more detail.

ADIN_STIME Allows the internal capacitors to fully charge before a sample is taken. This may be a value from 0 to 65535 microseconds (us). A value too small may result in a reduction of resolution. While too large a value will result in poor conversion speeds without any extra resolution being attained.

ADCON1 isthe register used to set up which pins are used as anologue / digital, and what pin to compare the voltage with (Vref). Check the datasheet for a more detailed explanation on the ADCON1 register for the PIC your using.

There are many different options, but to keep it easy, the following setting is used in this example;

ADCON1 = %10000000

 

The above makes all of PORTA analogue and the voltage reference is Vdd. Bit 7 (set as a 1 in the example) is to tell the MCU how to save the data, i.e. left / right justify. We have chosen 1 - right justify, so now the data will always be 0000 00xx xxxx xxxx in 10 bit mode - much easier to work with.

Now for the program itself. The following example performs an ADC on PORTA.0 and then PORTA.1 and displays the value in volts on the LCD. Note the small delay between samples, this is allowing the internal capacitors to charge between samples.

Proton Tutorial - Analogue To Digital Conversion (ADC)
Device 16F877
Declare XTAL 4
 
Declare ADIN_RES 10 ' 10-bit result required
 Declare ADIN_TAD FRC ' RC OSC chosen
 Declare ADIN_STIME 50 ' Allow 50us sample time
  
Declare LCD_TYPE 0 ' Type of LCD Used is Alpha
 Declare LCD_DTPIN PORTB.4 ' The control bits B4,B5,B6,B7
 Declare LCD_RSPIN PORTB.2 ' RS pin on B2
 Declare LCD_ENPIN PORTB.3 ' E pin on B3
 Declare LCD_INTERFACE 4 ' Interface method is 4 bit
  
PORTB_PULLUPS True
 
Dim Result1 As Float
Dim Result2 As Float
 
Dim Last_Result1 As Float
Dim Last_Result2 As Float
 
Symbol Input1 = PORTA.0
Symbol Input2 = PORTA.1
 
TRISA = %00000011 ' Configure AN0 (PORTA.0+1) as an input
  
ADCON1 = %10000000 ' Set analogue input, Vref is Vdd
  
Main:
 
Result1 = ADIn 0 ' Grab A0's digital value
DelayUS 1 ' Allow internal capacitors to charge
Result2 = ADIn 1 ' Grab A1's digital value
 
Result1 = Result1 * 5 / 1023 ' Scale it to volts
Result2 = Result2 * 5 / 1023 '
 
If Last_Result1 Result1 Then ' Check if value has changed
 Print At 1, 1, DEC2 Result1, "V " ' If it has, display new data
 Last_Result1 = Result1 ' and update last value
EndIf
 
If Last_Result2 Result2 Then ' Check if value has changed
 Print At 2, 1, DEC2 Result2, "V " ' If it has, display new data
 Last_Result2 = Result2 ' and update last value
EndIf
 
GoTo Main ' Loop for ever

 

The output on the LCD looks something like this;

adc.ht1

I have used floats in this example, and it's not the most efficient way of programming, but once the float algorithm has been loaded into the program, it doesn't consume to much more code whenever you use floats, however, this example compiled to 824 lines of code. You can however use words (16bit registers) to reduce the program size and increase its efficiency, but I always find myself choosing accuracy over speed..


Voltages over 5V

For voltages that exceed 5V that you wish to sample, simply use a voltage divider network like the following;

adc_voltage_divider


For best ADC performance of the PIC micro, the input impedance should not exceed 2.5K as the PIC's internal capacitors will take too long too charge/discharge. This isn't really an issue for most projects though, as you can just change the sample time with a couple of settings - see the help file of your compiler for more information. I generally use 10K resistors without any issues.

Forum Activity

Member Access