The ATmega’s (and ATtiny’s for that matter) all have a 10-bit ADC which can be used measure analog voltages. These ADC’s are ratiometric, meaning they measure relative to the analog reference voltage (usually VCC).
On a 5V Arduino, that means you can measure 0..5V as 0..1023, or roughly 5 mV per step.
On a 3.3V JeeNode, the measurements are from 0 to 3.3V, or roughly 3.3 mV per step.
There’s no point connecting VCC to an analog input and trying to measure it that way, because no matter what you do, the ADC readout will be 1023.
So can we figure out what voltage we’re running at? This would be very useful when running off batteries.
Well, there is also a “bandgap reference” in each ATmega/ATtiny, which is essentially a 1.1V voltage reference. If we read out that value relative to our VCC, then a little math will do the trick:
- suppose we read out an ADC value “x” which represents 1.1V
- with 5V as VCC, that value would be around 1100 / 5000 * 1023 = 225
- whereas with 3.3V as VCC, we’d expect a reading of 1100 / 3300 * 1023 = 341
- more generally, 1100 / VCC * 1023 = x
- solving for VCC, we get VCC = 1100 / x * 1023
So all we have to do is measure that 1.1V bandgap reference voltage and we can deduce what VCC was!
Unfortunately, the Arduino’s analogRead() doesn’t support this, so I’ve set up this bandgap demo sketch:
Sample output, when run on a JeeNode SMD in this case:
There’s a delay in the vccRead() code, which helps stabilize the measurement. Here’s what happens with vccRead(10) – i.e. 10 µs delay instead of the default 250 µs:
Quite different values as you can see…
And here’s the result on an RBBB with older ATmega168 chip, running at 5V:
I don’t know whether the 168’s bandgap accuracy is lower, but as you can see these figures are about 10% off (the supply voltage was measured to be 5.12 V on my VC170 multimeter). IOW, the bandgap accuracy is not great – as stated in the datasheet, which specifies 1.0 .. 1.2V @ 25°C when VCC is 2.7V. Note also that the bandgap reference needs 70 µs to start up, so it may not immediately be usable when coming out of a power-down state.
Still, this could be an excellent way to predict low-battery conditions before an ATmega or ATtiny starts to run out of steam.