Hi
I think this routine is exactly what I want to check the battery. I’ve noticed that when the battery goes dead, temperature results I make using a TMP36 are all wrong. If I could get this working, I could set an alarm if the battery is too low.
I’m an old person but a brand new user, new coder, new everything, so I’m pretty limited. I copied the code from lefty above and add some stuff to output onto an LCD so I could see Vcc when powered by a nine volt battery. I’m using an Uno R3 with nothing connected except the LCD. While the battery was connected, using a volt meter, I measured the voltage from Vin to Ground. I got the following results that seem to indicate something is not working as expected.
Power Source Vcc Vanalog Pin 0 Vin to Ground
USB 472 117 4.48
dead 9v bat 460 115 5.6
new 9v bat 474 117 7.98
My code is below. What to you suppose is wrong?
Thanks
Bill
// Function created to obtain chip’s actual Vcc voltage value, using internal bandgap reference
// This demonstrates ability to read processors Vcc voltage and the ability to maintain A/D calibration with changing Vcc
// Now works for 168/328 and mega boards.
// Thanks to “Coding Badly” for direct register control for A/D mux
// 1/9/10 “retrolefty” from http://arduino.cc/forum/index.php/topic,86516.0.html
#include <LiquidCrystal.h> // include the LCD library
#include <SD.h> // include the SD library
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
int battVolts; // made global for wider avaliblity throughout a sketch if needed, example a low voltage alarm, etc
void setup(void)
{
lcd.begin(16, 2); // set up the LCD’s number of columns and rows:
lcd.print(“Vcc VPin0”); // Print a header on the LCD.
Serial.begin(9600);
Serial.print(“volts X 100”);
Serial.println( “\r\n\r\n” );
Serial.print(“Initializing LCD card…”); //write to the serial monitor
delay(100);
}
void loop(void)
{
battVolts=getBandgap(); //Determins what actual Vcc is, (X 100), based on known bandgap voltage
Serial.print("Battery Vcc volts = ");
Serial.println(battVolts);
Serial.print("Analog pin 0 voltage = ");
Serial.println(map(analogRead(0), 0, 1023, 0, battVolts));
Serial.println();
//display the result on the LCD
lcd.setCursor(0, 1);
lcd.print(battVolts);
lcd.print(",");
lcd.print(map(analogRead(0), 0, 1023, 0, battVolts));
delay(1000);
}
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 = 1056L; // 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 * 1023L) / ADC) + 5L) / 10L; // calculates for straight line value
return results;
}