Search Microcontrollers

Sunday, October 28, 2012

MSP430G2 - the ADC10 peripheral /1

In the previous post I illustrated a few basic concepts about Analog to Digital Converters.
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 S&H phase is software selectable  (in ADC10CTL0) in 4,8,16 or 64 ADC10CLK cycles, a higher value would be used to reduce high frequency noise.
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.


Analog to Digital Converters - 1

Analog to Digital converters are, in my opinion, one of the most fun peripheral to deal with when working with Microcontrollers.
Why?
Let's face it : most of the measurements you want to do in the real world involve an analog reading, normally a voltage or a resistance returned by some kind of sensor.

Like most of the mcus, the MSP430G2 has an ADC built in (warning : the ADC10 is not included in all the devices of the family, check the datasheet or the specs for the specific device you are dealing with).
I am going to use the MSP430G2553 supplied with the launchpad and that one definitely has an ADC10 onboard.

First of all, it's called ADC10 because it has 10 bits of resolution.
10 Bits is the typical resolution you can find in "cheap"devices, more advanced ones (such as the C2000 or Cortex M3) may have a 12bit adc instead.

What's the difference?
It's about resolution : a 12 bit device, having 2 bits more, achieves a four (2^2) times higher resolution than a 10 bit one.
It's a big difference, however in many (most?) cases it does not really matter.

Let's imagine you are sampling a temperature from a sensor such as the LM35DZ (cheap and common sensor).
This sensor increases it's output by 10mV for each Centigrade, at 0C it will provide 0V (which makes it really simple to use it with mcus).
However this sensor does not provide high accuracy since it's best accuracy is about +/- 0.5C, which can be translated into +/- 5mV.

A 10 bit adc with range between 0 and 3.3V has a resolution of 3.3 / 1024 V/bit =  3mV/bit which is already higher than the accuracy of the sensor itself, therefore a higher adc resolution would be useless.
However this setup would allow us to measure temperatures between 0 and 33C, which it might be ok for some applications, but not enough for others.
The LM35 sensor itself can read temperatures from -55C to 150C (depending of the exact model, check the datasheet) but this would generate voltages from -5.5V up to 15V.
If you apply such ranges to a 3.3V tolerant ADC, you are likely to burn it, so most people normally regard this a as a bad idea.
You can offset and "scale" the signal using a voltage divider (with 3 resistors in case you need to add the offset), but at that point, should you still aim for +/- 0.5C resolution, the 10 bits are not enough anymore.

The example with the LM35 was useful to add some context, but the issue is generic.
Imagine we have a sensor that measures a quantity X and outputs linearly a voltage V(X) = V0+kX.
The constant k is the voltage gain of the sensor, it is a constant if the sensor output is linear.
The range we want to measure is [Xmin,Xmax], which gives us DX = Xmax-Xmin.
Assuming we can exactly map Xmin to the lower reference of the ADC (i.e. 0V) and Xmax to the higher reference (i.e. 3.3V), and we know we want to obtain a specific resolution R, then we can calculate how many bits (minimum) we need to sample the signal.

Say DX = 100X and the needed resolution R is 0.01X, this means that the ADC must have 100X/0.01X = 10.000 "steps".
To get the minimum number of bits you can apply a log2(10.000) or simply compare with the resolution of finite number of bits :
8 bits -> 256
10 bits -> 1.024
12 bits -> 4.096
14 bits -> 16.384
...

in our case we would need a 14 bit ADC, not an easy requirement as very few of the mcu integrated ADCs can get that precision.
At the same time, when sampling with such accuracy, we might have additional issues such as the stability of the reference voltages, the accuracy of the resistors used in an eventual divider, electronic noise etc.
When higher precision and speed must be achieved, the common solution is to use dedicated ADC devices.

If now you feel frustrated because your mcu only supports a 10 bit sampling device, just think this : precision instruments such as Digital Oscilloscopes use 8 bit ADCs (but they are normally extremely fast and equipped with high precision input circuits).
How do they give all that flexibility and precision with 8 bit only?
They allow to set different scales by altering the offset of the signal and the parameters of the input voltage divider.

The other important parameter is the sampling frequency.
Why achieving high frequency and high resolution at the same time can be difficult?
That's related to the way the sampling happens, which I will try to explain in a simple case.
Digital devices only understand two states : on and off, so how do they convert a voltage to an on or off state?
They can compare the voltage with a reference one and say : if the reference is higher, then set to off, else set to on.
Now if the reference voltage V(t) varies starting from V- (lower reference) and linearly climbs to V+ (higher reference) and at the same time we start a timer that counts the number of cpu cycles, at a given point in time, the signal will cross the reference and the comparison will return "on".
At that point the timer count t gives us a measurement of the voltage used in the comparison V(t).
Practically, some more advanced techniques are used, but that's  pretty much the basic concept.
You understand then that the timer speed is affecting the resolution + sampling rate combination.
If we have a 10 bit resolution, the timer must be able to count up to 1024 when V(t) = V+.
Imagine the timer uses the same clock frequency as the CPU being 16MHz -> the maximum sampling rate would be 16/1024 MHz = 15KHz.
As I previously stated, some more advanced techniques (series of approximations etc) are used, allowing the adcs to achieve better performances, but you now probably understand the relation between cpu speed, sampling rate and resolution.

In the next post I am going to experiment with the ADC10 device of the MSP430G2553