AVR - ADC (Analog to Digital Conversion)

Almost all AVR microcontrollers have ADC (Analog to Digital Conversion) pins, except a few, like ATTINY 2313 / 4313 series.

The main concept of ADC is,  a stair-case type reference voltage is generated  in steps by the micro-controller internally and compares the signal / input voltage with the generated reference voltage.  If the input voltage just crosses the reference voltage, then the step number in the stair case is noted and saved in to its related Register (ADC).  Our code reads the related Register and process as per our requirement.

RESOLUTION AND REFERENCE VOLTAGE SELECTION:

 

So, the Resolution of the ADC value depends on the number of steps generated for a range of voltage.  Normally AVR micro-controllers generate 1024 steps (equals to 2 to power 10) from 0VDC to Reference Voltage.  So, the data shows 10 bit resolution of ADC.  The Reference voltage may be Vcc voltage or separate external input voltage other than Vcc or fixed internal reference voltage ( like 1.2V).  The reference voltage input may be selected by setting the required bits in the related register (ADMUX).

Bits 7 & 6 of ADMUX are named as REFS1 and REFS0.  The bit setting serves for various input reference voltages in combination as shown below:

REFS1=0 and REFS0=0 means external voltage as reference at VREF pin.

REFS1=0 and REFS0=1 means Vcc as reference and connect 0.1uF capacitor at VREF pin to ground.

REFS1=1 and REFS0=1 means Internal Reference Voltage used  as reference and connect 0.1uF capacitor at VREF pin to ground.

ADC_working3.gif

eg: assume that the reference voltage is set to 5VDC. 

then, the ADC divides it into 1024 steps, ranging from 0000 to 1023 digital values.

so, each step of 5V (= 5000 milli Volts) is equals to 5000/1024 = 4.8828125 mV 

which is approximately equal to 5 milli Volts.

So, the ADC of AVR in this case cannot measure less than 5 milli Volt fraction,

in other wards, the ADC value of output available in the Register is approximately multiples of 5 milli Volts (= 0.005V)

So, you should not expect less than 5 milli volt accuracy with the above settings.

Similarly, you may calculate and set your input.

Note/Tip: if the external input reference voltage is 1.023V, then the ADC value is directly proportional to the milli Volt signal input. (1 ADC unit = 1 milli Volt)

ACCURACY AND speed of ADC conversion:

The accuracy of ADC for AVR micro-controller also depends on the speed of the comparision with the step voltage.  You have to sacrifice accuracy to a little extent to get the conversion quickly. The accuracy is sufficiently good upto 200 KHz clock set for the ADC comparision.  If the ADC clock speed is set more than 200 KHz, then little accuracy will lost in ADC conversion.  The frequency dividing w.r.t. CPU clock is called Prescaling for ADC conversion.

In case 8 bit conversion (0 to 255 steps) is suffiecient for your requirement, then the conversion may cross 200 KHz.

The clock speed may be set by division factor w.r.t. to the main CPU clock in related Register (ADCSRA), i.e., ADC Control and Status Register A.  The LSB bits of ADCSRA are names as  ADPS2, ADPS1, ADPS0 and 16, 4 and 2 are the division factors respectively.  The minimum division factor is 2 by default if all set to zeroes.

eg: if ADPS2=1, ADPS1=0 and ADPS0=1 means division factor is 16X2 = 32.

SELECTING CHANNEL FOR ADC conversion:

Normally, AVR micro-controllers have more than one ADC channel connected to specific pins to the exeternal world for ADC conversion.  Internally the ADC processor is same for all the channels, but a multiplexer is used to select a specific pin at a time for conversion.

The multiplexing Register (ADMUX) is not only used for selection of the particular pin, but also to select differential input and gain in some micro-controllers by setting the specific bits.  The LSBs of the ADMUX are used for directly selecting the channel (or pin).

eg: set 000 to LSB of ADMUX, to select channel 0(pin ADC0), 001 for channel 1 (pin ADC1) etc.

READING ADC VALUE FROM THE REGISTER:

The ADC value, which is the digital value for the analog voltage / signal input is stored in Register (ADC). The result is also available in ADCL and ADCH registers, which contains 8 LSB of the ADC and 8 MSB of ADC.   The value may be directly read from the ADC register by setting / returning to the variable name set by you in the program. 

eg: a = ADC;    or  return ADC;

      b = ADCL;  or return ADCL;

      c = ADCH;  or return ADCH;

The result of conversion of ADC is 10 bit resolution. i.e. it varies from 0000 to 1023.

If required, the result may be converted to 8 bit resolution by setting bit 5 (ADLAR) in ADMUX register as shown below:

ADLAR_effect_small.jpg

starting the adc:

 

Before starting the Analog to Digital Conversion, the settings as required, as explained above to be processed in the program. Also, bit 7 ,ADEN (ADC enable), should be set (to 1).

Now, to start ADC for every loop, the bit 6 ,ADSC (ADC Start conversion) of ADCSRA should be set to 1.  Then the Analog to Digital Conversion will start. On completion of conversion bit 4, ADIF (ADC Interrupt Flag) of ADCSRA will be set (to 1) and also ADSC will be reset (to 0).  So, by checking the status of ADIF or ADSC bit in ADCSRA register, you will come to know the conversion status.

Example code for adc:

//=================================================

void initializeAdc (  )
{

    //SET DIVISION FACTOR FOR F_CPU TO GET ADC CLOCK FREQUENCY

    ADCSRA |= ( (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) ); 

    //ADPS2 divides by 16.  ADPS1 divides by 4.  ADPS0 divides by 2.

    //SET REFERENCE VOLTAGE SOURCE

    ADCSRA |= ( (1 << REFS1) | (1 << REFS0) ); 

    //set REFS1,REFS0 = 0,0 for Reference at AREF pin.

    // 0,1 for AVCC as Reference. 1,1 for Internal Reference Voltage.

    // ENABLE ADC
    ADCSRA |= (1 << ADEN); 

}

//=================================================
int readAdc ( int channelno ) 
{

    // reset previous channel number upto 8 channels, if any.

    ADMUX &= (0b11111000);  

    // select current Channel number to read ADC.

    ADMUX = (channelno);  
    

    // START conversion now.
    ADCSRA |= (1 << ADSC);

    

    // WAIT till conversion is complete
    while (ADCSRA & (1 << ADSC));

    // READ ADC value and return the function.

    return ADC;
}

//=================================================

Note:

This is a general concept of ADC conversion in AVR micro controllers. Some small changes may be observed for each AVR micro-controller, which may be obtained from the data sheet specific to the micro-controller.

eg:for ATTINY micro-controllers have only 4 ADC channels and only two options for reference voltage selection. REFS0=0 means Vcc or REFS0=1 means 1.1V internal Voltage Reference. REFS1 is not available.

More controls are available while reading ADC of AVR micro controller.  The specific ADC usage is available in programs and explained the specific concept and usage in the project.