Having them integrated into MCUs makes it really easier to use them, we are going to play a bit with the MSP430G2553 ADC10 converter.
The two main control registers to drive the ADC10 are ADC10CTL0 and ADC10CTL1.
Using them we can set the reference voltages, which channel to be sampled, we can turn on and off the reference voltage and the peripheral itself.
The MSP430G2 family is designed to be a low power solution, this is why the peripherals and features that may potentially use some energy are turned off by default.
Finally the sampled result can be easily recovered from the ADC10MEM register :
int mySensor = ADC10MEM;
Sample & Hold and conversion
During the sampling process, I explained in the previous post, a reference voltage is V(t) is compared with the voltage coming from the signal.
If the signal fluctuates in this process, it might be impossible to compare it with the reference.
For this reason a "sample and hold" functionality is implemented, you can see some details here.
This means that the value of the signal to be sampled is maintained constant during the conversion.
from wikipedia
This time is defined by the SHS (Sample and Hold Source) clock which, in the MSP430 can be one of the following :
00 = ADC10SC (ADC10 internal oscillator, about 5MHz and can be divided from 1 to 8)
01 = Timer_A.OUT1
10 = Timer_A.OUT0
11 = Timer_A.OUT2
In this way we basically define the maximum sampling rate which is the result of the sampling time, being the sum of the Sample and Hold phase plus the conversion phase.
from the TI MSP430 User Guide
The conversion part is then executed in 13 ADC10CLK cycles (thanks to a series of approximations performed internally).
Playing a bit with numbers, we can verify that, at a minimum we need 4 + 13 = 17 cycles.
Assuming the ADC10CLK is the 5MHz (note : we should not expect it to be EXACTLY 5MHz, it's a digital oscillator and it might have some tolerance) Internal source
1 cycle = 1 / 5.000.000 s = 200ns
The sampling time is then 17 * 200ns = 3.5us
The sampling time is 1 / 3.5us = roughly 294 Ksps (Kilo Samples Per Second)
Data then needs about 1 or 2 MCLK cycles to be made available in the ADC10MEM register (it uses an internal DMA), so the actual rate is slightly lower and it depends on the CPU frequency.
The data sheet claims a sampling rate exceeding 200 Ksps, which is in line with what we calculated and I believe is pretty good for a 16MHz mcu.
Reference Voltages
The ADC will return 0 if the signal is lower than or equal to the Vref- voltage and will return 1023 if it is higher than or equal to Vref+.
The ADC10 has different options when it comes to Reference voltages, it can use internal precisely generated voltages (1.5V or 2.5V) , it can use Vcc as Vref+ and Vss (Ground) as Vref- or it can get them from two external pins.
All these parameters are controlled via the ADC10CTL0 register.
In the user guide we find :
SREFx Bits 15-13 Select reference.
SREF_0 000 VR+ = VCC and VR- = VSS
SREF_1 001 VR+ = VREF+ and VR- = VSS
SREF_2 010 VR+ = VeREF+ and VR- = VSS. Devices with VeREF+ only.
SREF_3 011 VR+ = Buffered VeREF+ and VR- = VSS. Devices with VeREF+ pin only.
SREF_4 100 VR+ = VCC and VR- = VREF-/ VeREF-. Devices with VeREF- pin only.
SREF_5 101 VR+ = VREF+ and VR- = VREF-/ VeREF-. Devices with VeREF+/- pins only.
SREF_6 110 VR+ = VeREF+ and VR- = VREF-/ VeREF-. Devices with VeREF+/- pins only.
SREF_7 111 VR+ = Buffered VeREF+ and VR- = VREF-/ VeREF-. Devices with VeREF+/- pins only.
The constants SREF_0 to SREF_7 are conveniently defined in the standard .h file.
In the same file we also find the other constants needed to enable the internal reference and to set it to 1.5 or 2.5 V
REF2_5V Reference-generator voltage. REFON must also be set.
0 1.5 V
1 2.5 V
REFON Reference generator on
0 Reference off
1 Reference on
There anyways restrictions on the voltages that can be applied to the analog input (should be between 0 and Vcc) and to the eventual external references :
Vref- (specifically for the 2553, check the DS for other devices) should be between 0 and 1.2V
Vref+ (same considerations) should be between 1.4V and Vcc
This said, if you are planning to sample a higher voltage (I tried with the mains ; 250V AC) you need to use a voltage divider (with offset regulation for AC signals) and to make sure the output of your divider is always in the expected range (check with a scope if you can).
If you don't need to sample with a high frequency and you are using an internal reference, what you may want to do is to turn on and off the internal Vref to reduce power consumption.
There is also an option to burst" it so it turns off and on as needed by the ADC, however you should be aware of the fact that the internal Vref takes a small amount of time to settle, and the sampling can happen only when it is stable.
tref (the time Vref internal needs to settle at 99.9% of its value) is 30us.
Finally, the peripheral can fire an interrupt once the conversion is done, so it's common to start the process, enter in Low Power Mode and then wake up receiving the interrupt, get the value from ADC10MEM, do whatever needed with it and start the process again.
In the next post I will present some sample code using the ADC.