Measuring Voltage of Small Lithium Polymer battery, analog errors?

So I have a small single cell lithium-polymer battery (3.7 volts nominal) and I am trying to read the voltage level via analog in. measured with my multimeter (10Mohm input impedance) I find the voltage to be 3.8 volts. However using my arduino I find the voltage to be a tad over 4 volts. I am hoping it is the code I am using and not the arduino. The battery is 70mAH.

My Code:

long batReading = 0;
long numReadings = 0;
long previousMillis = 0;
long interval = 200;

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  unsigned long currentMillis = millis();
  
  batReading = batReading + analogRead(0);
  numReadings = numReadings + 1;
  
  if(currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    
    double batVolts = 0.0;
    batVolts = batReading / numReadings / 1024.0 * 5.0;
    Serial.println(batVolts);
    
    batReading = 0;
    numReadings = 0;
  }
}

Where did you connect the negative terminal of the battery?

You will also get slightly more accurate readings by writing:

batVolts = 5.0 * batReading / numReadings / 1024.0;

instead of:

batVolts = batReading / numReadings / 1024.0 * 5.0;

In your version, the expression "batReading / numReadings" is integer division which loses precision (e.g., 5/2 == 2).

-- The Ruggeduino: compatible with Arduino UNO, 24V operation, all I/O's fused and protected

The negative terminal is hooked to ground. Thanks for the code bit there, I will put that in immediately.

It does work some what because it shows a large voltage drop if i connect a load that draws a fair amount of current from it (small motor). Its just inaccurate.

There is a surprising amount of voltage drop in regular 24AWG hookup wire when it starts carrying current. Try to keep the wires from the battery to the Arduino as short as possible (both the positive and the negative wires). Connect to the Arduino ground pin close to the analog inputs. Use separate wires from the battery to the motor.

-- The Flexible MIDI Shield: MIDI IN/OUT, stacking headers, your choice of I/O pins

i am doing all those things. The problem is that the arduino is showing a value higher than my multimeter.

Here's a thought....measure the +5V output of the Arduino.

I bet it's less than 5V :)

-- The Rugged Circuits Yellowjacket: 802.11 WiFi module with ATmega328P microcontroller, only 1.6" x 1.2", bootloader

How much too high?

Try batVolts = 5.0 * batReading / numReadings / 1023.0;

as 1023 (B11 1111 1111) represents Aref.

You also seem to have some funny average of 2 readings over 200mS going on? Am I reading that right? Why not just read A0 twice and just use the 2nd reading?

it reads the analog pin like ~200 times. then every 200 milliseconds takes the average of all those readings and calculates actual volts. Its about 0.3v too high. I’m waiting for the battery to wear down somewhat to see if the 0.3 volts remains consistent. I suspect that it won’t.

RuggedCircuits: Here's a thought....measure the +5V output of the Arduino.

I bet it's less than 5V :)

-- The Rugged Circuits Yellowjacket: 802.11 WiFi module with ATmega328P microcontroller, only 1.6" x 1.2", bootloader

yikes! its 4.65! I'm running it of usb. that would explain that. ill try replacing 5 with 4.65 and see if that helps.

the readings are spot on now! is there any way of reading the arduino's 5 volt output? and then using that in my calculations?

Yes, you can use a voltage divider (1k/10k) to knock 5V down to about 0.5V and then use the internal 1.1V reference to measure it.

-- The Basic Motor Driver: simple, inexpensive motor driver for 1 stepper motor or 2 DC motors

how would i go about doing this? how would i use the internal 1.1volt reference? Thanks btw. :D

You can use the analogReference() function to change the A/D reference voltage on-the-fly:

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

-- The QuadRAM shield: add 512 kilobytes of external RAM to your Arduino Mega/Mega2560