I needed a solution to monitor both current and voltage for my battery powered microcontroller projects.
The gotcha was in the measured input being above the Vcc of the microcontroller.
I found INA219 based boards to be suitable. Except there was no library for micropython (which I use for quick prototyping and generally get things done).
While I was testing the board I found that there was some misleading information regarding measuring negative current. Unlike many internet sources the chip is indeed capable measuring the current in both direction. This makes it perfect to monitor charge and discharge of a ~12V battery.
Here is the micropython code (ESP32 board, but should work with others):
from machine import I2C, Pin """ INA219 Power Monitor interface. Copyright GPL3.0 sergei.nz. https://www.ti.com/lit/ds/symlink/ina219.pdf """ MAX_CURRENT = 3.2 # Amps CURRENT_LSB = MAX_CURRENT/(2**15) R_SHUNT = 0.1 # Ohms CALIBRATION = int(0.04096 / (CURRENT_LSB * R_SHUNT)) CONF_R = 0x00 SHUNT_V_R = 0x01 BUS_V_R = 0x02 POWER_R = 0x03 CURRENT_R = 0x04 CALIBRATION_R = 0x05 ADDRESS = 0x40 SDA = Pin(21) SCL = Pin(22) FREQ = 400000 i2c = I2C(sda=SDA,scl=SCL,freq=FREQ) i2c.writeto_mem(ADDRESS, CALIBRATION_R ,(CALIBRATION).to_bytes(2, 'big')) def read_current(): raw_current = int.from_bytes(i2c.readfrom_mem(ADDRESS, SHUNT_V_R, 2), 'big') if raw_current >> 15: raw_current -= 2**16 return raw_current * CURRENT_LSB def read_voltage(): return (int.from_bytes(i2c.readfrom_mem(ADDRESS, BUS_V_R, 2), 'big') >> 3) * 0.004
The tricky bit is the calibration, you can read voltage without any calibration, but to make sense for current you will need to set the calibration register (0x05) to a specific value.
The calibration formula can be found here. It is present in the code above as well, all you need to do is define your shunt value (in Ohms) and maximum current you wish to measure (in Amps). Obviously there are limitations that are described in the documentation.
I haven’t implemented read_power(), but it should be straight forward to do.