void setup() {
Serial.begin(9600);
Serial.println("Setup completed.");
}
void loop() {
// Read external battery VCC voltage
Serial.print("Bat: ");
uint16_t batVolts = getBatteryVolts();
Serial.print(batVolts);
Serial.print(" - ");
Serial.println(getBatteryVolts2());
delay(500);
}
// One way of getting the battery voltate without any double or float calculations
unsigned int getBatteryVolts() {
//http://www.gammon.com.au/adc
// Adjust this value to your boards specific internal BG voltage x1000
const long InternalReferenceVoltage = 1100L; // <-- change this for your ATMEga328P pin 21 AREF value
// 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);
// Let mux settle a little to get a more stable A/D conversion
delay(50);
// Start a conversion
ADCSRA |= _BV( ADSC );
// Wait for conversion to complete
while ( ( (ADCSRA & (1 << ADSC)) != 0 ) );
// Scale the value - calculates for straight line value
unsigned int results = (((InternalReferenceVoltage * 1024L) / ADC) + 5L) / 10L;
return results;
}
// A different way using float to determine the VCC voltage
float getBatteryVolts2() {
// You MUST measure the voltage at pin 21 (AREF) using just a simple one line sketch consisting
// of: analogReference(INTERNAL);
// analogRead(A0);
// Then use the measured value here.
const float InternalReferenceVoltage = 1.1; // <- as measured (or 1v1 by default)
// turn ADC on
ADCSRA = bit (ADEN);
// Prescaler of 128
ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2);
// MUX3 MUX2 MUX1 MUX0 --> 1110 1.1V (VBG) - Selects channel 14, bandgap voltage, to measure
ADMUX = bit (REFS0) ;
ADMUX |= B00000000; //I made it A0 //ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
// let it stabilize
delay (10);
// start a conversion
bitSet (ADCSRA, ADSC);
// Wait for the conversion to finish
while (bit_is_set(ADCSRA, ADSC))
{
;
}
// Float normally reduces precion but works OK here. Add 0.5 for rounding not truncating.
float results = InternalReferenceVoltage / float (ADC + 0.5) * 1024.0;
return results;
}
I tried executing this program but it did not work i believe there is some issue with my pin declaration or circuit. Please check. I want the code to read my voltage but it constantly reads wrong value and it is not even reading from A0
I just changed this part of the code enter image description here
Unfortunately you did not follow my advice to study the linked information at https://github.com/RalphBacon/Arduino-Battery-Monitor. Especially those provided at http://www.gammon.com.au/adc
Instead you obviously messed with the first snipped you found without understanding what it does.
Otherwise I cannot explain why you would change
to
You don't want to read analog channel 0. You want to read the bandgap voltage (which is used as internal reference voltage).
There's the reference voltage, the ADC value and the measured voltage.
Usually you would use a known reference voltage and the ADC value to calculate the measured voltage.
V = ADC * Aref / 1023
But in this case you use the ADC voltage and the known measured voltage to calculate the reference voltage, which is the voltage of your battery connected to Aref.
Aref = V_bandgap * 1023 / ADC
But in order to do that you must set the ADMUX register to measure the internal voltage reference (1.1V) using an external reference voltage.