INA238 Power Monitor Guide
The INA238 is connected to I2C bus 1. In Linux, this is bus 7 with address 0x45.
sudo i2cdetect -y -r 7
A example Python driver is provided here.
https://github.com/ARK-Electronics/ARK-OS/blob/main/platform/jetson/scripts/ina238_test.py
from smbus2 import SMBus
import time
import math
# INA238 Register Addresses
REG_CONFIG = 0x00
REG_ADC_CONFIG = 0x01
REG_SHUNT_CAL = 0x02
REG_VSHUNT = 0x04
REG_VBUS = 0x05
REG_DIETEMP = 0x06
REG_CURRENT = 0x07
REG_POWER = 0x08
# Conversion factors
VSHUNT_LSB = 5e-6 # 5 µV/LSB for ADCRANGE = 0
VBUS_LSB = 3.125e-3 # 3.125 mV/LSB
TEMP_LSB = 0.125 # 125 m°C/LSB
POWER_LSB_MULTIPLIER = 0.2
class INA238:
def __init__(self, bus_num=7, address=0x45, r_shunt=0.001, i_max=70.7):
self.bus = SMBus(bus_num)
self.address = address
self.r_shunt = r_shunt
# Current_LSB = MaxExpectedCurrent / 2^15
self.current_lsb = i_max / 32768 # Max 16-bit signed
self.power_lsb = self.current_lsb * POWER_LSB_MULTIPLIER
# SHUNT_CAL = 819.2 x 10^6 x CURRENT_LSB x R_shunt
self.shunt_cal = int(819.2e6 * self.current_lsb * self.r_shunt)
self.configure()
def configure(self):
# Default CONFIG: ADCRANGE = 0 (±163.84mV), CONVDLY = 0
self.write_register(REG_CONFIG, 0x0000)
# ADC_CONFIG: continuous conversion on all (bus, shunt, temp), 1052µs conv time, AVG = 16
adc_config = (0xF << 12) | (5 << 9) | (5 << 6) | (5 << 3) | 2
self.write_register(REG_ADC_CONFIG, adc_config)
# SHUNT_CAL: The register provides the device with a conversion constant value
# that represents shunt resistance used to calculate current value in Amperes.
# This also sets the resolution for the CURRENT register.
self.write_register(REG_SHUNT_CAL, self.shunt_cal)
def write_register(self, reg, value):
data = [(value >> 8) & 0xFF, value & 0xFF]
self.bus.write_i2c_block_data(self.address, reg, data)
def read_register(self, reg, length=2):
data = self.bus.read_i2c_block_data(self.address, reg, length)
value = int.from_bytes(data, byteorder='big', signed=(reg != REG_POWER))
return value
def read_shunt_voltage(self):
raw = self.read_register(REG_VSHUNT)
return raw * VSHUNT_LSB
def read_bus_voltage(self):
raw = self.read_register(REG_VBUS)
return raw * VBUS_LSB
def read_temperature(self):
raw = self.read_register(REG_DIETEMP)
# Top 12 bits are the temperature
raw_temp = raw >> 4
# Convert 12-bit two's complement
if raw_temp & 0x800: # negative value
raw_temp -= 1 << 12
return raw_temp * TEMP_LSB
def read_current(self):
raw = self.read_register(REG_CURRENT)
# Current [A] = CURRENT_LSB x CURRENT
return raw * self.current_lsb
def read_power(self):
raw = self.read_register(REG_POWER, length=3)
# Power [W] = 0.2 x CURRENT_LSB x POWER
return raw * self.power_lsb
def close(self):
self.bus.close()
if __name__ == "__main__":
# 1mOhm 5W shunt
# power = I * I * R --> sqrt(5W / 0.001) = 70.7107
power_rating = 5 # Watts
shunt_resistance = 0.001 # Ohms
max_current = math.sqrt(power_rating / shunt_resistance)
ina = INA238(r_shunt=shunt_resistance, i_max=max_current)
try:
while True:
print(f"Bus Voltage: {ina.read_bus_voltage():.3f} V")
print(f"Shunt Voltage: {ina.read_shunt_voltage():.6f} V")
print(f"Current: {ina.read_current():.3f} A")
print(f"Power: {ina.read_power():.3f} W")
print(f"Temperature: {ina.read_temperature():.2f} °C")
print("-" * 40)
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
ina.close()
Last updated