This is a function to determine your Arduino's supply voltage automatically in order to convert
the results of analogRead into a much more accurate voltage. As you may know, analogRead()
returns
a value that's relative to the supply voltage to the Arduino, which can deviate. If you feed a known
voltage to an analog pin, this function can read and use it to calculate what Arduino's supply voltage is:
double getArduinoVcc(int analog_pin, double expected_volt)
{
double received_frac = (double)analogRead(analog_pin) / 1023.0;
double expected_frac = (expected_volt / 5.0);
return (expected_frac / received_frac) * 5.0; // == vcc
}
You must have a known, accurate and stable voltage at analog_pin
, be it from a precision reference IC or anything else you
know is stable and accurate. The function will read the voltage at that pin and compare what it should see if the supply was 5.0V vs what it actually sees. The ratio between them * 5.0 is the supply voltage,
which is returned. Normally you would do something like this:
int sensorValue = analogRead(A0);
float voltage = sensorValue * (5.0 / 1023.0);
But now you can do this:
// make sure A3 has 4.0 volts at this point in time...
float vcc = getArduinoVcc(A3, 4.0); // only called once. Use the vcc value everywhere
int sensorValue = analogRead(A0);
float voltage = sensorValue * (vcc / 1023.0);
Or to be more efficient, do vcc / 1023.0
just once and use everywhere:
double vcc_div1023 = getArduinoVcc(A3, 4.0) / 1023.0; // use everywhere
float voltage = analogRead(A0) * vcc_div1023;
In case you're curious how it work and/or want to test it without having the known voltage applied + simulating different supply voltages... put this atop your sketch:
// TESTING for getArduinoVcc()...
double fakeAnalogRead(double expected_volt, double simulated_vcc)
{
return 1023.0 * (expected_volt/simulated_vcc);
}
double testGetArduinoVcc(int analog_pin, double expected_volt, double simulated_vcc)
{
// received_frac * VCC == expected_volt... but what is VCC?
double received_frac = (double)fakeAnalogRead(expected_volt, simulated_vcc) / 1023.0;
Serial.println( "Got: " + String(received_frac) + " * VCC");
// expected_frac is received_frac * VCC if VCC was exactly 5.0V
double expected_frac = (expected_volt / 5.0);
Serial.println( "Expected: " + String(expected_frac) + " * VCC");
double error_frac = expected_frac / received_frac;
Serial.print("VCC is "); Serial.println(error_frac * 5.0);
return error_frac * 5.0; // == vcc
}
and call it like this:
void setup()
{
Serial.begin(9600);
double vcc = testGetArduinoVcc(A0, 4.1, 4.9);
Serial.print(vcc);
}