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: AustraliaPosts: 6098 |
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 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 FOR n = 0 TO 17 conf = INA3221_read(n) PRINT HEX$(conf,4), conf NEXT n FOR n = 254 TO 255 conf = INA3221_read(n) PRINT HEX$(conf,4) NEXT n PRINT INA3221_Current(1,0.00909)' 0.01 || with 0.1 PRINT INA3221_Current(2,0.00909) PRINT INA3221_Current(3,0.00909) PRINT INA3221_ShuntVoltage(1)/1000000 PRINT INA3221_ShuntVoltage(2)/1000000 PRINT INA3221_ShuntVoltage(3)/1000000 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: NetherlandsPosts: 4238 |
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: AustraliaPosts: 6098 |
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 StatesPosts: 3150 |
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: AustraliaPosts: 6098 |
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 StatesPosts: 3150 |
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: NetherlandsPosts: 4238 |
@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 StatesPosts: 3150 |
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: NetherlandsPosts: 4238 |
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 StatesPosts: 3150 |
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: AustraliaPosts: 6098 |
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 StatesPosts: 3150 |
Thanks--I'll order several. PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
Print this page |