INA226 I2C Current Sensor Module

Place code snippets and demo code here
Post Reply
lyizb
Posts: 308
Joined: Fri Feb 12, 2021 8:23 pm
Has thanked: 162 times
Been thanked: 117 times

INA226 I2C Current Sensor Module

Post by lyizb »

The INA226 can read voltages up to 36V and currents as determined by the shunt resistor connected to it.

I want to monitor at least 4 small solar panels to compare the effects of a poor azimuth and tilt angle (what is possible where I may in the future mount full-sized panels) with a more ideally-aligned panel. These will be mounted on the front of my barn. I will also be looking at shading, since it is possible that in the winter in Nova Scotia, the lower panels will be partially or completely shaded by the house.

The INA226 looks perfect for this, but the Arduino and other code examples I found seemed overly complex (to the point where I couldn't understand exactly what they were doing--even after looking at the library code). I also found the data sheet confusing--I had to actually get a circuit to work before I understood what the data sheet was saying about how to set the Calibration register. The wiring diagrams on the internet were helpful.

Datasheet: https://www.ti.com/lit/ds/symlink/ina22 ... 9076066708

I'm using two different modules:
INA226 module 1.jpg
INA226 module2t.jpg
(I just ordered another 5 of the first type from Aliexpress for $2.02US each including shipping.)

Here's a sample Arduino wire-up:
Arduino INA226.jpg
In this test, the motor is replaced by an LED, and the "Source" is either 5V or 3V3 from an ESP32-S2Mini.

My wiring is just a lash-up for developing the code.

The INA226 has 8 registers: Configuration, Shunt voltage drop, Source Voltage, Power, Current, Calibration, Alert, and Mask. The Configuration register has default values which I did not change. It is necessary to set the Calibration register for the Power and Current registers to be filled in. The calculation is used in the program: 0.00512 divided by ( 0.001 * 0.01 ) (the latter two numbers are the number of volts per incremental value of the voltage reading, and the .01 is the ohmic value of the shunt resistor (labelled 010 on the first module type I have, and 100 on the second--it's also possible to remove the on-board shunt resistor and wire up a much larger external one--so that, for instance, a 100Ah 12V battery could be monitored--that's a future project).

I ran the program first with the source voltage from the 3V3 pin on the ESP32-S2Mini I was using, and then again with the voltage from the 5V pin. Here are the readings I got:

Code: [Local Link Removed for Guests]

Calib: 512
           Config    ShuntV    BaseV     Power     Current   Calib     Mask      Alert     
I2C  &h40  4127      106       3.31V      8mW      66mA      200       8         0         
Calib: 512
           Config    ShuntV    BaseV     Power     Current   Calib     Mask      Alert     
I2C  &h40  4127      25E       5.11V      31mW      152mA      200       8         0         
Here's the code:

Code: [Local Link Removed for Guests]

' ina226_test.bas
' https://www.ti.com/lit/ds/symlink/ina226.pdf?ts=1719076066708 TI data sheet
' https://github.com/macgeorge/STM32-example-codes/blob/master/6%20-%20INA226/F7_INA226.c
' 
rConfig=0:rShuntV=1:rBaseV=2:rPower=3:rCurrent=4:rCalib=5:rMask=6:rAlert=7:rManuf=&hFE:rDieID=&hFF
iConfig=0:iShuntV=0:iBaseV=0:iPower=0:iCurrent=0:iCalib=0:iMask=0:iAlert=0:iManuf=0:iDieID=0
i=0:j=0:k=0:l=0:m=0:n=0:reg=0: flagI2C2=0:port=&h40

dim ia(3) ' input buffer, 
dim ib(8) ' register values
dim sReg$(9)="Config","ShuntV","BaseV","Power","Current","Calib","Mask","Alert","Manuf","DieID"

I2C.SETUP 33, 35  ' set I2C port on pins 33-sda and 35-scl--esp32-S2Mini

'i2c.ReadRegArray port,rConfig,2,ia()
'ib(0)=ia(0)*256+ia(1)
'wlog hex$(ib(0)) ' returns '4127--power-on configuration reg value

  iCalib = 0.00512 / ( 0.001 * 0.01 )
  wlog "Calib: ";iCalib ' 512 for .010 Ohms, 1mv/LSB
  ia(0)=iCalib/256: ia(1)=iCalib-(ia(0)*256)
  i2c.WriteRegArray port,rCalib,2,ia()
  gosub outputvals
  end

outputvals:
  a$="           "
  for i=0 to 7
    a$=a$+sReg$(i)+space$(10-len(sReg$(i)))
  next i
  wlog a$
  a$ = "I2C  &h"+hex$(port)+"  "
  for i=0 to 7
    i2c.ReadRegArray port,i,2,ia()
    ib(i)=ia(0)*256+ia(1)
    select case i
      case rBaseV: a$=a$+str$(int(ib(i)*0.00125*100)/100)+"V      " ' to hundredths of a volt
      case rPower: a$=a$+str$(ib(i))+"mW      "
      case rCurrent: a$=a$+str$(ib(i))+"mA      "
      case else: a$=a$+hex$(ib(i))+space$(10-len(hex$(ib(i))))
    end select
  next i
  wlog a$
return 
Pic of the lash-up:
INA226 test rig with ESP32-S2Mini.jpg
I've also successfully tested the module with 12 volts. It should have no problem with my small 18V solar panels
You do not have the required permissions to view the files attached to this post.
These users thanked the author lyizb for the post (total 7):
bugs, Electroguard, PeterN, BeanieBots, Oli, cicciocb, PANNO
Rating: 26.92%
 
lyizb
Posts: 308
Joined: Fri Feb 12, 2021 8:23 pm
Has thanked: 162 times
Been thanked: 117 times

Re: INA226 I2C Current Sensor Module

Post by lyizb »

For anyone looking at this, the calculation for current is wrong--it should be divided by 25, so, for instance, 3.31 volts at 66/25mA is 8.8mW, and 5.11V at 152/25mA is 31mA.

The values I get for Power and Current do not match the readings of a volt/ammeter device I wired in, so there is something wrong with the Calibration value. I will investigate further and report--but it may take a while--another project has gotten in the way.

(And incidentally, I love the way I wake up about every morning with a new project or wrinkle with Annex and the ESP32--thank you again, Francesco. The latest is emergency lighting for when the power goes out using Dollar Store LEDs which use 3-AAAs--the batteries are terrible (bright for maybe an hour), but the LEDs are quite bright when powered/dimmed at 5V using S2Minis or C3SuperMinis and IRLZ44N mosfets. I am controlling 4 of these LED lights from an ESP32-S2Mini now with a browser, and plan to add 4-5 more remotely using MQTT. Easy programming with Annex)

I do plan to get back to the INA226 before long--I have 7 small solar panels to monitor in various locations that I want to get mounted before we are too far past the summer solstice.
User avatar
Oli
Posts: 98
Joined: Tue Feb 09, 2021 10:07 am
Location: Germany, Meissen
Has thanked: 27 times
Been thanked: 65 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Oli »

hi,
thanks for the work,
i want to use the IC,
i admire how much you compressed all the bit shifts.

since i want to monitor a battery i need negative current too, the IC does that, it jumps to 64000 and counts down at negative current. how can you solve that ?
so not 16 positive bits, but 15 positive and 15 negative.
the power is also displayed positive at negative current flow.

another problem is that if the i2c is interrupted, the program aborts or shows strange values instead of 0

i am trying very hard, but someone with more experience can certainly modernize the code better,

the voltage works great,
but with the current i only get
from -1800 to +1800
but i expect -32000 to +32000
i don't have an explanation yet

sample:
if ib(4) > 32767 then Wlog " " , str$(0- (65535 - ib(4)))+"mA"
if ib(4) < 32767 then Wlog " " , ib(4)
if ib(4) > 32767 then Wlog " " , 0-(ib(3))
if ib(4) < 32767 then Wlog " " , ib(3)

greetings Oli
You do not have the required permissions to view the files attached to this post.
lyizb
Posts: 308
Joined: Fri Feb 12, 2021 8:23 pm
Has thanked: 162 times
Been thanked: 117 times

Re: INA226 I2C Current Sensor Module

Post by lyizb »

I'm not sure it addresses your problem, but I see one difference in the code for the calculation of current. I found I had omitted something, and the line should be:

Code: [Local Link Removed for Guests]

case rCurrent: a$=a$+str$(ib(i)/25,"%4.2f")+"mA    "
"since i want to monitor a battery i need negative current too"

Do you mean you want to monitor charging as well as discharging? I haven't looked at that yet.

At present I'm struggling to try to get a 6-channel PCB working (3 INA226s each on 2 different I2C pin sets). And other projects have intervened.

Monitoring charging and discharging a battery is certainly on my list, but I don't know when I will get back to it. Good luck.
User avatar
Oli
Posts: 98
Joined: Tue Feb 09, 2021 10:07 am
Location: Germany, Meissen
Has thanked: 27 times
Been thanked: 65 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Oli »

the problem was with the calibration register,
the value must be in a reasonable range for the IC to calculate correctly.

the i2c 1.3" display is on the same port (0.9 has a different initialization)
here is my result:

Code: [Local Link Removed for Guests]

' ina226
port=&h40
i=0:shunt=0:busV=0
j=0:k=0:l=0:m=0:n=0:reg=0
dim ia(2) ' input buffer 2x8bit, 
dim ib(6) ' register values

I2C.SETUP 8, 9  ' set I2C port on pins 33-sda and 35-scl--esp32-S2Mini
OLED.INIT 1,1 ' 128.64 upside down (below 4-pin header)


'------------Konfigurations register schreiben ------------
  ia(0)=&b01001001: ia(1)=&b00100111 '
  i2c.WriteRegArray port,0,2,ia()


'------------Konfigurations register lesen, kann weg ------------
i2c.ReadRegArray port,0,2,ia()
ib(0)=ia(0)*256+ia(1)
wlog hex$(ib(0)) ' returns '4127--power-on configuration reg value


'------------Kalibrierung Register 5 schreiben ------------
  iCalib = 10000
  ia(0)=iCalib/256: ia(1)=iCalib-(ia(0)*256)
  i2c.WriteRegArray port,5,2,ia()

  
  
Anf: 

for i=0 to 5 'lese Register 0-5 
i2c.ReadRegArray port,i,2,ia() 'lese I2C
ib(0)=ia(0)*256+ia(1)        'bringe die 2x8 bit Werte zu einer Zahl zusammen
if i=1 then shunt = ib(0)
if i=2 then busV = ib(0)
if i=3 then Power = ib(0)
if i=4 then Current = ib(0)
next i

if shunt > 32767 then  Current = 0 - (65535 - Current) : Power = 0 - Power : shunt = 0 - (65535 - shunt) 


 wlog "BUS: " , busV , "shunt: " , shunt , "Current: " , Current , "Power: " , Power  

  OLED.CLS
  OLED.FONT 1
  OLED.PRINT 0,0, ip$ 
  OLED.FONT 3
  OLED.PRINT 35,20, str$(busV)
  OLED.PRINT 35,40, str$(shunt)
  
pause 700
goto anf  

 end  
You do not have the required permissions to view the files attached to this post.
User avatar
Oli
Posts: 98
Joined: Tue Feb 09, 2021 10:07 am
Location: Germany, Meissen
Has thanked: 27 times
Been thanked: 65 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Oli »

At present I'm struggling to try to get a 6-channel PCB working (3 INA226s each on 2 different I2C pin sets). And other projects have intervened.
the IC can have 16 different I2C addresses,
see in the data sheet, just pull the A0 and A1 to the correct signal,
lyizb
Posts: 308
Joined: Fri Feb 12, 2021 8:23 pm
Has thanked: 162 times
Been thanked: 117 times

Re: INA226 I2C Current Sensor Module

Post by lyizb »

I'm not using the IC, I'm using a module which has (tiny) pads for A0 and A1 on either side of a pad for VCC. Theoretically, that should give you 4 possible addresses, but I can only get 3 to work.

However, I have no problem with reading 6 INA226 modules distributed on two different sets of I2C pins.
User avatar
Starraker
Posts: 158
Joined: Tue Sep 03, 2024 1:53 am
Location: Canberra Australia
Been thanked: 45 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Starraker »

LYZIB,

I have looked up the TI information on this chip and copied the following except from their specifications

https://www.ti.com/lit/ds/symlink/ina22 ... e.com%252F

6.5.5.1 Serial Bus Address
To communicate with the INA226, the master must first address slave devices via a slave address byte. The
slave address byte consists of seven address bits and a direction bit that indicates whether the action is to be a
read or write operation.
The device has two address pins, A0 and A1. Table 6-2 lists the pin logic levels for each of the 16 possible
addresses. The device samples the state of pins A0 and A1 on every bus communication. Establish the pin
states before any activity on the interface occurs.
Table 6-2. Address Pins and Slave Addresses
A1 A0 SLAVE ADDRESS
GND GND 1000000
GND VS 1000001
GND SDA 1000010
GND SCL 1000011
VS GND 1000100
VS VS 1000101
VS SDA 1000110
VS SCL 1000111
SDA GND 1001000
SDA VS 1001001
SDA SDA 1001010
SDA SCL 1001011
SCL GND 1001100
SCL VS 1001101
SCL SDA 1001110
SCL SCL 1001111
6.5.5.2 Serial Interface
The INA226 operates only as a slave device on both the I2C bus and the SMBus. Connections to the bus are
made using the open-drain SDA and SCL lines. The SDA and SCL pins feature integrated spike suppression
filters and Schmitt triggers to minimize the effects of input spikes and bus noise. Although the device integrates
spike suppression into the digital I/O lines, proper layout techniques help minimize the amount of coupling into
the communication lines. This noise introduction can occur from capacitively coupling signal edges between
the two communication lines themselves or from other switching noise sources present in the system. Routing
traces in parallel with ground in between layers on a printed circuit board (PCB) typically reduces the effects of
coupling between the communication lines. Shielded communication lines reduces the possibility of unintended
noise coupling into the digital I/O lines that can be incorrectly interpreted as start or stop commands.
The INA226 supports the transmission protocol for fast mode (1 kHz to 400 kHz) and high-speed mode (1 kHz to
2.94 MHz). All data bytes are transmitted most significant byte first.
User avatar
Starraker
Posts: 158
Joined: Tue Sep 03, 2024 1:53 am
Location: Canberra Australia
Been thanked: 45 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Starraker »

LYZIB,

I have looked up the TI information on this chip and copied the following excerpt from their specifications

https://www.ti.com/lit/ds/symlink/ina22 ... e.com%252F

6.5.5.1 Serial Bus Address
To communicate with the INA226, the master must first address slave devices via a slave address byte. The slave address byte consists of seven address bits and a direction bit that indicates whether the action is to be aread or write operation.
The device has two address pins, A0 and A1. Table 6-2 lists the pin logic levels for each of the 16 possible addresses. The device samples the state of pins A0 and A1 on every bus communication. Establish the pin states before any activity on the interface occurs.

Table 6-2. Address Pins and Slave Addresses (the following is a table to be copy pasted into a spreadsheet app)
A1 A0 SLAVE ADDRESS
GND GND 1000000
GND VS 1000001
GND SDA 1000010
GND SCL 1000011
VS GND 1000100
VS VS 1000101
VS SDA 1000110
VS SCL 1000111
SDA GND 1001000
SDA VS 1001001
SDA SDA 1001010
SDA SCL 1001011
SCL GND 1001100
SCL VS 1001101
SCL SDA 1001110
SCL SCL 1001111


6.5.5.2 Serial Interface
The INA226 operates only as a slave device on both the I2C bus and the SMBus. Connections to the bus are made using the open-drain SDA and SCL lines. The SDA and SCL pins feature integrated spike suppression filters and Schmitt triggers to minimize the effects of input spikes and bus noise. Although the device integrates spike suppression into the digital I/O lines, proper layout techniques help minimize the amount of coupling into the communication lines. This noise introduction can occur from capacitively coupling signal edges between the two communication lines themselves or from other switching noise sources present in the system. Routing traces in parallel with ground in between layers on a printed circuit board (PCB) typically reduces the effects of coupling between the communication lines. Shielded communication lines reduces the possibility of unintended noise coupling into the digital I/O lines that can be incorrectly interpreted as start or stop commands.
The INA226 supports the transmission protocol for fast mode (1 kHz to 400 kHz) and high-speed mode (1 kHz to 2.94 MHz). All data bytes are transmitted most significant byte first.

This should give you all of the addresses that you seek
Last edited by Starraker on Fri Jun 13, 2025 5:26 am, edited 3 times in total.
User avatar
Oli
Posts: 98
Joined: Tue Feb 09, 2021 10:07 am
Location: Germany, Meissen
Has thanked: 27 times
Been thanked: 65 times
Contact:

Re: INA226 I2C Current Sensor Module

Post by Oli »

i am enthusiastic about the ic.
if you have the shunt at ground, you can increase the voltage with a pre-divider, far beyond the 36V, even 600V are possible.
the shunt input can also be 80mV above the supply potentials in polarity. i.e. from -0.08V to (Ub +0.08V)
+-80mV is the full scale,

here the minimal:

Code: [Local Link Removed for Guests]

' ina226
port=&h40
i=0:shunt=0:busV=0
dim ia(2) ' input buffer 2x8bit, 
dim ib(3) ' register values
I2C.SETUP 8, 9  ' set I2C port on pins 33-sda and 35-scl--esp32-S2Mini
 
  
Anf: 
for i=0 to 3 'lese Register 0-5 
i2c.ReadRegArray port,i,2,ia() 'lese I2C
ib(0)=ia(0)*256+ia(1)        'bringe die 2x8 bit Werte zu einer Zahl zusammen
if i=1 then shunt = ib(0)
if i=2 then busV = ib(0)
next i
if shunt > 32767 then  shunt = 0 - (65535 - shunt) 

wlog "BUS: " , busV , "shunt: " , shunt 
 
pause 700
goto anf  

end 
Post Reply