Tuesday, August 19, 2014

AVR Tutorial - ADC (Analog to Digital Converter)

ADC as you can guess converts analog voltage to digital number, so we could work with it in microcontroller. We can build simple ADC with comparator, it's a device which compares 2 signals (1 of them is some constant reference voltage) gives one otput if 1 signal is bigger and other if smaller.

ADC accuracy depends on it's resolution. e.g. if we have reference voltage = 5 V and our ADC is 10-bit, then on every bit we have 5 / ( 2^10 - 1 ) = 0.00489 or 5 mV, so we can't measure changes less than 5 mV.
To configure ADC we use ADSCRA register
7 ADEN enable ADC
1 ON  
0 OFF

6 ADSC runs ADC, if we configure ADC to run only 1 time then we need to write here 1, after ADC ends calculations this bit will be cleared and we have to change it again if we want to run ADC again.

5 ADFR choose ADC working mode
0 – trigger ADSC manually
1 – auto triggering (it runs endlessly, 1 is always written in ADSC)

4 ADIF This bit is set when an ADC conversion completes and the Data Registers are updated.

3 ADIE Interrupts
0 – Disable
1 – Enable

2 1 0 ADPS ADC frequency
CK = MC frequency

000         СК/2
001         СК/2
010         СК/4
011         СК/8
100         СК/16
101         СК/32
110         СК/64
111         СК/128


ADMUX register is responsible for choosing input pin and reference voltage.
7-6 REFS These bits select the voltage reference for the ADC.
00  AREF
01  AVCC with external capacitor at AREF pin
10  Reserved
11  Internal 2.56V Voltage Reference with external capacitor at AREF pin

5 ADLAR determines how ADC conversion result will be written in data register. We have 10-bit ADC, so we need to use 2 8-bit registers.





4-0 MUX The value of these bits selects which combination of analog inputs are connected to the ADC. (ATmega8)
0000      ADC0
0001      ADC1
0010      ADC2
0011      ADC3
0100      ADC4
0101      ADC5
0110      ADC6
0111      ADC7


Working proteus project

#include <avr io.h>
#include <avr interrupt.h>

//Configure interrupt
ISR(ADC_vect)
{    
 unsigned int ADCdata, voltage_0, voltage, voltage_2, voltage_3;
 ADCdata = ADCW; // ADCW keeps our ADC result value (16 bit)
 voltage_0 = ADCdata * 48875 / 10000; // 5 вольт / 1023 = 4.8875
 voltage = voltage_0 % 10000 / 1000;  
 voltage_2 = voltage_0 % 1000 / 100;
 voltage_3 = voltage_0 % 100 / 10;


 PORTC = voltage;
 PORTD = voltage_2;
 PORTB = voltage_3;

 ADCSRA = ADCSRA | 0x40;// Start Conversion 0b01000000
}

int main (void)
{
 DDRB = 0xFF;
 DDRD = 0xFF;
 DDRC = 0xFF;
 ADMUX = 0x00; // PA0
 ADCSRA = 0b11001110; 

 PORTB = 0x00;
 PORTD = 0x00;
 PORTC = 0x00;
 
 sei();
 while(1); 
}
Circuit:


Applying voltage on PA0. After that convert it in to digital value and display information on displays, Port B == ones, Port C == tenths, Port D == hundreths. So we have 2.35 V.

We get information about voltage from ADCW (it automaticly reads 2 bytes from ADC registers). I configured ADC to take reference voltage from AVCC, when we have 5 V on pin, ADCW value will be 2^10-1 = 1023.

Now we use formule:
Volts = ADCW * reference voltage / resolution
In our case:
5 / 1023 = 0.0048876
1 bit == 0.0048876 V

It's better to use integrers then fractions.
0.0048876 = 48876 / 10000000

I need mV to be integrer, that's why i will 5 multiply by 1000.

5000 / 1023 = 4.8875 = 48875 / 10000

Now 1 bit == 4 mV. (int's are not rounded)

In the end we have:

unsigned int ADCdata
ADCdata = ADCW
voltage_0 = ADCW * 48875 / 10000

So in our variable we have a four-digit number which represents mV. e.g. 3524 == 3.524 V.
Now we just need to get every part seperatly.

voltage = voltage_0 % 10000 / 1000
voltage_0 is our four-digit number.

We take from that remainder when divided by 10000, we would get 3524, after that divide it by 1000, now we get 3.
voltage == 3.
write that in corresponding port and repeat the process with tenths and hundredths

Information:
samou4ka.net
avrlab.com
chipenable.ru
radioparty.ru
my-avr.at.ua
myrobot.ru
avr-tutorials.com
Book: "Шпак Ю.А. - Программирование на языке C для AVR и PIC"

No comments :

Post a Comment