Difficulty measuring V into arduino pro mini

I’d like my project to monitor incoming voltage so it can alert me when the battery is running low.
I’m making an altitude sensor to fit in a model rocket. I’m using

  • arduino pro mini, 328P, 3.3V/8MHz.
  • SparkFun OpenLog
  • SparkFun MPL3115A2 pressure/altitude sensor
  • Lipo battery 240mAh, 3.7V plugged in to arduino’s raw pin.

I have a voltage divider running like this…

Vcc (arduino pin)


R1 = 10k

├─── A0 pin


R2 = 1k

Ground

In my sketch’s setup I made analogReference(INTERNAL) so the analog input compares with the 328P’s internal 1.1 reference voltage.

Each time I plug the battery in and run my sketch, I read slightly different voltages…
From Vcc to ground I read a voltage of between 3.27 and 3.14 V, and from A0 to ground I read a voltage of between 0.296 and 0.284 V — Each time I measured this while my sketch was running.

If I’m doing the math right, 0.296V (voltage at A0) divided by the internal 1.1V reference, times the 1023 read resolution, gives 275. But that time the analogRead gave me 305.

The time when I measured 0.284V at A0 pin, I calculate that analogRead should have given me 264, but instead it gave me 409.

I’m not making any changes to the breadboard. The pressure sensor and OpenLog are both running during all this but seem to be functioning fine.

What am I doing wrong?

P.S. I also tried measuring the value at A0 with just the OpenLog and not the pressure sensor. When I do that the sketch gives me a more consistent value each time I run it, but is still about 20 more than what I calculate it should be. (Ex. A0 measured 0.296V, I calculate it should read 275, but actually read 287. Here’s my code for that:

int voltSensorPin = A0;
int voltVal = 0;

void setup()
{ 
  Serial.begin(9600);
  Serial.println("Reading analog input on A0 pin.");
  
  //Establish analog read using INTERNAL voltage
  analogReference(INTERNAL);
}

void loop()
{ 
  voltVal = analogRead(voltSensorPin);
  Serial.print("int voltVal = ");
  Serial.println(voltVal); 
}

Lipo battery 240mAh, 3.7V plugged in to arduino’s raw pin.

Don’t do that, because the RAW pin goes through a voltage regulator. Connect the battery to the “5V” / “Vcc” pin to bypass the regulator.

You can use the stable internal voltage reference to read the battery voltage, with no external connection. However, you need to calibrate the internal voltage reference, because it can have any value between about 1.0 and 1.2 V.

Here is a function to make that measurement:

// Read Vcc using 1.1V internal voltage reference
// EVERY PROCESSOR MUST BE CALIBRATED INDIVIDUALLY!

unsigned int readVcc(void) {
  unsigned int result;
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1);
  delay(2); // Wait for Vref to settle

  ADCSRA |= (1 << ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // wait until done
  result = ADC;

  // two readings are better than one

  ADCSRA |= (1 << ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // wait until done
  result = ADC;

  // calibrated for Miniduino board
  result = 1195700UL / (unsigned long)result; //1126400 = 1.1*1024*1000
  return result; // Vcc in millivolts
}

You will need to change the constant “1195700UL” to match your Pro Mini. Use your multimeter to measure the actual battery voltage, and adjust that constant so that the function returns the correct answer.

Thank you so much, jremington! Between your responses here and on this thread (Arduino Forum), I think I've got the code working to read the Vcc!

Question though. Wouldn't it be unsafe to plug the battery directly into the Vcc pin? It's a 3.3v arduino, and after fulling charging the Lipo battery it reads 4.13v. Isn't that too much to plug directly in?

The ATmega328 used on the Pro Mini is designed to run at any voltage between 1.8 and 5.0V. You do have to reduce the clock speed for voltages below about 4V.

The type of regulator (MIC5205) used in some of 3.3V the Pro Minis tolerates higher voltages on its output. But I don’t know if that holds for all variants. If you are worried about the 3.3V regulator failing, it is easy to remove with the tip of a hot solder pencil. Just swipe it off.

You do have to worry about the pressure sensor, which is spec’d for 3.6V maximum. You could try connecting the battery to the RAW pin and see what the voltage drop is to Vcc, which depends on the type of regulator used. If the marking on the regulator chip is “KB33” then you have the MIC5205, which has extremely low dropout voltage and should be OK. Tell us what you find.

However, you then need a different technique to measure the battery voltage.

I do have the KB33 regulator on my pro mini, but as you said, since the datasheet for my pressure sensor indicates it can only receive up to 3.6v it means I have to measure battery voltage another way.

Can I ask, is the reason that the code you gave me won’t work for detecting low battery voltage because it measures what comes off the voltage regulator, and therefore won’t detect any drop in voltage until the battery goes below 3.3 volts?

Separate question, should I go back to the voltage divider I set up in the first post? I was getting inconsistent readings from it, so was wondering if I was doing something wrong or if there’s a way I can improve it?

Thank you very much for your patience and help!!!

therefore won't detect any drop in voltage until the battery goes below 3.3 volts?

Correct, but with the KB33 regulator you should be OK. The regulator output voltage will "track" the battery voltage below that.

If Vcc (after the regulator) drops below 3.0V, you need to turn off the board, or the battery will be damaged or destroyed.

I don't know why you are having troubles with the voltage divider. It should work, except that the 11:1 divider does not allow you to use the full range of the ADC. A 4:1 divider would be better. Note also that the 1.1V reference is not calibrated. It is stable, but the voltage can be anywhere between about 1.0 and 1.2V.

You might try adding a 10 to 100nF cap from the junction of the voltage divider to ground, or just averaging a few readings, or both.