3.3. Analog to Digital Converter (ADC)

An ADC is a simple electronic system or a module that has analog input, reference voltage input and digital outputs. The ADC translates the analog input signal to a digital output value that represents the size of the analog input relative to the reference voltage. It basically samples the input analog voltage and produces an output digital code for each sample taken[2].

The world is full of analogue signals: light, sound, heat; they represent a continuous specter of values. Microcontrollers “perceive” these signals through sensors, but information has to be stored and processed on the microcontroller in a digital way. The Analog to Digital Converter measures the voltage of these continuous signals and compares them to a reference voltage in order to produce a digital input for the microcontroller. The resolution of the result is given by the resolution of the ADC. The ATmega328P has a 10-bit ADC, which means that the result of the conversion will be stored in 10 bits. This, in turn, means that this ADC can supply as output 210 = 1024 different values.

A conversion mode is a method in which the ADC processes the input and performs the conversion operation. A standard ADC has basically two types of conversion modes[2]:

  1. Single ended conversion mode.
  2. Differential conversion mode.

In single ended conversion, only one analog input is taken and the ADC sampling and conversion is done for that input. This is the mode that we will be using throughout this workshop.

Another important ADC parameter is the sampling rate. The higher the sampling rate, the better we can reconstruct the sampled signal. Changing the sampling rate is done with the help of a prescaler in the same manner as we have seen in the 2.11. Timers section. In Figure 1 you can see how undersampling affects the quality of the reconstructed signal.

Figure 1. Accuracy loss when reconstructing a signal from samples.

But what is the minimum sampling rate necessary to reproduce without losing accuracy a signal of a given frequency? Nyquist's theorem states that the sampling rate should be at least double the frequency of the measured signal. This applies in various situations; for instance, voice sampling during a phone conversation has to be reproduced accurately so the other person can understand what you are saying or even recognize your voice.

After the conversion is complete, the conversion result can be found in the ADC Result Registers. For single ended conversion, the result is where VIN is the voltage on the selected input pin and VREF the selected voltage reference[1].

The analog input channel is selected by writing to the MUX bits in ADMUX. Any of the ADC input pins, as well as GND and a fixed bandgap voltage reference, can be selected as single ended inputs to the ADC[1].

The ADC generates a 10-bit result which is presented in the ADC Data Registers, ADCH and ADCL. By default, the result is presented right adjusted, but can optionally be presented left adjusted by setting the ADLAR bit in ADMUX[1].

If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is read, neither register is updated and the result from the conversion is lost. When ADCH is read, ADC access to the ADCH and ADCL Registers is re-enabled[1].

Advanced: What if you need a higher resolution? Oversampling provides a way of increasing the resolution of the ADC. For example, to implement a 14-bit converter, it is enough to have a 10-bit converter which can run at 256 times the target sampling rate. Averaging a group of 256 consecutive 10-bit samples adds four bits to the resolution of the average, producing a single sample with 14-bit resolution. The number of samples required to get additional n bits is equal to 22n.

Pseudocode

To initialize ADC:

  1. Enable ADC (ADEN bit in ADCSRA register)
  2. Choose single-conversion or auto-trigger (ADATE bit in ADCSRA register)
  3. Set the clock prescaler (ADPS[2:0] bits in ADCSRA register)
  4. Choose the voltage reference (REFS[1:0] bits in ADMUX register)
  5. Choose left or right adjustment of result (ADLAR bit in ADMUX register)
  6. Choose the AD channel to convert (MUX[3:0] bits in ADMUX register)

To do a conversion:

  1. Start a conversion (ADSC bit in ADCSRA)
  2. Wait until conversion is complete (ADIF bit in ADCSRA). You can:
      - Monitor the ADIF bit in ADCSRA, or
      - Generate an interrupt

To use interrupts:

  1. Enable global interrupts: sei();
  2. Activate the ADC Conversion Complete Interrupt (ADIE bit of ADCSRA register)
  3. Define an interrupt handling routine. The interrupt handling routine call will automatically clear the ADIF flag.
      - Don't forget about the interrupt header: #include <avr/interrupt.h>
      - The parameter to the ISR is ADC_vect.

To read data from the ADC data register:

  - If you have 10-bit precision: ADCL has to be read first, then ADCH. 
       - Note that access to the ADC data register is blocked until both ADCL and ADCH are read. Once ADCH is read, the ADC data register can be updated.
  - If the result is right-adjusted, you can just read the whole ADC register.
  - If the result is right-shifted and you only need 8-bit precision you can just use ADCL.
  - If the result is left-shifted and you only need 8-bit precision you can just use ADCH.

Bibliography

Resources

roboticsisfun/chapter3/ch3_3_adc.txt · Last modified: 2012/10/28 20:16 by liana.marinescu