ADC Conversion Time of ATmega328 of Arduino UNO

The purpose of this post is to understand few statements of the ATmega328 data sheet in connection with ADC Module against Experimental Data

1. With regards to ADC Module of ATmega328, the data sheet says:

(a) The first conversion after the ADC is switched on (i.e., ADCSRA.ADEN is written to 1)
takes 25 ADC clock cycles in order to initialize the analog circuitry (Figure 28-4).

(b) Remark: In Figure 28-4, we observe that following the ADC Start
Command, 13.5 ADC Clock Cycles are spent to arrive up to the point of Sample-Hold. There
remains 25.0 - 13.5 = 11.5 cycles. The ADC is a SAR-type 10-bit converter. Assuming that the
input is of any part of Full Scale, the ADC will start from Vref/2 (1000 0000 00) and then manipulate
this number as needed until match occurs with the input analog voltage.

(c) Let us review the working principle of SAR-type A/D converter before we conclude on how many more clkADC pulses (10 or 11.5) would be required to finish conversion.

(d) In SAR method of 10-bit A/D conversion, there are 10 binary-weighted blocks 512, 256, 128, 64, 32, 16, 8, 4, 2, and 1. The MS-block of 512 is tried first. If it is too high than the input voltage, it is set aside and a 0 is recorded for bit-9 position. Then the next MS-block is tried. If adding a block does not make the intermediate result higher than the input, then a 1 is recorded for that bit. Each block is tried only for once. When all the blocks have been tried, the result is a 10-bit binary for the input voltage.

(e) Let us apply the above conversion principle to the 10-bit SAR-type ADC of the ATmega328. Assume input voltage is 3.78V with Vref = 5V. Expected binary is 11 0000 0101.

clkADC Tried value Remark Partial Binary Result
1 1000 0000 00 Vdac < Vin 1000 0000 00
2 1100 0000 00 Vdac < Vin 1100 0000 00
3 1110 0000 00 Vdac > Vin 1100 0000 00
4 1101 0000 00 Vdac > Vin 1100 0000 00
5 1100 1000 00 Vdac > Vin 1100 0000 00
6 1100 0100 00 Vdac > Vin 1100 0000 00
7 1100 0010 00 Vdac > Vin 1100 0000 00
8 1100 0001 00 Vdac < Vin 1100 0001 00
9 1100 0001 10 Vdac > Vin 1100 0001 00
10 1100 0001 11 Vdac < Vin 1100 0001 01 = Final Binary Result

We observe that 10 more clkADC pulses are enough to finish the conversion! As a result, the net conversion time is 10+1.5 = 11.5 clkADC. But, the data sheet (Figure 28-4, 28-5) and Experimental Data Sheet (Section-5) clearly show that the conversion has taken in 13 clkADC. We may naturally ask, for the shake of better understanding, where does the ATmega328 ADC use the extra 1.5 cycle time?

(f) Normal conversion, after the conversion of Section-1(a), takes 13 ADC clock cycles (Figure 28-5).

(g) By default, the successive approximation circuitry requires input clock frequency between 50 kHz
and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input
clock frequency to the ADC can be higher than 200 kHz to get higher sample rate. The Arduino setting for clkADC is 125 kHz.

(h) 13 - 260 us conversion time

(i) Remark:
Assuming clkADC 50 kHz, the normal conversion time: 1/50000 * 13 = 260 us

Assuming clkADC 200 kHz, the normal conversion time: 1/200000 * 13 = 65 us

Assuming standard clkADC 125 kHz, the normal conversion time: 104 us. We have
experimentally seen by reading the content of ADCSRA-register that the analogRead(AX)
function uses 125 kHz as clkADC.

How to explain the figure 13 us as mentioned in the data sheet? To achieve a normal conversion
time of 13 us, we need to use clkADC of 1 MHz (1/1000000 * 13 = 13 us) which Atmel does not
recommend!

2. We have done some measurements based on the following setup of Section-4. The experimental data establishes propositions of Section-1(a) and Section-1(b). We could not correlate experimental data with the statement of Section-1(c). Forum members may interpret the presented data and explain the meaning of the statement of Section-1(c).

3. Queries as to Section-1(g):
(a) Why is the restriction of 50 kHZ to 200 kHz. The experimental data of Section-5 shows that the
ADC is quite well converting data with clkADC from 1 MHz 500 kHz to 488 Hz!

(b) What is the meaning of maximum resolution? The experimental data of Section-6 shows that the
resolution (Volt for the LS-bit) remains the same for all permissible clkADC.

(c) What does it mean: Lower resolution than 10-bit. The experimental data of Section-6 shows that
the converted data remains in the domain of 10-bit for all permissible clkADC.

4. The Hardware and Software Flow Chart Setup

5. The Experimental Data Sheet (attachment: ADCConvert.doc)

6. The Arduino IDE Codes (Tested) engaged for the collection of data of Step-5 (attachment: P2410).

(a) After ADC is started, the Timer-1 is made ON to count high resolution (16 MHz) pulses from the
internal oscillator and continues counting until the conversion is completed. The content of CNT1
is proportional to the very first conversion time of the input analog signal. The content is shown on
LCD TopLeft. Later on, it is converted to clkADC manually and is recorded in the Table of Section-5.

Similarly, the proportional count of conversion time for the next normal conversion is presented
on LCD TopRight.

(b) The ADC value for the first conversion is presented on LCD BottomLeft. The ADC value for
the next normal conversion is shown on LCD BottomRight.

(c) The clkADC is changed by manipulating the value of CLKPR- and ADCSRA-registers.

(d) The following codes are one-to-one representation of the Flow Chart of Section-4.

(e) The conversion time of the ADC can not be measured using analogRead(AX) function as we
have no idea when this function is activating the 'ADC Start Bit, ADSC' and polling the
'End-of-Conversion Bit, ADIF'.

#include <LiquidCrystal.h>
LiquidCrystal lcd(5, A0, A1, A2, A3, A4);


void  setup()
    {
      
       lcd.begin(16, 2);                    //16 charcaters 2 lines LCD
       //  pinMode(13, OUTPUT);

       CLKPR = 0x80;      // data to enable write into CLKPR register
       CLKPR = 0x00 ;     //data to select clock: clkSYS = 16 MHz
    
      //Timer-1 as an Internal Pulse Counter----
      TCCR1A = 0x00;   //Normal UpCounting Mode
      TCCR1B = 0x00;  //T1 is OFF
      TCNT1 = 0x00;   //Initial Value
     
      bitClear(PRR, 0);            //5V is connected to ADC module 
      ADCSRA = 0x97;                //   125 KHz clkADC
      ADMUX = 0x45;                 //    Vref= 5V, Ch5


      bitWrite(ADCSRA, 6, HIGH);          // ADC is started bd ADSC
      TCCR1B = 0x01;                         // Timer-1 is made ON running at 16 MHz
      while (bitRead(ADCSRA, 4) != HIGH)  //Checking EOC by sensing ADIF
        ;
      TCCR1B = 0x00;          //Stop T1
      lcd.setCursor(0, 0);     //Cursor at TopLeft
      lcd.print(TCNT1, 10);   //LCD shows ADC conversion time as Count of 16 MHZ T1's clock
                                     // the count is converted to clkADC in Section-5  
  
      bitWrite(ADCSRA, 4, HIGH);          //ADIF-bit is cleared by putting LH

      int x1 = ADCL;                      // redaing ADC lower 8-bit first
      int x2 = ADCH;

      x2 = x2<<8;
      x2 = x2 | x1;

      lcd.setCursor(0, 1);              //ADC value during first conversion    
      lcd.print(x2, 16);
  
//---- Normal conversion----------    
       TCNT1 = 0x00;

        bitWrite(ADCSRA, 6, HIGH);                //ADC is started bd ADSC
        TCCR1B = 0x01;                              // running at 16 MHz
        while (bitRead(ADCSRA, 4) != HIGH)  //Checking EOC by sensing ADIF
           ;
        TCCR1B = 0x00;                              //Stop T1
        lcd.setCursor(12, 0);
        lcd.print(TCNT1, 10);                        //showing conversion of of normal conversion as counts  
        bitWrite(ADCSRA, 4, HIGH);              //ADIF-bit is cleared by putting LH

        x1 = ADCL;                      
        x2 = ADCH;

        x2 = x2<<8;
        x2 = x2|x1;
        lcd.setCursor(12, 1);
        lcd.print(x2, 16);               //shows ADC value of normal conversion
 
}  

void loop()
{
  
}

ADCConvert.doc (43 KB)

P2410.ino (3.08 KB)