The IC itself needs a couple of registers to configure its range, and the red-coloured sensor module on the attached picture also contains a couple more resistors which form a voltage divider, so the module also offers voltage measurement capability.

The module is intended to measure power consumption of devices which use up from about a watt to about 60 watts. I don’t think it’s very precise in the low range. It outputs a voltage level on the Vt pin which is 5x lower then the input voltage, and outputs a voltage level on the At pin which is directly analogous to the current, i.e. for 1A it will output 1V.

By measuring the voltage and current output pins from the module, it’s trivial to calculate the power passing through the device. The device’s limits are about 3A for current and about 25V for the voltage (this one depends on the voltage of the MCU doing the reading of the analogue pin!).

AVR microcontrollers (and this is also true for most of the other families of microcontrollers) generally measure a voltage level using an ADC (analogue-to-digital) circuit which compares the desired voltage to the MCUs Vcc level, and outputs an integer in the range of 0 to 1023 (because the ADC has 10 bits of accuracy). So for an input voltage of 0 V, the ADC will output 0, and for an input voltage exactly equal to Vcc it will output 1023. To convert this reading into a (floating point) voltage, this equation needs to be used:

V = (reading / 1023) * Vcc

…or, in actual code:

```float Vcc = 5.0;
float V = (analogRead(A0) / 1023.0) * Vcc;```

Microcontrollers are often used in battery-powered devices, and this means the Vcc will change over time. If the Vcc value were hard-coded in the program (i.e. “5.0”), the voltage calculated in the above equation would soon become severely inaccurate.

Fortunately, the AVR MCUs have an built-in, stable internal voltage reference which can also be used to measure a voltage. The “stable” part means it doesn’t vary with Vcc and even to a large degree external factors such as temperature. Unfortunately, this reference voltage level is around 1.1 V, which means by default we could only measure voltages on the pin up to this level, and also, the reference voltage is uncalibrated, meaning its value, while stable for a particular IC, varies during the production process, so each chip has a slightly different internal reference voltage level.

Fortunately, again, the AVR’s ADC can be configured to measure the internal voltage reference, comparing it to the external Vcc, and if the Vcc is known, the internal voltage reference can be measured, and its voltage level calibrated. This allows us to attach a voltmeter to the Vcc pin and measure it precisely, then measure the internal voltage reference, and calculate its value from the same equation as above. With a bit of math, by measuring the internal voltage reference, the Vcc can be calculated and calibrated, which is done by the following code:

```int readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined (__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

delay(2); // Wait for Vref to settle

uint8_t high = ADCH; // unlocks both

long result = (high<<8) | low;

result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000

return result - 0; // hard-coded calibration
}```

By running a program on the MCU with the above code, which returns an integer number of millivolts, and comparing its result to what an external voltmeter says the Vcc is, we can incorporate this difference as a calibration value in the “return” statement above, so the result of the function is equal to what the external voltmeter reports.

This calibrated Vcc value is needed to measure the output of the MAX471 sensor module:

```float Vcc = readVcc() / 1000.0; // Vcc in volts
float Vpin = (analogRead(A0) / 1023.0) * Vcc; // Voltage on the Vt pin
float Vsensor = Vpin * 5; // The sensor divides the voltage by 5
float Asensor = (analogRead(A1) / 1023.0) * Vcc; // Voltage on the At pin```

This is enough to accurately measure voltages of up to 25 V (only if the MCU is powered by a 5V-ish power supply, because the input to the ADC must not exceed Vcc!), and currents of up to 3 A on the sensor module.