Go Down

Topic: Organisation Interfacing and Programming of ADC Module of ATmega328 MCU (Read 3066 times)previous topic - next topic

GolamMostafa

May 31, 2017, 01:44 amLast Edit: Jul 15, 2020, 08:51 am by GolamMostafa
4.1 Organisation of Analog-to-Digital Converter Module

(1) The ATmega328 contains a built-in SAR (successive approximation register)-type multi-channel analog-to-digital converter of which only 6-channels (Ch0 - Ch5) are available to acquire external signals via APin (analog pin connector: A0 - A5) connector of the Arduino UNO Learning Kit. Ch8, Ch14, and Ch15 are internally connected to 'Temperature Sensor, TS', 0V and 1.1 V respectively. The desired channel is selected with the help of ADMUX (ADC Multiplexer Register).

(2) The Conceptual View of the ADC Module is given below in Fig-4.1.

Figure-4.1: Conceptual View of the ADC module of ATmega328 Microcontroller

(3) For this MCU, the input voltage to an external channel must be equal or less than the voltage connected at the VREF point of the ADC. The ADC can receive its VREF voltage from three sources: External 5V (AVcc = Analog Voltage), Internal 1.1 V (VBG = Band Gap Voltage), and External Variable Voltage (AREF = 0 to 5V). The usual voltage (default) of the reference point is 5V. We must use 1.1V as VREF while measuring the signals of Ch8, Ch14, and Ch15.

A warning, extracted from the Arduino Language Reference Manual, is worth to mention: While connecting VREF point to the external AREF-point, the voltage at the AREF point must not be less that 0V or higher than 5V; otherwise, the MCU will possibly be damaged. The VREF voltage selection is made via ADMUX register.

(4) Full Scale (FS) of an ADC: It is the maximum analog input voltage for which all the output bits (B0 - B9) will assume LH states.

(a) Assume FS = 5V = 5000 mV.
(b) When Vin = 5000 mV, the output = 1111111111 (1023) = 210-1 = 2n - 1
(c) Resolution = 5000 mV/1023 = 4.8875 mV for the LS-Bit of the output.
(d) Better resolution ADC means: lesser mV for the LS-Bit of the output.
(e) According to data sheets, the Resolution: 5000 mV/10n = 5000/1024 = 4.8821 mV.

(6) The following conditions are to be satisfied to transform a port pin of PORTC into an analog channel for the ADC.
(a) LL must be written into Bit-0 of the PRR (Power Reduction Register).
Status Register A). Division factor in the ADC Clock Prescaler should also be set as needed
using ADCSRA-register. The directions of the port pins of PORTC are automatically configured
as inputs.
(c) VREF voltage for the ADC and analog channel selection (which channel to acquire) are to be
done with the help of ADMUX-register.
conversion time of the ADC : 13 µs - 260 µs.

(7) End-of-Conversion (EOC) is detected in the following ways:
(a) By polling the ADSC bit of ADCSRA and checking that it has assumed LL-state. As long as the
conversion is going on, the ADSC bit remains at LH state. At the end-of-conversion ADSC
assumes LL state.
(b) By polling the ADIF bit of ADCSRA and checking that it has assumed LH-state. As long as the
conversion is going on, the ADIF bit remains at LL state. At the end-of-conversion, ADIF assumes
LH state. If interrupt is made active by enabling the I-bit of SREG and ADIE-bit of ADCSRA, this
ADIF-bit will interrupt the MCU notifying the end-of-conversion. The ADIF is automatically
cleared when the MCU vectors to ISR (Interrupt Sub Routine) at location 002Ah. If EOC is
detected by polling the ADIF, the ADIF bit must be cleared manually by writing LH at this bit

(8) After the conversion, the 10-bit ADC data is available in the following two registers:
(a) ADCL [0:7] : ADC Data Register Low (It contains lower 8-bit).
(b) ADCH [8:15] : ADC Data Register High (Bit-8, 9 are the part of ADC result; the remaining 6-bit
(Bit-10 to Bit-15 are always 0s.).

(9) IO Registers involved in the ADC Operation:
(f) PRR : Power Deduction Register Power Reduction Register
(g) CLKPR: System Clock Prescaler Register

AWOL

It's a "Power Reduction Register"

GolamMostafa

It came well in Step-6, but it failed in Step-9.

Thanks,

GolamMostafa

#3
Jun 02, 2017, 08:15 pmLast Edit: Jun 03, 2017, 06:46 pm by GolamMostafa
4.2 Interfacing and Programming of ADC in Single Conversion Mode

Figure-4.2: Interfacing and programming of ADC module

In this section, we will develop setup and program codes for the functional check of the ADC module of the ATmega328 Microcontroller. The Test Bench is the 'Arduino UNO Learning Kit and its associated IDE Interface.' A functional check is usually carried out in the following way: a known voltage (the excitation) is injected at the input; proportional known output (the response) is observed. In the present case, we will apply 1.67V, 3.33V, and 5.00V from the voltage divider into Ch5; proportional known output 0156h, 02A9h, and 03FFh are expected to appear on the LCD. During this operational check, we will be familiar with the procedures of putting the ADC into operation. The EOC would be sensed by polling the ADIF-bit of the ADCSRA-register.

(1)  Refer to Fig-4.2, let us build a voltage divider (R1-R2-R3) circuit on the breadboard; connect the P-point voltage (1.67V) with A5-pin (Ch5 of the ADC) of the Arduino Kit.

(2)  Place a LCD display unit (2-Line 16-Character) on the breadboard as per Fig-4.2, and connect it with the ATmega328 MCU using the APin/DPin connectors of the Arduino.

(3)  Let us carry out initialization tasks as needed before putting the ADC into 'Single Conversion Mode.' As the input signal is a constant value, we may sample it in every 3-sec interval by calling the delay (3000) function of the Arduino IDE.

In single conversion mode, the ADC is started for once; wait until the conversion is complete by polling the ADIF-bit; read the ADCL and ADCH data. The ADC is not automatically started for the next time. The procedures for single conversion mode are:

L1. LL  PRADC bit of PRR-register :  ADC is connected with 5V

L3.  [0, 1]  [REFS1, REFS0] of ADMUX : VREF of ADC is AVcc (+5V)
[0, 1, 0, 1]  [MUX3:MUX0] : ADC Channel-5 is selected

L5.  Wait here until conversion is complete by polling ADSC-bit or ADIF-bit.

(4)  Assembly Codes for the instructions of Step-3 (tested using RMCKIT/AVR Studio 4)
Code: [Select]
`           .org 0x0040 START: nop L1:      ldi r16, 0x00           out PRR, r16              ; 5V supply is connected to all IO modules including ADC L2:      ldi r16,  0x93             ; 10010011  clkADC = 138.24 KHz           out ADCSRA, r16 L3:      ldi r16, 0x45   ; 0100 0101 Ch5           out ADMUX, r16 L4:      in r16, ADCSRA           ori r16, 0x40 ; 0100 0000 ADC is started           out ADCSRA, r16 L5:      in r16, ADCSRA ; polling the ADIF bit for LH to sense End-of-Conversion            rol r16           rol r16           rol r16           rol r16           brcc L5 L6:      in r16, ADCSRA           out ADCSRA, r16 ; ADIF flag is cleared by writing LH at ADIF-bit L7:      in r16, ADCL           in r17, ADCH ; ADC value in <r17 r16>.`

P425 (5) Arduino IDE Codes for the instructions of Step-3/4 (tested using Arduino)
Code: [Select]
`#include <LiquidCrystal.h>//LiquidCrystal lcd(RS, E, D4, D5, D6, D7);LiquidCrystal lcd(5, A0, A1, A2, A3, A4);void  setup(){ lcd.begin(16, 2); lcd.setCursor(0,0);       //DP0 position of Top Line (L0) //-------------------- pinMode(13, OUTPUT);        // Labels correspond to Step-3 bitClear(PRR, 0);           //L1: ADCSRA = 0x97;             //L2: clkADC = 125 KHz ADMUX = 0x45;               //L3: Ch5 }void loop(){ lcd.clear(); // remove from LCD whatever is there bitWrite(ADCSRA, 6, HIGH);         //L4: ADC is started by ADSC while (bitRead(ADCSRA, 4) != HIGH) //L5: Checking EOC by sensing ADIF   ; bitWrite(ADCSRA, 4, HIGH);         //L6: ADIF-bit is cleared by putting LH int x1 = ADCL;                       //L7: int x2 = ADCH; //L7A: x2 = x2<<8; // L7B: shifting ADCH value to the left by 8-bit x2 = x2 | x1; // L7C: making 16-bit chunk out of ADCH and ADCL digitalWrite(13, !(digitalRead(13))); //Toggling L as an indication that conversion is being taken place lcd.print(x2, 16);                     //ADC value in LCD in Hex format delay(3000);                           //Repeat acquisition at 3-sec interval}  `

P246 (6) Arduino IDE Codes for the instructions of Step-3/4/5 (tested using Arduino)
Code: [Select]
`#include <LiquidCrystal.h>//LiquidCrystal lcd(RS, E, D4, D5, D6, D7);LiquidCrystal lcd(5, A0, A1, A2, A3, A4); //takes care of user connection between LCD and Arduinovoid setup(){analogReference(DEFAULT); //does it cover tasks of L1 - L3 of Step-3?}Void loop(){unsigned int x = analogRead(A5); // does it cover tasks of L4 - L7C of Step-5? //---------------------------digitalWrite(13, !digitalReda(13)); //Toggle L to see that conversion takes placelcd.print(x, 16); //ADC value in LCD in hex formatdelay (3000); //wait for 3-sec and then acquire input signal again}`

(7)     (a) Connect P-point (1.67V) of the voltage divider of Fig-4.2 with Ch5 via  APin-A5.
(b) Compile and upload P246 program of Step-6.
(c) Check that the LCD shows a value: close to: 155h ± 2%
(d) Connect Q-point (3.33V) with Ch5 and check that LCD shows close to 2A7h ± 2%.
(e) Connect 5V-point (5.00V) with Ch5 and check that LCD shows close to 3FFh ± 2%.

P248 (8) Add the following two instructions with P246 just before the delay() function.
lcd.setCursor (0, 1);

Save the new program as P248. Compile and upload the program. Check that the bottom line of the LCD shows: 97h. Consult data sheet of ATmega328 for the ADCSRA-register; decode the number 97h (1001 0111) and find that the clkADC has been set at 125 KHz.

Whandall

(c) Resolution = 5000 mV/1023 = 4.8875 mV for the LS-Bit of the output.
It has to be 1/1024 (4.8828 mV) not 1/1023.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

GolamMostafa

#5
Jun 24, 2017, 07:26 pmLast Edit: Jun 24, 2017, 07:30 pm by GolamMostafa
Quote
It has to be 1/1024 (4.8828 mV) not 1/1023.
A lot of debates happened on this issue! Finally, all parties won the game; both options are acceptable.

1.  One community is saying: 0 to 1023 steps; there are 1024 evels; so, resolution = FS/1024.

2.  Another community is saying: Input 0V            Ouput : 00 0000 0000 = 0 count
Inout 5V (FS)     Output : 11 1111 1111 = 1023 count
So, resolution = volt/LS-count = 5/1023.

3.  %error = (5/1023 - 5/1024)/1023 = (0.0048875 - 0.0048828)/1023 = ~ 0%

However, questions remains as: How both could be right?

Thanks for the feedback.

AWOL

Quote
How both could be right?
The answer is simple - they can't both be correct, obviously.
The correct answer is in the processor datasheet.

GolamMostafa

Quote
The correct answer is in the processor datasheet.
Has Atmel documented all accurate information in the ATmega328 datasheets?

AWOL

Has Atmel documented all accurate information in the ATmega328 datasheets?
Oh dear. This is getting needlessly messianic. (To quote DNA)

GolamMostafa

@AWOL

I am so happy to see that the shining rays of the Muslim Ramadan's Prestigious Night (The Sabe Kadar - the Night better than the thousand nights) have favored your intuition not to cheat your intellect. This is a very rare scenario I will ever remember!

AWOL

I have absolutely no idea what you're wittering on about.

Go Up