Go Down

Topic: Voltage divider problem (Read 7160 times) previous topic - next topic

Boopidoo

My goal is to read voltage from either a 2S or 3S lipo-battery which means that to read it with my arduino I need to reduce the voltage. I had some 100K and 10K resistors at home so I built a voltage divider using these. I measured the resistors to be R1=98700 and R2=9790. As can be seen in the code I use a variable called voltage_divider that has these values which I use when reading the voltage. The voltage is read using the Vin pin, there I connect R1 & R2 then connect to ground. I read the voltage over R2 into the A0-pin.

The problem is that I get a value that's close to the correct value but too far away to be acceptable. For example, a voltage of 4.55V reads 4.35V and 11.68V reads 11.45V.

Can anyone spot an obvious error?

Code: [Select]

#include <LiquidCrystal.h>

//LCD display pinout - YM2004A & OV1604A
//VSS   LCD pin 1     -  Connect to ground
//VDD   LCD pin 2     -  Connect to +5V
//V0    LCD pin 3     -  Connect to potentiometer
//RS    LCD pin 4     -  Arduino pin D07 
//RW    LCD pin 5     -  Connect to ground
//EN    LCD pin 6     -  Arduino pin D08
//DB4   LCD pin 11    -  Arduino pin D09
//DB5   LCD pin 12    -  Arduino pin D10
//DB6   LCD pin 13    -  Arduino pin D11
//DB7   LCD pin 14    -  Arduino pin D12
//ELA   LCD pin 15    -  Arduino pin D13
//ELK   LCD pin 16    -  Connect to ground
//LiquidCrystal lcd(7, NULL, 8, 9, 10, 11, 12);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int screen_backlight = 13;                 //pin D13 will control the backlight
float voltage_battery = 0;                 //pin A0
float voltage_divider = (98700+9790)/9790;    //((R1+R2)/R2)*voltage on A0-pin

void setup() {
  pinMode(screen_backlight, OUTPUT);       //LCD Setup
  digitalWrite(screen_backlight, HIGH);    // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(20,4);                         // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                             // start with a blank screen
  lcd.setCursor(0,0);                      //LCD text row 1
  lcd.print("Ui      V");
}

void read_voltage() {
  //Voltage input, U must be lower then 5V, HW-diveded then SW-multiplied
  voltage_battery = analogRead(A0)*voltage_divider*5/1023;
}

void screen_print() {
//Printing battery voltage level on LCD-screen
  lcd.setCursor(3,0);
  if(voltage_battery<10) {
    lcd.print(" ");
  }
  lcd.print(voltage_battery);
}

void loop() { 
  read_voltage();
  screen_print();
}

Boopidoo

#1
Jan 02, 2013, 01:04 am Last Edit: Jan 02, 2013, 01:06 am by Boopidoo Reason: 1
To clarify, this picture shows how I've done.


fungus

What are the exact voltages measured at the battery, the Arduino +5V pin and the analog input pin when it's connected up?
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

MAS3

Your voltage divider adds up to about a factor 11, not as a factor 10.
I guess that's what you are tripping over.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

be80be

#4
Jan 02, 2013, 01:36 am Last Edit: Jan 02, 2013, 01:53 am by be80be Reason: 1
I would change the resistor values to as in my drawing

Then a little math and see if it don't work better
Code: [Select]
ADC reading  1000 +2000 = 3000 /1000 = 3

check the chips ADC AREF pin say it's 4.89 volt
you can compensate for that in code 

so your math is 1000 +2000 = 3000 /1000 = 3 * 5 =(V1) 15

So a ADC reading of (V2) 5 volts = 15 volts



Boopidoo


What are the exact voltages measured at the battery, the Arduino +5V pin and the analog input pin when it's connected up?



The +5 pin is 4.55V and the battery is 11.68V.

Boopidoo

@be80be
Why the extra 1K resistor before the A0-pin?

MarkT


Your voltage divider adds up to about a factor 11, not as a factor 10.
I guess that's what you are tripping over.


That's obviously not the issue if you look at the code.
Code: [Select]

float voltage_divider = (98700+9790)/9790;    //((R1+R2)/R2)*voltage on A0-pin


One issue is that the calculation is in integer arithmetic, and secondly that error of about 2% is perfectly within spec anyway.

That code sets voltage_divider to 11.000.
Code: [Select]

float voltage_divider = (98700.0+9790.0)/9790.0;    //((R1+R2)/R2)*voltage on A0-pin


Will do the right thing.  Voltage regulators (such as the 5V regulator on the Arduino that you are using as
the voltage reference for ADC measurements) will normally have a +/- 2% or 5% rating - until you measure
the actual 5V rail voltage and substitute it for "5" in the calculations you can't do any better.
[ I won't respond to messages, use the forum please ]

be80be


@be80be
Why the extra 1K resistor before the A0-pin?


I will save you from making a bo bo it limits the current

be80be

The voltage divider has to be set for the AREF to get a true  reading  You pick a voltage range 0 to 15

Then you pick the resistors to read full scale at your AREF voltage is how you get a true reading.

Boopidoo

Ok, so to improve the accuracy I could reduce the resistor values or at least the dividing factor so that I get something around 3 or 4 instead of 11. This should make the accuracy a little better right? I want to be able to connect up to 4S-battery (16.8V) safely.

The 5V supply from the arduino seems to be a pretty solid 5V when I connect an external battery. I get 5.00V on my multimeter and when I power it using USB I get 5.06V. Or do you mean another 5V-rail then the 5V-output pin?

be80be

I would go for 20 volts then R1 would be 3k  and R2 1K  I would use a 2K Trimpot feed 20 volts to it and set the center dead on my VREF.

MAS3

Your measuring range with the original divider is too high.
I will gladly admit i didn't look at the code to see that you are using a formula that takes the number 11 as the divider.
But this way your maximum reading of 1023 would represent about 55 volts.

Therefore it would be better to try to get as close as possible to the actual range you are in.
So if you have 12 volts, and with the available resistors, i would use R1 as is, and instead of R2, 2 10K resistors in parallel forming a resistor of about 5K.
This would put you in a range of 15 volts, about 3 times better than where you are at now.

You then are measuring more accurate, because you have more bits to divide per voltage, so calculating with the measured result will also be more accurate.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

jackrae

#13
Jan 02, 2013, 09:40 am Last Edit: Jan 03, 2013, 10:51 am by jackrae Reason: 1
Hi guys

Don't confuse "resolution" (bits per volt) with "accuracy" (precision of measurement)

Increasing resolution will help with determination of measurement but it does not necessarily increase "accuracy", which depends on your Vref, ADC precision and input resistor tolerances.  You cannot get "accurate" results if you use 10% tolerance, high temp coefficient resistors.  And don't say you've already measured their values with your digital test meter.  What level of precision does that offer ?

On the other hand, measurement is a "relative" thing.  If you use your personal test meter as your "in-house standard" then all well and good since all subsequent measurements are referenced to it  -  not to precise national standards.  For example, I'm quite happy to use my cheap and nasty test meters as my reference standards but cannot ever consider them "accurate"  -  just good enough for my needs.

Boopidoo

#14
Jan 02, 2013, 01:45 pm Last Edit: Jan 02, 2013, 07:02 pm by Boopidoo Reason: 1
Now I've reduced the voltage divider and use R1=2990 and R2=984 and yes I do use my calibrated Fluke to measure everyting (as well as a cheapo but quite accurate meter). This will not need to hold any kind of indistry calibration standard but I need it to be as close to my meters as possible.

Now I get the following results:
Power over USB: 4.32V (arduino), 4.47 (on my meters),  3.35% diff
Power over 3S: 11.52V (arduino), 11.66V (on my meters), 1.2% diff

Of course I'd like it to be even better so I guess I should now start investigating this VREF that I guess is how the arduino close the arduino 5V supply is to 5V. Is that correct? Is there a prefered method of doing this?

Go Up