Go Down

### Topic: Trying to measure input voltage... Doing something wrong. (Read 3742 times)previous topic - next topic

#### maniacbug

##### May 16, 2011, 06:53 amLast Edit: May 16, 2011, 02:53 pm by maniacbug Reason: 1
I am trying to measure the "Vin" voltage into my 3V3 Arduino on an analog input pin.  This is to monitor how the battery is doing.  Because the Vin voltage is higher than the Vcc voltage, there is a voltage divider circuit to cut the voltage down by 1.5x.  There is a 1M resistor from A5 to ground, and a 500k from A5 to Vin.

This actually works reasonably well as long as the ONLY thing being read is the analog pin connected to the voltage divider.

The problem comes when reading ANOTHER analog pin.  In this case there is a a temp sensor which is really the point of the application, so that MUST get read.  Introducing the reading of the temp sensor into the mix hoses the values I get back on my voltage reading.

Here is some sample code

Code: [Select]
`const int voltage_pin = A5;const int temp_pin = A4;void setup(void){  Serial.begin(57600);  Serial.println("adc_test");}void loop(void){  Serial.print("temp=");  Serial.println(analogRead(temp_pin),DEC);  Serial.print("volt=");  Serial.println(analogRead(voltage_pin),DEC);  delay(1000);}`

Running it, I get the following:

Code: [Select]
`adc_testtemp=221volt=883temp=221volt=869temp=223volt=885temp=223volt=900temp=225volt=870temp=224volt=924temp=223volt=881temp=223volt=869temp=224`

But if I comment out the temp reading, I get more reasonable values:

Code: [Select]
`adc_testvolt=980volt=985volt=985volt=986volt=985`

Anyone have thoughts on what needs to be done to get this right?  Thanks!

#1
##### May 16, 2011, 07:23 am
The ADC circuit has a Sample and Hold capacitor that charges up and is then converted.
Your large resistor values don't let much current in for that to happen, just a few microamps.
Put a little delay between the 2 read types, should help the 800+  numbers look more like the 900+ numbers.
Or, lower the 500K/1M values.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### MarkT

#2
##### May 17, 2011, 02:13 am
The spec says the ADC wants signals with a source impedance of 10k or less for reliable measurements.

Change your voltage divider to use 10k and 4k7 resistors.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

#### maniacbug

#3
##### May 17, 2011, 03:03 amLast Edit: May 17, 2011, 03:05 am by maniacbug Reason: 1

The spec says the ADC wants signals with a source impedance of 10k or less for reliable measurements.

Change your voltage divider to use 10k and 4k7 resistors.

Oooh..  Wow, ok, thanks.  Reading through the ADC part of the data sheet, I just could not figure that out.

That's rough, though.  So at 10k impedance, that circuit is going to burn 0.33mA, right?  As it stands now, this unit uses 0.12mA on average, so this would quadruple my current usage just to measure current usage...  Taking 20 months out of my battery life!  Yikes.

The thing is, when I read the values by themselves, I get better readings.  They're still a little off from what I'd expect, but not by 100+.

Tonight I'll run some tests against CR's suggestion too.

#4
##### May 17, 2011, 03:54 am
Quote
That's rough, though.  So at 10k impedance, that circuit is going to burn 0.33mA, right?  As it stands now, this unit uses 0.12mA on average, so this would quadruple my current usage just to measure current usage...  Taking 20 months out of my battery life!  Yikes.

Time for a "low side switch"?  You can then "turn off" the voltage divider when you are not measuring the battery voltage (you should only need to take a measurement every few minutes, hours, or possibly days).

#### maniacbug

#5
##### May 17, 2011, 05:49 am

Put a little delay between the 2 read types, should help the 800+  numbers look more like the 900+ numbers.

Tried that, to no avail.  Here's the new sample...

Code: [Select]
`const int voltage_pin = A5;const int temp_pin = A4;unsigned long interval = 250; // msconst unsigned long increase = 250; // msvoid setup(void){  Serial.begin(57600);  Serial.println("adc_test");}void loop(void){  Serial.print("delay=");  Serial.print(interval,DEC);  Serial.print(" temp=");  Serial.print(analogRead(temp_pin),DEC);  delay(interval);  Serial.print(" volt=");  Serial.println(analogRead(voltage_pin),DEC);  delay(interval);    interval += increase;}`

...and the output:

Code: [Select]
`adc_testdelay=250 temp=217 volt=908delay=500 temp=218 volt=901delay=750 temp=220 volt=882delay=1000 temp=220 volt=899delay=1250 temp=220 volt=867delay=1500 temp=220 volt=886delay=1750 temp=220 volt=874delay=2000 temp=220 volt=875delay=2250 temp=220 volt=886delay=2500 temp=213 volt=879delay=2750 temp=220 volt=883delay=3000 temp=220 volt=874delay=3250 temp=219 volt=900delay=3500 temp=220 volt=909delay=3750 temp=220 volt=870delay=4000 temp=220 volt=909delay=4250 temp=213 volt=871delay=4500 temp=220 volt=883delay=4750 temp=220 volt=920delay=5000 temp=220 volt=894delay=5250 temp=219 volt=889delay=5500 temp=220 volt=879delay=5750 temp=220 volt=879delay=6000 temp=220 volt=893delay=6250 temp=220 volt=896`

Quote

Time for a "low side switch"?  You can then "turn off" the voltage divider when you are not measuring the battery voltage (you should only need to take a measurement every few minutes, hours, or possibly days).

Ok, thanks, I will check those out.  Never heard of it before.  Yes, that's right in fact the whole unit is only awake for 40ms every minute to take and send a temp reading.  And yes, a voltage reading once a day is probably even overkill.  It sounds like that would do the job.

For the moment, it seems to work just living with the low reading.  It's off by a reliable factor, so as long as I calibrate it, I can obtain the true voltage across the range of operating voltages.

#6
##### May 17, 2011, 07:45 am

What is connected to AREF?

#### pito

#7
##### May 18, 2011, 02:30 amLast Edit: May 18, 2011, 03:47 am by pito Reason: 1
IEdit: I removed the stuff with dividers, needs to be measured again..

Edit: when you use a high impedance dividers on the input ain5 and low impedance source on ain4 and the voltage difference between the channels is high and you are scanning the both analog channels fast in a loop, then you will get such difference
as depicted in the first topic (charging/discharging high potential on the S/H capacitor  via two different impedancies)..
If the voltage difference between the two channels will be low, then you may use an higher impedance divider on one channel and lower impedance on the next as the S/H capacitor will be held on a "constant" potential level and therefore will charge/discharge a smaller potential/current..

Your last readings seems ~ok for me, as a) you use Vcc as the reference ( a lot of niose) and b) there is a lot of noise comming from poor decoupling maybe , c) or from other grounding loops. Try to put 10nF-100nF cpapcitor between analog input and ground and you will get better numbers, hopefully.
P.

#### maniacbug

#8
##### May 18, 2011, 05:19 am
Thanks for the responses, folks!

Quote

What is connected to AREF?

Not connected.  Tried tying it to VCC just now.  No appreciable difference.

Quote

All those things about the vcc and noise, etc, still apply when I was getting the reading of only the voltage, I was getting 980's which was more right.  Only the addition of testing the other analog pin changes the other reading to <900, which is definitely wrong.

Quote

Try to put 10nF-100nF cpapcitor between analog input and ground and you will get better numbers, hopefully.

Aha!  Yes, a 104 cap did the job.  Now the values are fantastic.  Thanks!!

Doh...  I already sent off the first set to the fab.  Guess I have some blue-wire in my future

#9
##### May 18, 2011, 06:01 am
Quote
What is connected to AREF? Not connected.  Tried tying it to VCC just now.  No appreciable difference.

Try a 0.1 uF capacitor between AREF and positive voltage.

#### pito

#10
##### May 18, 2011, 06:58 am
..and try this:

analogReference(INTERNAL);

..

#### maniacbug

#11
##### May 18, 2011, 07:12 amLast Edit: May 18, 2011, 07:14 am by maniacbug Reason: 1

..and try this:

analogReference(INTERNAL);

From http://arduino.cc/en/Reference/AnalogReference ...

Quote

analogReference(type)
Description

Configures the reference voltage used for analog input (i.e. the value used as the top of the input range). The options are:

INTERNAL: an built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328 and 2.56 volts on the ATmega8 (not available on the Arduino Mega)

1.1 volts?!  Maybe you mean 'EXTERNAL'?

#### maniacbug

#12
##### May 18, 2011, 03:19 pm

Quote
What is connected to AREF? Not connected.  Tried tying it to VCC just now.  No appreciable difference.

Try a 0.1 uF capacitor between AREF and positive voltage.

Ok, I tried this, and the results were just bizarre.  After adding that cap and setting 'analogReference(EXTERNAL)', which from the docs looks like the right thing, I was getting readings of 1024.

In any case, the cap across A5/GND seems to do the trick.

Thanks again!

#### Grumpy_Mike

#13
##### May 18, 2011, 03:30 pm
The code:-
Serial.print(" temp=");
delay(interval);
Serial.print(" volt=");
Is not what was meant by inserting a delay it should be like this:-
Serial.print(" temp=");
delay(interval);
Serial.print(" volt=");

The delay goes between the first read of the input channel and the second read. You throw away the first read as the capacitor will not have had time to charge up. You do this every time you change channels. Read it, delay, read it again.

#14
##### May 18, 2011, 07:38 pm

Is AVCC connected to power?

Go Up

Please enter a valid email to subscribe