Vin and Bandgap isue on Arduino Nano

Hi all,

I want monitor battery voltage on a Nano board (VIN), Found a lot of chatter about Bandgap, so I thought I would try it out, Problem is it always returns near 5 volts.

USB power result is 5.10 volts
5.72 volt battery result is 5.10 volts
9 volt battery result is 5.44 volts

each has a little fluctuation. I am ok with that. But the big issue is obviously the Readings are not right,

Now this is a Clone board but it appears to be fine for everything else. I have tried using this code to get reading

long readVcc() {
   long result;   // Read 1.1V reference against AVcc
   ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
   delay(2); // Wait for Vref to settle
   ADCSRA |= _BV(ADSC); // Convert
   while (bit_is_set(ADCSRA,ADSC));
   result = ADCL;
   result |= ADCH<<8;
   result = 1126400L / result; // Back-calculate AVcc in mV
   return result;
 }

I have also tried this

int getBandgap(void) // Returns actual value of Vcc (x 100)
    {
        
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
     // For mega boards
     const long InternalReferenceVoltage = 1115L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc reference
        // MUX4 MUX3 MUX2 MUX1 MUX0  --> 11110 1.1V (VBG)         -Selects channel 30, bandgap voltage, to measure
     ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
  
#else
     // For 168/328 boards
     const long InternalReferenceVoltage = 1180L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
        // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
     ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
       
#endif
     delay(50);  // Let mux settle a little to get a more stable A/D conversion
        // Start a conversion  
     ADCSRA |= _BV( ADSC );
        // Wait for it to complete
     while( ( (ADCSRA & (1<<ADSC)) != 0 ) );
        // Scale the value
     int results = (((InternalReferenceVoltage * 1024L) / ADC) + 5L) / 10L; // calculates for straight line value 
     return results;
 
    }

Here is the calling code

 void loop()
 {

     battVolts=getBandgap();  //Determins what actual Vcc is, (X 100), based on known bandgap voltage
     mySerial.print("Battery Vcc volts =  ");
     mySerial.println(battVolts);
     mySerial.print("Analog pin 0 voltage = ");
     mySerial.println(map(analogRead(0), 0, 1023, 0, battVolts));  // returns roughly 133 - 139
   

     long myval = readVcc();
     mySerial.print("Vcc2 volts =  ");
     mySerial.println(myval);
     mySerial.println(); 
     
     delay(2000);
     return;
}

I have to admit, I do not play with the internals of this chip, so this is cut and past as far as the read voltage goes.

The board does have a few things plugged in.
#define pin_cmd 4
#define pin_but1 8
#define pin_rx 10
#define pin_tx 11
#define pin_led1 13

It is a 328 processor in the board.

Anybody else have this issue? Any ideas on what I am doing wrong.

Using a Voltage divider will not work for me, The final creation will be a low power device and I do not want battery life to be shortened.

Thanks in advance
Highflier

highflier:
Using a Voltage divider will not work for me...

In that case you will not be able to measure the voltage on VIN.

What are you trying to measure, Vcc or Vin?

I didn't read very carefully, but it looks like the code you've got is reading Vcc by comparing it to measurement of the bandgap reference. That can only measure Vcc, which always should be around 5v on an unmodified 5v arduino.

To measure Vin, you must use a voltage divider, and you must connect the middle of it to one of the analog pins and measure that...

What people often do in battery operated applications is to run the microcontroller straight off a LiPo battery, and then Vcc is the battery voltage (3.7 nominal, 4.2 when fully charged - google will get you lots of graphs of discharge curves of LiPo chemistry - it's a little tricky to tell the state of charge from the voltage since it's a very flat curve for most of the discharge process - it very quickly falls from 4.2 to 3.7ish, then is around 3.7. This way, you're measuring the battery voltage, not a regulated voltage. Obviously, this requires either a custom made board, or a modified arduino board - but you need to modify an Arduino board anyway if you want good battery life. Even just the power LED is a real killer if you're putting the micro into sleep most of the time, as you often end up doing on battery.

highflier:
Using a Voltage divider will not work for me, The final creation will be a low power device and I do not want battery life to be shortened.

Than you can't measure V-in.
There is no physical connection between V-in to the MCU.

A voltage divider can be made with very high value resistors with a minimal load on the battery.
The "top" resistor to the battery could be as high as 10 Megohm.
Try 1Megohm from analogue input to ground, and 10Megohm from input to battery, and measure with 1.1volt Aref.
Also add a 100n cap from analogue input to ground.
That divider draws about 800nA (on a 9volt battery).

It seems you want to power the Nano from a 9volt battery.
With the onboard 5volt regulator?
That regulator has an idle current of 4-10mA, even when the MCU is asleep.
Leo..

Well I was trying to power the unit with 4AA's and it will be on 100% of the time. I will use sleep when possible to extend the life of the batteries.

I wanted a way to verify when the batteries are getting low.

I assume the Nano does not fault at 4.9 volts. So I guess if I forget about a battery level gauge, I can still monitor the regulated power level and then give warning when it is dropping to low. Just how low can the regulated power get before the Nano would become unstable? What are the safe limits on the Vcc pin, assuming you can use it for voltage in. (see below question)

Is it OK to connect the Vcc pin to the power source instead of the Vin pin, Assuming I use 3AA or 4AA batteries. Then this would allow me to use band gap to watch battery voltage?

If I use a Voltage divider what type of impact would I see on battery life? Of course using higher resistors as recommended above by Wawa.

Another part of this project will use a attiny85. I know that runs to much lower power levels. Thus I could use 3 AA to power that. I have not checked, is there a similar non-pin way to watch it's VCC?

Thanks for all the replies so far, Got me thinking on what I may need to change.

Highflier

Just how low can the regulated power get before the Nano would become unstable?

Per the Speed Grade chart in the datasheet, a 16 MHz Nano needs ~3.78V to be fully compliant.

If you divide down the battery into the 1.1V Max range as an analog input, the internal bandgap ADC reference should be good with Vcc all the way down to 3.8V.

highflier:
If I use a Voltage divider what type of impact would I see on battery life? Of course using higher resistors as recommended above by Wawa.

It's a pair of resistors. Figure out how much current they'll draw, and add that to your power budget to figure out how much it increases the battery load.

What are the safe limits on the Vcc pin, assuming you can use it for voltage in. (see below question)

Datasheet. The datasheet is your sacred canon, you just need to know where to look for it.

If you just want to know when the system might stop working, then continue with what you already have been doing. Measure VCC internally with 1.1volt Aref.
http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
If VCC of a 16Mhz Arduino drops below ~3.8volt, you know you're getting into the danger zone.
But the Nano might well work at or below 3.3volt.
Anything non-ratiometric that you measure with the analogue pins and default Aref will become unuseable when VCC drops below 5volt, but digital things still keep on going.
Leo..

ATTiny needs the same voltage as ATMega (chip in Arduino). If you underclock either (to 4MHz) you can run it from 1.8V.

Voltage regulator and LEDs and USB interfacing chip on Arduino eats so much power that consumption from the MCU itself is neligible - measure it!

Thanks for all the feedback. Waiting on a few bits before I can do power consumption study.

This project requires 2 devices, The first will be the Nano or micro etc..., but it will have access to plenty of power, I will just use the internal voltage regulator. The other half I was hoping to use a Tiny85, But I think my code will exceed the tiny85, flash memory. I am already at 6k used. Not sure how much is mine vs the libraries that are included.
Is there a step up from the tiny85 that has 16k flash or so. It also would not hurt to get 1-4 more pins.

16K flash on a 12 pin device would be the perfect fit. Since power is a issue No power LED is a requirement. I looked but did not see anything that appeared cost effective. Any boards out there for go the Pwr LED?