Lecture 6’s sequence
6.1 Introduction to ADC
6.2 ADC in ATmega16
Review of C Programming
Introduction to A-to-D conversion
▪ An ADC samples an analogue signal at discrete times and converts the sampled
signal to digital form.
▪ Used with transducers, ADCs allow us to monitor real-world inputs and
perform control operations based on these inputs.
▪ Many dedicated ICs are made for ADC, e.g.
❑ ADC0804: 8-bit, successive approximation.
❑ Maxim104: 8-bit, flash type.
A-to-D conversion: Typical embedded application
A-to-D conversion: Example applications
▪ Local positioning sensor for object tracking
❑ Measure the distance b/t FM transmitter and receiver
❑ The receiver has Receiver Signal Strength Indicator (RSSI)
❑ The RSSI voltage is inversely proportional to the squared distance
▪ Temperature sensor for shower water
❑ Measure the temperature of shower water
❑ Use a thermistor as sensor
❑ Control hot/cold water valves
A-to-D conversion: Example applications
▪ Obstacle sensor & audio cues in the cane for the blind
❑ Measure distance to nearest object with an ultrasonic sensor
❑ The sensor output is digitized using the ADC
▪ Electric fence monitoring
❑ Determine if an electric fence is being tampered
❑ Measure the voltage level of an electric fence
A-to-D conversion: Example applications
▪ Wireless irrigation system
❑ Measure soil moisture using a resistor and an ADC
❑ Turn ON or OFF the sprinklers
❑ Transmit data wirelessly to base station
▪ Intelligent clothesline
❑ Use sensors to measure humidity, temperature, and wind speed
❑ Open/close the clothesline cover to protect against rain
Lecture 6’s sequence
6.1 Introduction to ADC
6.2 ADC in ATmega16
6.2. The ADC in ATmega16
▪ The ADC in ATmega16 has a 10-bit resolution:
❑ The digital output has n = 10 bits
▪ The ADC has 8 input channels:
❑ Analog input can come from 8 different sources
❑ However, it performs conversion on only one channel at a time
▪ If default reference voltage Vref = 5V is used:
❑ step size: 5(V)/1024 (steps) = ± 4.88mV
❑ Error range: = ± 4.88mV (not half of step)
▪ The clock rate of the ADC can be different from the CPU clock rate:
❑ One ADC conversion takes 13 ADC clock cycles
❑ An ADC pre-scaler will decide the actual ADC clock rate
ADC unit ─ Relevant pins
8 ADC
input pins
External Vref
Supply voltage to
ADC and Port A
ATmega16 chip
ADC unit ─ Block diagram
ADCCSRA to configure
the ADC unit
ADCMUX to select
the input source
ADCH/ACHL register
to store digital output
8 analog
input pins
ADC Multiplexer Selection Register (ADCMUX)
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
MUX4-0: Select analog channel and gain
ADC Left Adjust Result: 1 to left adjust the ADC result
Reference Selection bits: To select reference voltage
▪ Reference voltage Vref can be selected among 3 choices [Slide 14]
▪ Analog input voltage can be selected among 8 pins
Differential input and custom gain factor can also be chosen [Slide 15]
▪ ADLAR flag determines how the 10-bit digital output is stored in output register [Slide 16]
Selecting reference voltage Vref
Table 6.1: ADC reference voltage selection
REFS1 REFS0 Voltage Reference Selection
0 0 AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
Internal 2.56V voltage reference with external
1 1
capacitor at AREF pin
▪ Usually, mode 01 is used: AVCC = 5V as reference voltage
▪ If the input voltage has a different dynamic range, we can use mode 00 to select an
external reference voltage
Selecting input source and gain factor
Table 6.2: ADC input source
Choices of analogue input voltage:
▪ 8 ADC pins (ADC0 to ADC0)
▪ Differential between 2 ADC pins
▪ Different gain factors (1, 10, 200)
ADC Left Adjust flag and ADCH/L registers
When bit ADLAR = 0 (Right Aligned)
# # # # # # ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0
ADCH ADCL
When bit ADLAR = 1 (Left Aligned)
ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0 # # # # # #
ADCH ADCL
▪ Digital output is stored in two 8-bit registers ADCH and ADCL
▪ The format of ADCH and ADCL depends on flag ADLAR
▪ Important: When retrieving digital output, ADCL must be read first ADCH
ADC Control and Status Register (ADCSRA)
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
ADC Pre-scaler Select bits: next slide
ADC Interrupt Enable: 1 to enable ADC interrupt
ADC Interrupt Flag: set to 1 when conversion is completed
ADC Auto Trigger Enable: 1 to enable auto-triggering of ADC by certain events
ADC Start Conversion: 1 to start conversion
ADC Enable: 1 to enable the ADC unit
▪ ADC unit can operate in two modes: manual or auto-trigger
▪ In manual mode, setting flag ADSC = 1 will start the conversion. When conversion is
completed, flag ADSC = 0 automatically
▪ In auto-trigger mode, a predefined event will start conversion
ADC clock
Table 6.3: ADC Pre-scaler Selection
ADPS2 ADPS1 ADPS0 Division Factor
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
▪ The ADC clock is obtained by dividing the CPU clock and a division factor
▪ There are 8 possible division factors, decided by the 3 bits {ADPS2, ADPS1, ADPS0}
▪ Example: Using internal clock of 1Mz and ADC pre-scaler bits of ‘011’, one ADC clock cycle = 8 x CPU
clock cycle = 8 µs
Special Function IO Register (SFIOR)
ADC Auto Trigger Source
ADTS2 ADTS1 ADTS0 - ACME PUD PSR2 PSR10
Table 6.4: ADC Auto Trigger Source
ADTS2 ADTS1 ADTS0 Trigger Source
0 0 0 Free Running mode
0 0 1 Analog Comparator
0 1 0 External Interrupt Request
0 1 1 Timer/Counter0 Compare Match
1 0 0 Timer/Counter0 Overflow
1 0 1 Timer/Counter1 Compare Match B
1 1 0 Timer/Counter1 Overflow
1 1 1 Timer/Counter1 Capture Event
▪ Three flags in register SFIOR specify the event that will auto-trigger an A-to-D conversion
Steps to use the ADC
▪ Step 1: Configure the ADC using registers ADMUX, ADCSRA, SFIOR
❑ What is the ADC source?
❑ What reference voltage to use?
❑ Align left or right the result in {ADCH, ADCL}?
❑ Enable or disable ADC auto-trigger?
❑ Enable or disable ADC interrupt?
❑ What is the ADC pre-scaler?
▪ Step 2: Start ADC operation
❑ Write 1 to flag ADSC (register ADCSRA)
▪ Step 3: Extract ADC result
❑ Wait until flag ADSC becomes 0
❑ Read result from registers ADCL and then ADCH
Example 1: Performing ADC
Write C program that repeatedly performs ADC on a sinusoidal signal
and displays the result on LEDs.
▪ Step 1: Configure the ADC
❑ What is the ADC source? ADC0 (pin A.0)
❑ What reference voltage to use? AVCC = 5V
❑ Align left, or right? Left (top 8-bit in ADCH)
❑ Enable or disable ADC auto-trigger? Disable
❑ Enable or disable ADC interrupt? Disable
❑ What is the ADC pre-scaler? 2 (fastest, selector 001)
Example 1: Performing ADC
▪ Step 1: Configure the ADC
0 1 1 0 0 0 0 0
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0 ADCMUX
1 0 0 0 0 0 0 1
ADEN ADSC ADATE ADIF ADIE ADPS2 ASPS1 ADPS0 ADCSRA
▪ Steps 2 and 3: Show next in the C program
Example 6.1: Programming
#include <avr/io.h>
int main (void){
unsigned char result;
DDRB = 0xFF; // set port B for output
// Configure the ADC module of the ATmega16
ADMUX = 0b01100000; // REFS1:0 = 01 -> AVCC = 5v as reference,
// ADLAR = 1 -> Left adjust,
// MUX4:0 = 00000 -> ADC0 as input,
ADCSRA = 0b10000001; // ADEN = 1: enable ADC,,
// ADSC = 0: don't start conversion yet,
1
// ADATE = 0: disable auto trigger,
// ADIE = 0: disable ADC interrupt,
// ASPS2:0 = 001: ADC prescaler = 2.
while(1){ // main loop
ADCSRA |= 0b01000000; // Start conversion by setting flag ADSC 2
while (ADCSRA & 0b01000000){;} // Wait until conversion is completed
result = ADCH; // Read the top 8 bits, output to PORTB 3
PORTB = ~result; // Port B connected to LEDs (0 = ON, 1 = OFF)
}
return 0;
}
Using ADC interrupt
▪ In the polling approach shown previously, we must check ADSC flag to know
when an ADC operation is completed
▪ Alternatively, the ADC unit can trigger an interrupt when ADC is done
▪ We enable ADC interrupt through ADIE flag in register ADCSRA
▪ In the ISR, we can write code to read registers ADCL and ADCH
▪ ADC interrupt is usually combined with auto-trigger mode [Tutorial 05]
Example 2: ADC interrupt
Write interrupt-driven program to digitize a sinusoidal signal and
display the result on LEDs.
▪ Step 1: Configure the ADC
❑ What is the ADC source? ADC0
❑ What reference voltage to use? AVCC = 5V
❑ Align left, or right? Left (top 8-bit in ADCH)
❑ Enable or disable ADC auto-trigger? Disable
❑ Enable or disable ADC interrupt? Enable
❑ What is the ADC pre-scaler? 2 (fastest conversion)
▪ Step 2: Start ADC operation (set ADSC flag = 1)
▪ Step 3: In ISR, read and store ADC result in a global variable
Example 2: Programming
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0 ADCMUX
#include<avr/io.h>
0 1 1 0 0 0 0 1
#include<avr/interrupt.h>
ADEN ADSC ADATE ADIF ADIE ADPS2 ASPS1 ADPS0 ADCSRA
volatile unsigned char result;
1 0 0 0 1 0 0 1
ISR(ADC_vect){
}
result = ADCH; // Read the top 8 bits, and store in variable result
3
int main (void){
DDRB = 0xFF; // set port B for output
// Configure the ADC module of the ATmega16
ADMUX = 0b01100000; // REFS1:0 = 01 -> AVCC as reference,
// ADLAR = 1 -> L ft dj t eft adjust
// MUX4:0 = 00000 -> ADC0 as input
ADCSRA = 0b10001001; // ADEN = 1: enable ADC,
// ADSC = 0: don't start conversion yet
//
//
ADATE = 0: diable auto trigger,
ADIE = 1: enable ADC interrupt,
1
// ASPS2:0 = 002: pre-scaler = 2
sei(); // enable interrupt system globally
while(1){ // main loop
ADCSRA |= 0b01000000; // start a conversion
PORTB = ~result; // display on port B 2
}
return 0;
}