Teensy-LC and Analog Signal Measurement Stability

Status
Not open for further replies.

dripsys

Member
Dear all,

I am working with the Teensy-LC and I am measuring an analog signal coming from a battery.
I have the battery voltage connected to the Analog Pin A2 via a voltage-divider 470K and 150K.

Therefore, if I have a voltage of 3.3V it will result in a voltage of 0.798V at the analog input pin:

3.3 / (470*10^3 + 150*10^3) * 150*10^3 = 0.798V

I also have the following function calls in the setup():

analogReadAveraging(10); // Teensy: average this many readings
analogReadResolution(10); // Teensy: set ADC resolution to this many bits (2^10 = 1024)

I display the analogRead() value every 1 second and observe a value fluctuation from 214 to 261. The value is approximately correct (should be 247), but it fluctuates.

The board is powered by a battery, so there is no noise coming from a power supply.
I have the 3.3 volts connected to the AREF pin.
I tried to put a capacitor (small and large) on the analog pin, and also increased the analogReadAveraging to 100 but both had no effect.

Any ideas are appreciated...
 
When you say fluctiation, how much is it that? is this plus/minus one, or +/- 50?

Given what happens with the cap most likely option is that your reference is unstable. You don't say if you are actually have a command to use Aref in your code, otherwise it will be useing the internal one by default. The correct method to use the Aref pin is to provide a stable reference to it other than your main CPU supply and then set the ref to external. That said wouldn't have expected that much noise from a battery sample regardless.

Other possible checks are to see if you have noise on the battery test lead as read with a multimeter, and see if you get a stable read of your 3.3V input, and across something like a diode fed from the 3.3V (which should in theory be a low noise test voltage example to see if things are working right).
 
Last edited:
The result should be 100% stable with those analogReadAveraging(10) / analogReadResolution(10) settings. What's your supply voltage? AREF can't be larger than VDDA (=supply voltage - regulator drop).

0.1uF would be a good capacitor value between ground and your input.
 
Thank you all.

The problem was the high resistor values of the voltage divider. Once I took tvetter advice and reduced the resistors to 4.7K/1.5K the value was stable within 1 digit (out of 1024)
Adding a 0.1uF at the analog pin, as tni suggested, made the reading fixed without any fluctuation!

Final question:
As I understood, the Teensy-LC has no internal reference so for the mean time I just connected the 3.3V to the AREF. Later on I am intending to add a voltage reference chip.
I tried all 3 versions of the analogReference() with DEFAULT, INTERNAL and EXTERNAL. The DEFAULT and INTERNAL worked the same and gave me the correct reading, while the EXTERNAL gave me max value of 1023. With all options whether I had the AREF connected to the 3.3V or not didn't make a difference.

These results are confusing and I am not sure how to connect a future voltage reference chip.
 
Teensy LC has two reference sources for the ADC. The first (default / INTERNAL) is internally connected to the supply voltage (3.3V). The second one (EXTERNAL) is the AREF pin. The AREF pin is floating, if nothing is connected, so you can connect any kind of voltage reference you like.

You don't necessarily need an external reference, if your power supply voltage is reasonably stable (slowly changing), even if you drop below 3.3V. Teensy LC has an internal bandgap reference (1V) that you can measure (it can't be used as reference voltage for the ADC directly).

Code:
PMC_REGSC |= PMC_REGSC_BGBE; // enable bandgap ref
delay(10); // let the reference stabilize
int bandgap_val = analogRead(39);

This allows you to calculate the absolute value of the supply voltage or whatever is connected to AREF (depending on whether you selected INTERNAL or EXTERNAL). E.g., if your resolution is set to 10 bits and you read a value of 312, the current absolute value of the reference voltage is 1023 / 312 = 3.28V.
 
BTW, there is no reason to use a tiny divider like 4.7K/1.5K. I've used 200k/50k with the 0.1uF cap and it is completely stable.
 
tni - thank you for the response.

1. I tried to use a larger divider (47K/15K) but the reading was again unstable and fluctuated about 8 (292 - 301). When I placed the smaller divider (4.7K/1.5K) again, the reading was stable. I would like to use the larger divider in order to increase my battery life, but the instability of the measurement prevents me from doing so. Any other ideas why?

2. I am not sure I understand your explanation of how to use the internal bandgap voltage when measuring an analog signal. Currently I measure the analog signal (battery level) as follows:

// Battery voltage is split via a voltage divider built from 2 resistors:
// R1=4.7K; R2=1.5K
// Ratio = (R1+R2) / R2 = (4.7*10^3 + 1.5*10^3) / 1.5*10^3 = 4.133

BatValue = analogRead(BatVoltagePin); // Returns a value between 0 and 1023
BatV = BatValue * (3.3 / 1023.0) * 4.133;
 
1. I tried to use a larger divider (47K/15K) but the reading was again unstable and fluctuated about 8 (292 - 301).
Did you put the 0.1uF cap between measurement pin and ground? If so, you must have some serious noise. With a large divider, the cap is essential for the ADC being able to draw enough current for a stable reading.

If you are not using analogAveraging(), set it to 32.

2. I am not sure I understand your explanation of how to use the internal bandgap voltage when measuring an analog signal.
Let's assume you have VREF disconnected and you are using the INTERNAL reference = VDDA. Your battery level is 3V, so the regulator can't sustain 3.3V. Its voltage drop is maybe 200mV, so your VDD / VDDA is 2.8V (also your reference voltage). But you don't really know this voltage yet.

You perform the bandgap read (the bandgap is fixed 1V). Let's say you read 365. You can back-calculate that the reference voltage (VDDA) is 1023 / 265 = 2.83V. You can now measure you voltage divider and figure out the battery voltage.

This only works if your power draw is reasonably stable. The regulator voltage drop changes with the load when it's out of regulation.

As long as the supply voltage is in regulation, you know it's 3.3V. But if you want to draw your battery down more than that, you can use the above.
 
1. I tried to use a larger divider (47K/15K) but the reading was again unstable and fluctuated about 8 (292 - 301). When I placed the smaller divider (4.7K/1.5K) again, the reading was stable. I would like to use the larger divider in order to increase my battery life, but the instability of the measurement prevents me from doing so. Any other ideas why?

FWIW, the LC datasheet says "To achieve the best results, the analog source resistance must be kept as low as possible", max of 5K.

also see Using-a-Voltage-Divider-on-an-ADC-Input
 
manitou - this explains why the voltage divider works with the 4.7K/1.5K resistors. In this configuration, will the "Source Resistance" be considered the 1.5K ohm as this is the resistor that connect the analog pin to ground?
If this is the case, I can increase it up to 5K and save a bit more on the current draw from the battery.

tni -
You perform the bandgap read (the bandgap is fixed 1V). Let's say you read 365. You can back-calculate that the reference voltage (VDDA) is 1023 / 265 = 2.83V. You can now measure you voltage divider and figure out the battery voltage.

From your explanation I understand the following:

Bandgap-Voltage = (Bandgap-Value / 1023) * VREF

which translates to:

VREF = Bandgap-Voltage * (1023 / Bandgap-Value)

Which in your example:

(Bandgap-Voltage is always 1V)
VREF = 1V * (1023 / 365) = 2.80V

Is it true then that the Bandgap voltage will always be 1V but the analogRead(39) will return different values depending on VREF?

Thanks
 
manitou - this explains why the voltage divider works with the 4.7K/1.5K resistors. In this configuration, will the "Source Resistance" be considered the 1.5K ohm as this is the resistor that connect the analog pin to ground?
If this is the case, I can increase it up to 5K and save a bit more on the current draw from the battery.
The 0.1uF cap with the large voltage divider is extremely conservative and normally far more than enough to compensate. The ADC needs to fill a 5pF sampling cap to perform a reading. 5pF is 1/20'000 of 0.1uF.

Is it true then that the Bandgap voltage will always be 1V but the analogRead(39) will return different values depending on VREF?
Yes.
 
Status
Not open for further replies.
Back
Top