Pages: [1] 2 3 4   Go Down
Author Topic: Voltage divider problem  (Read 5246 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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();
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To clarify, this picture shows how I've done.



* volts.jpg (17.29 KB, 640x400 - viewed 137 times.)
« Last Edit: January 01, 2013, 07:06:49 pm by Boopidoo » Logged

Valencia, Spain
Online Online
Faraday Member
**
Karma: 144
Posts: 5365
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

The Netherlands
Offline Offline
Edison Member
*
Karma: 47
Posts: 1544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Offline Offline
Full Member
***
Karma: 3
Posts: 244
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would change the resistor values to as in my drawing

Then a little math and see if it don't work better
Code:
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




* Dv15.PNG (7.92 KB, 479x363 - viewed 99 times.)
« Last Edit: January 01, 2013, 07:53:28 pm by be80be » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Shannon Member
****
Karma: 200
Posts: 11730
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
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.
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Full Member
***
Karma: 3
Posts: 244
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Offline Offline
Full Member
***
Karma: 3
Posts: 244
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Offline Offline
Full Member
***
Karma: 3
Posts: 244
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

The Netherlands
Offline Offline
Edison Member
*
Karma: 47
Posts: 1544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

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

SW Scotland
Offline Offline
Edison Member
*
Karma: 17
Posts: 1377
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: January 03, 2013, 04:51:30 am by jackrae » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
« Last Edit: January 02, 2013, 01:02:02 pm by Boopidoo » Logged

Pages: [1] 2 3 4   Go Up
Jump to: