Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 01:48 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Using the INA3221 I2C current and power monitor IC

Author Message
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6098
Posted: 06:53am 19 Dec 2023
Copy link to clipboard 
Print this post

My original battery monitor used 3 ACS712 hall effect current sensors.
These modules are analog out with zero amps = 2.5V (approximately).
This worked but I had a lot of trouble achieving a stable zero current reference.

A recent redesign of the rack inspied me to try INA3221 instead.
I was going to use three INA219 modules but the INA3221 is 3 channel so a perfect fit for the job.

The INA3221 registers are all 16 bit so to read, first send the register number (8 bit) then read 16 bits.
Unlike some I2C devices, you can only read one register at a time.
The modules I used came with 0.1 ohm shunts but that means they are only good for 1.6 Amps. Adding a 0.01 shunt fixed that.

The following code contains the functions I used for the task.
One of the readings is PV charging current which is a slow PWM once the battery is up to charge.
In order to read the charge current and the peak available, I take 100 rapid samples then average. The maximum of the readings is the peak available.
The slow PWM is a variable frequency so a simple average will not start and stop at each cycle starts. This results in an error.
This was corrected by looking for the first low to high and the last low to high transition in the 100 samples. This smaller sample is then averaged. Much better but slower.

The load and AC mains charge are reasonably steady so a simple single read was sufficient

The functions:
 ' INA3221 3 channel current and voltage I2C IC
 ' TassyJim Dec 2023
 OPTION EXPLICIT
 OPTION DEFAULT INTEGER
 OPTION BASE 0
 DIM INTEGER n , conf, gotime
 DIM FLOAT PVcurrent(99)
 CONST ina3221addr =&h40
 DIM FLOAT cur
 
 I2C2 OPEN 400,400
 INA3221_reset
 PRINT MM.I2C
 PRINT
 INA3221_enable_channel 7
 INA3221_set_Averaging 0
 INA3221_set_Volt_Time 3
 INA3221_set_Shunt_Time 3
 INA3221_set_Mode 3
 gotime = TIMER
 DO
 LOOP UNTIL INA3221_Ready()
 PRINT "Conversion time = "; TIMER-gotime; "mS"
 
 PAUSE 1
 PRINT
 FOR n = 0 TO 17
   conf = INA3221_read(n)
   PRINT HEX$(conf,4), conf
 NEXT n
 PRINT
 
 FOR n = 254 TO 255
   conf = INA3221_read(n)
   PRINT HEX$(conf,4)
 NEXT n
 PRINT
 PRINT INA3221_Current(1,0.00909)' 0.01 || with 0.1
 PRINT INA3221_Current(2,0.00909)
 PRINT INA3221_Current(3,0.00909)
 PRINT
 PRINT INA3221_ShuntVoltage(1)/1000000
 PRINT INA3221_ShuntVoltage(2)/1000000
 PRINT INA3221_ShuntVoltage(3)/1000000
 PRINT
 PRINT INA3221_Voltage(1)
 PRINT INA3221_Voltage(2)
 PRINT INA3221_Voltage(3)
 
 ' any PWM current source needs special consideration.
 cur = instCurrent(2,0.00856)
 PRINT cur ;" av A"
 PRINT MATH(MAX PVcurrent()); " max A"
 
 FOR n = 0 TO 99
   PRINT PVcurrent(n)
 NEXT n
 I2C2 CLOSE
 
FUNCTION instCurrent(channel AS INTEGER, r AS FLOAT) AS FLOAT
 'local integer register = channel * 2
 INA3221_enable_channel 1 << (channel-1)
 INA3221_set_Averaging 0
 INA3221_set_Volt_Time 1
 INA3221_set_Shunt_Time 1
 
 INA3221_set_Mode 1
 DO
 LOOP UNTIL INA3221_Ready()
 
 FOR n = 0 TO 99
   PVcurrent(n) = INA3221_Current(channel,r)
   INA3221_set_Mode 1
   'pause 0.1
 NEXT n
 instCurrent = MATH(MEAN PVcurrent())
END FUNCTION
 
FUNCTION INA3221_read(reg AS INTEGER) AS INTEGER
 LOCAL registers$
 I2C2 WRITE ina3221addr,0,1,reg
 I2C2 READ ina3221addr,0,2,registers$
 INA3221_read = STR2BIN(INT16,registers$,BIG)
END FUNCTION
 
 
SUB INA3221_write reg AS INTEGER, value AS INTEGER
 LOCAL INTEGER hibyte, lobyte
 lobyte = value AND &hFF
 hibyte = (value >> 8) AND &hFF
 I2C2 WRITE ina3221addr,0,3,reg,hibyte,lobyte
END SUB
 
SUB INA3221_reset
 LOCAL INTEGER config
 config = INA3221_read(0)
 config = config OR &h8000
 INA3221_write(0,config)
END SUB
 
SUB INA3221_set_Mode INA_Mode%
 LOCAL INTEGER config, x
 x = INA_Mode% AND &b111
 config = INA3221_read(0) AND &b0111111111111000
 config = config OR x
 INA3221_write(0,config)
END SUB
 
SUB INA3221_enable_channel INA_Mode%
 LOCAL INTEGER config, x
 x = (INA_Mode% AND &b111) << 12
 config = INA3221_read(0) AND &b0000111111111111
 config = config OR x
 INA3221_write(0,config)
END SUB
 
SUB INA3221_set_Averaging INA_Mode%
 LOCAL INTEGER config, x
 x = (INA_Mode% AND &b111) << 9
 config = INA3221_read(0) AND &b0111000111111111
 config = config OR x
 INA3221_write(0,config)
END SUB
 
SUB INA3221_set_Volt_Time INA_Mode%
 LOCAL INTEGER config, x
 x = (INA_Mode% AND &b111) << 6
 config = INA3221_read(0) AND &b0111111000111111
 config = config OR x
 INA3221_write(0,config)
END SUB
 
SUB INA3221_set_Shunt_Time INA_Mode%
 LOCAL INTEGER config,  x
 x = (INA_Mode% AND &b111) << 3
 config = INA3221_read(0) AND &b0111111111000111
 config = config OR x
 INA3221_write(0,config)
END SUB
 ' current shunt voltage register contains 40uV per bit
FUNCTION INA3221_ShuntVoltage(channel AS INTEGER)AS INTEGER
 LOCAL INTEGER register = channel * 2 - 1
 INA3221_ShuntVoltage = INA3221_read(register)/8 * 40 ' microvolts
END FUNCTION
 
FUNCTION INA3221_Current(channel AS INTEGER,r AS FLOAT) AS FLOAT
 LOCAL INTEGER uV
 uV = INA3221_ShuntVoltage(channel)
 INA3221_Current = uV/r /1000/1000 ' I = E/R
END FUNCTION
 
 ' volts register resolution 8 mV per bit
FUNCTION INA3221_Voltage(channel AS INTEGER) AS FLOAT
 LOCAL INTEGER register = channel * 2
 INA3221_Voltage = INA3221_read(register) / 1000 ' volts
END FUNCTION
 
FUNCTION INA3221_Ready() AS INTEGER
 INA3221_Ready = INA3221_read(15) AND 1
END FUNCTION



The 'better' averaging function:
 ' 100 rapid current reads for PWM PV regulators
FUNCTION instCurrent(channel AS INTEGER, r AS FLOAT) AS FLOAT
 LOCAL INTEGER n,a,b, armed
 LOCAL FLOAT m, mi, currents
 INA3221_enable_channel 1 << (channel-1)
 INA3221_set_Averaging 0
 INA3221_set_Volt_Time 1
 INA3221_set_Shunt_Time 2
 
 INA3221_set_Mode 1
 DO
 LOOP UNTIL INA3221_Ready()
 
 FOR n = 0 TO 99
   PVcurrent(n) = INA3221_Current(channel,r)
   INA3221_set_Mode 1
   'pause 0.1
 NEXT n
 
 m = MATH(MAX PVcurrent())
 mi = MATH(MIN PVcurrent())
 IF (m - mi) > 3 THEN
   m = m -1
   mi = mi + 1
   FOR n = 0 TO 99
     IF PVcurrent(n) < mi THEN
       armed = 1
       EXIT FOR
     ENDIF
   NEXT n
   IF armed THEN
     FOR a = n TO 99
       IF PVcurrent(a) > m THEN EXIT FOR
     NEXT a
     armed = 0
     FOR n = 99 TO 0 STEP -1
       IF PVcurrent(n) > m THEN
         armed = 1
         EXIT FOR
       ENDIF
     NEXT n
     FOR b = n TO 0 STEP -1
       IF PVcurrent(b) < mi THEN EXIT FOR
     NEXT b
     b = b + 1
   ENDIF
   IF armed AND (b-a) > 20 THEN
     FOR n = a TO b
       currents = currents + PVcurrent(n)
     NEXT n
     IF verbose THEN PRINT STR$(currents/(b-a),3,2);" ";STR$(MATH(MEAN PVcurrent()),3,2);" ";a;" to ";b
     instCurrent = currents/(b-a)
   ELSE
     instCurrent = MATH(MEAN PVcurrent())
   ENDIF
 ELSE
   instCurrent = MATH(MEAN PVcurrent())
 ENDIF
 
END FUNCTION


The rack:



Top of cabinet - router/accesspoint
Top shelf - RPi running cumulus weather software. Hanging of it is a picomite acting as a Davis weather station look-a-like, a micromite running my watering systems monitor and the adjacent box containing the armmiteF4 running the battery monitor.
The watering micromite will eventually hang of the armmiteF4 instead of the RPi.
Ser2net on the RPi gives me remote access to all 'mites.
Next is the Repeater radio
Then a WEBmite monitoring the radio and sharing the case with another RPi running Allstar internet radio linking software.
The WEBmite will get data from the Armmite in the next stage.
The DC distribution is next with the INA3221 in the small grey box on the right.
The mains charger which gets a bit of use in winter is out of sight.

Jim
VK7JH
MMedit   MMBasic Help
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4238
Posted: 07:13am 19 Dec 2023
Copy link to clipboard 
Print this post

Hi TassyJim,

Good that you added an explanation of what it is. I could have been mistaken easily.
Teletext decoder ? Amateure radio IF test set ? I assume these boxes are used for their metal peices, and contain the circuits you describe...

Volhout
PicomiteVGA PETSCII ROBOTS
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6098
Posted: 07:20am 19 Dec 2023
Copy link to clipboard 
Print this post

The rack cabinet and the teletext module came from a local telecom disposal sale.
Most of the other hardware came from my employer from 20+ years ago. They have been sitting in my shed waiting for a use.
I don't throw much out and I have a big shed.

Jim
VK7JH
MMedit   MMBasic Help
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 01:43pm 19 Dec 2023
Copy link to clipboard 
Print this post

Impressive, but can you explain more fully what you are doing with what kind and capacity of battery, solar, and load?

Also, what range does that 0.01 shunt give you?

Can you provide a link to the module you used?

~
Edited 2023-12-19 23:45 by lizby
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6098
Posted: 07:45pm 19 Dec 2023
Copy link to clipboard 
Print this post

This is the module I used
https://www.ebay.com.au/itm/325401704422

There are a couple of designs out there but all that I saw were basically the same with 0.1 ohm shunts.
The fullscale shunt voltage for the IC is +-163.8mV so with the shunt of 0.1 this gives 1.638 amps
With the external shunt of 0.01 ohms this gives a more useful +-16.38 amps. I used 5% resistors for the shunt so I don't consider my readings any better than that without some tweaking.

The system has a 12V 200W solar panel and 2 X 100Ah AGM batteries.
It also has mains power available for when the sun has a few days off.

The load currently is a base load of 1.3A with peak load of ~11 amps for anything up to 6 hours a day (but usually much less)

The radio is an amateur radio repeater serving the local area and linked around the world via the Internet linking on the RPi.

The old system used a micromite and ACS712 sensors for about 6 years. I have logs starting in June 2017.
I will be adding the car charging rate to the mix soon, ready for when I finally get mains solar fitted in a few months. Until I have that installed I can't finish the plans for load control around the house. Car charger, ride-on mower charger and bore pump and garden watering are all candidates for control to suit the sun and all doable with the armmiteF4.

Jim
VK7JH
MMedit   MMBasic Help
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 08:04pm 19 Dec 2023
Copy link to clipboard 
Print this post

Thanks. I'm happy with using a SONOFF device with Tasmota flashed flashed to get current measurements for mains voltages (with wifi reporting), but I've been looking for similar for 12V DC.

My big problem is trying to run my 120V AC shallow well pump through an inverter. It only runs 6-8 times a day for about 70 seconds at a time, but it draws at a rate of 1100 watts for that time, and I don't know what the surge wattage is. Overall daily consumption is less than 500 watts.

For that, I would need to be able to measure 100 amps at 12 volts (and perhaps I don't know how much overhead).

This INA3221 looks suitable to me for everything else I want to do.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4238
Posted: 09:08am 20 Dec 2023
Copy link to clipboard 
Print this post

@Lizby,

There are plenty 1 miliOhm resistors available (giving 163A range), such as:



But if you do not need to be accurate, why not use piece of copper wire.
There are plenty online calculators that tell you how many mili-ohm per meter/foot an AWG6 or whatever you use is. Then remove isolation at 2 locations of that wire that are X feet/meter appart, and connect to the INA3221.

1 mili ohm is what you would need.

The wire will have some thermal drift, but I am assuming you do not need to be 1% accurate. 5%-10% is definitely do-able with copper wire.

Volhout
PicomiteVGA PETSCII ROBOTS
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 02:52pm 20 Dec 2023
Copy link to clipboard 
Print this post

Thank you for the examples of what to look for. Appears not available at digikey, upwards of $20 from Mouser, and about $3.50 each for 5 in Chinesium for the shunt resistor.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4238
Posted: 03:15pm 20 Dec 2023
Copy link to clipboard 
Print this post

Hi Lizby,

Digikey @$0.73 each, stock part.
It can dissipate 6 watt (@70 ambient), so of you want to run 100A continuous (equals 10 watt) you need to put a fan on it.



Volhout
Edited 2023-12-21 01:16 by Volhout
PicomiteVGA PETSCII ROBOTS
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 04:17pm 20 Dec 2023
Copy link to clipboard 
Print this post

Thank you for that. When I searched, everything it found said "out of stock". Searching on that specific part number, I find 4,788 In Stock at a price of $.80 for one.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6098
Posted: 07:52pm 20 Dec 2023
Copy link to clipboard 
Print this post

Running for 70 seconds at atime, you might get away without a fan as long as it is in free air and not too much circuitboard etc around it.

With my setup, I have come to the conclusion that I should have removed the 0.1 ohm resistors on the module and used the 0.01 resistors on their own. I am getting a bit of crosstalk. Not enough to upset the calculations but annoying. 10 amps of solar and the mains indicates 0.04 amps even though I know it is off.

I will know better next time.

Lizby,
Instead of the INA3221, look at the INA219. It is single channel and has adjustable gain etc so might be easier to use in your case.


Jim
VK7JH
MMedit   MMBasic Help
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 08:23pm 20 Dec 2023
Copy link to clipboard 
Print this post

  TassyJim said  Instead of the INA3221, look at the INA219


Thanks--I'll order several.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024