├── .gitignore ├── README.md ├── SDL_Pi_INA3221.py └── testSDL_Pi_INA3221.py /.gitignore: -------------------------------------------------------------------------------- 1 | .*DS_Store 2 | *.pyc 3 | tx* 4 | .*.swp 5 | *.xml 6 | *.temp 7 | *.test 8 | nohup.out 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Raspberry Pi Python Library for SwitchDoc Labs INA3221 Breakout Board and SunAirPlus 3 | 4 | SwitchDoc Labs, LLC September 2019 - updated to Python 3 5 | 6 | Run testINA3221.py to test all three channels 7 | 8 | More Information on www.switchdoc.com 9 | 10 | 11 | -------------------------------------------------------------------------------- /SDL_Pi_INA3221.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # SDL_Pi_INA3221.py Python Driver Code 4 | # SwitchDoc Labs March 4, 2015 5 | # V 1.2 6 | 7 | 8 | #encoding: utf-8 9 | 10 | from datetime import datetime 11 | 12 | import smbus 13 | 14 | # constants 15 | 16 | #/*========================================================================= 17 | # I2C ADDRESS/BITS 18 | # -----------------------------------------------------------------------*/ 19 | INA3221_ADDRESS = (0x40) # 1000000 (A0+A1=GND) 20 | INA3221_READ = (0x01) 21 | #/*=========================================================================*/ 22 | 23 | #/*========================================================================= 24 | # CONFIG REGISTER (R/W) 25 | # -----------------------------------------------------------------------*/ 26 | INA3221_REG_CONFIG = (0x00) 27 | # /*---------------------------------------------------------------------*/ 28 | INA3221_CONFIG_RESET = (0x8000) # Reset Bit 29 | 30 | INA3221_CONFIG_ENABLE_CHAN1 = (0x4000) # Enable Channel 1 31 | INA3221_CONFIG_ENABLE_CHAN2 = (0x2000) # Enable Channel 2 32 | INA3221_CONFIG_ENABLE_CHAN3 = (0x1000) # Enable Channel 3 33 | 34 | INA3221_CONFIG_AVG2 = (0x0800) # AVG Samples Bit 2 - See table 3 spec 35 | INA3221_CONFIG_AVG1 = (0x0400) # AVG Samples Bit 1 - See table 3 spec 36 | INA3221_CONFIG_AVG0 = (0x0200) # AVG Samples Bit 0 - See table 3 spec 37 | 38 | INA3221_CONFIG_VBUS_CT2 = (0x0100) # VBUS bit 2 Conversion time - See table 4 spec 39 | INA3221_CONFIG_VBUS_CT1 = (0x0080) # VBUS bit 1 Conversion time - See table 4 spec 40 | INA3221_CONFIG_VBUS_CT0 = (0x0040) # VBUS bit 0 Conversion time - See table 4 spec 41 | 42 | INA3221_CONFIG_VSH_CT2 = (0x0020) # Vshunt bit 2 Conversion time - See table 5 spec 43 | INA3221_CONFIG_VSH_CT1 = (0x0010) # Vshunt bit 1 Conversion time - See table 5 spec 44 | INA3221_CONFIG_VSH_CT0 = (0x0008) # Vshunt bit 0 Conversion time - See table 5 spec 45 | 46 | INA3221_CONFIG_MODE_2 = (0x0004) # Operating Mode bit 2 - See table 6 spec 47 | INA3221_CONFIG_MODE_1 = (0x0002) # Operating Mode bit 1 - See table 6 spec 48 | INA3221_CONFIG_MODE_0 = (0x0001) # Operating Mode bit 0 - See table 6 spec 49 | 50 | #/*=========================================================================*/ 51 | 52 | #/*========================================================================= 53 | # SHUNT VOLTAGE REGISTER (R) 54 | # -----------------------------------------------------------------------*/ 55 | INA3221_REG_SHUNTVOLTAGE_1 = (0x01) 56 | #/*=========================================================================*/ 57 | 58 | #/*========================================================================= 59 | # BUS VOLTAGE REGISTER (R) 60 | # -----------------------------------------------------------------------*/ 61 | INA3221_REG_BUSVOLTAGE_1 = (0x02) 62 | #/*=========================================================================*/ 63 | 64 | SHUNT_RESISTOR_VALUE = (0.1) # default shunt resistor value of 0.1 Ohm 65 | 66 | 67 | 68 | class SDL_Pi_INA3221(): 69 | 70 | 71 | 72 | ########################### 73 | # INA3221 Code 74 | ########################### 75 | def __init__(self, twi=1, addr=INA3221_ADDRESS, shunt_resistor = SHUNT_RESISTOR_VALUE ): 76 | self._bus = smbus.SMBus(twi) 77 | self._addr = addr 78 | config = INA3221_CONFIG_ENABLE_CHAN1 | \ 79 | INA3221_CONFIG_ENABLE_CHAN2 | \ 80 | INA3221_CONFIG_ENABLE_CHAN3 | \ 81 | INA3221_CONFIG_AVG1 | \ 82 | INA3221_CONFIG_VBUS_CT2 | \ 83 | INA3221_CONFIG_VSH_CT2 | \ 84 | INA3221_CONFIG_MODE_2 | \ 85 | INA3221_CONFIG_MODE_1 | \ 86 | INA3221_CONFIG_MODE_0 87 | 88 | 89 | 90 | 91 | self._write_register_little_endian(INA3221_REG_CONFIG, config) 92 | 93 | 94 | def _write(self, register, data): 95 | #print "addr =0x%x register = 0x%x data = 0x%x " % (self._addr, register, data) 96 | self._bus.write_byte_data(self._addr, register, data) 97 | 98 | 99 | def _read(self, data): 100 | 101 | returndata = self._bus.read_byte_data(self._addr, data) 102 | #print "addr = 0x%x data = 0x%x %i returndata = 0x%x " % (self._addr, data, data, returndata) 103 | return returndata 104 | 105 | 106 | def _read_register_little_endian(self, register): 107 | 108 | result = self._bus.read_word_data(self._addr,register) & 0xFFFF 109 | lowbyte = (result & 0xFF00)>>8 110 | highbyte = (result & 0x00FF) << 8 111 | switchresult = lowbyte + highbyte 112 | #print "Read 16 bit Word addr =0x%x register = 0x%x switchresult = 0x%x " % (self._addr, register, switchresult) 113 | return switchresult 114 | 115 | 116 | def _write_register_little_endian(self, register, data): 117 | 118 | data = data & 0xFFFF 119 | # reverse configure byte for little endian 120 | lowbyte = data>>8 121 | highbyte = (data & 0x00FF)<<8 122 | switchdata = lowbyte + highbyte 123 | self._bus.write_word_data(self._addr, register, switchdata) 124 | #print "Write 16 bit Word addr =0x%x register = 0x%x data = 0x%x " % (self._addr, register, data) 125 | 126 | 127 | 128 | def _getBusVoltage_raw(self, channel): 129 | #Gets the raw bus voltage (16-bit signed integer, so +-32767) 130 | 131 | value = self._read_register_little_endian(INA3221_REG_BUSVOLTAGE_1+(channel -1) *2) 132 | if value > 32767: 133 | value -= 65536 134 | return value 135 | 136 | def _getShuntVoltage_raw(self, channel): 137 | #Gets the raw shunt voltage (16-bit signed integer, so +-32767) 138 | 139 | value = self._read_register_little_endian(INA3221_REG_SHUNTVOLTAGE_1+(channel -1) *2) 140 | if value > 32767: 141 | value -= 65536 142 | return value 143 | 144 | # public functions 145 | 146 | def getBusVoltage_V(self, channel): 147 | # Gets the Bus voltage in volts 148 | 149 | value = self._getBusVoltage_raw(channel) 150 | return value * 0.001 151 | 152 | 153 | def getShuntVoltage_mV(self, channel): 154 | # Gets the shunt voltage in mV (so +-168.3mV) 155 | 156 | value = self._getShuntVoltage_raw(channel) 157 | return value * 0.005 158 | 159 | def getCurrent_mA(self, channel): 160 | #Gets the current value in mA, taking into account the config settings and current LSB 161 | 162 | valueDec = self.getShuntVoltage_mV(channel)/ SHUNT_RESISTOR_VALUE 163 | return valueDec; 164 | 165 | 166 | -------------------------------------------------------------------------------- /testSDL_Pi_INA3221.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_Pi_INA3221 4 | # John C. Shovic, SwitchDoc Labs 5 | # 03/05/2015 6 | # 7 | # 8 | 9 | # imports 10 | 11 | import sys 12 | import time 13 | import datetime 14 | import random 15 | import SDL_Pi_INA3221 16 | 17 | # Main Program 18 | 19 | print("") 20 | print("Test SDL_Pi_INA3221 Version 1.0 - SwitchDoc Labs") 21 | print("") 22 | print("Sample uses 0x40 and SunAirPlus board INA3221") 23 | print(" Will work with the INA3221 SwitchDoc Labs Breakout Board") 24 | print("Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S")) 25 | print("") 26 | 27 | filename = time.strftime("%Y-%m-%d%H:%M:%SRTCTest") + ".txt" 28 | starttime = datetime.datetime.utcnow() 29 | 30 | ina3221 = SDL_Pi_INA3221.SDL_Pi_INA3221(addr=0x40) 31 | 32 | # the three channels of the INA3221 named for SunAirPlus Solar Power Controller channels (www.switchdoc.com) 33 | LIPO_BATTERY_CHANNEL = 1 34 | SOLAR_CELL_CHANNEL = 2 35 | OUTPUT_CHANNEL = 3 36 | 37 | 38 | while True: 39 | 40 | print("------------------------------") 41 | shuntvoltage1 = 0 42 | busvoltage1 = 0 43 | current_mA1 = 0 44 | loadvoltage1 = 0 45 | 46 | 47 | busvoltage1 = ina3221.getBusVoltage_V(LIPO_BATTERY_CHANNEL) 48 | shuntvoltage1 = ina3221.getShuntVoltage_mV(LIPO_BATTERY_CHANNEL) 49 | # minus is to get the "sense" right. - means the battery is charging, + that it is discharging 50 | current_mA1 = ina3221.getCurrent_mA(LIPO_BATTERY_CHANNEL) 51 | 52 | loadvoltage1 = busvoltage1 + (shuntvoltage1 / 1000) 53 | 54 | print("LIPO_Battery Bus Voltage: %3.2f V " % busvoltage1) 55 | print("LIPO_Battery Shunt Voltage: %3.2f mV " % shuntvoltage1) 56 | print("LIPO_Battery Load Voltage: %3.2f V" % loadvoltage1) 57 | print("LIPO_Battery Current 1: %3.2f mA" % current_mA1) 58 | print 59 | 60 | shuntvoltage2 = 0 61 | busvoltage2 = 0 62 | current_mA2 = 0 63 | loadvoltage2 = 0 64 | 65 | busvoltage2 = ina3221.getBusVoltage_V(SOLAR_CELL_CHANNEL) 66 | shuntvoltage2 = ina3221.getShuntVoltage_mV(SOLAR_CELL_CHANNEL) 67 | current_mA2 = -ina3221.getCurrent_mA(SOLAR_CELL_CHANNEL) 68 | loadvoltage2 = busvoltage2 + (shuntvoltage2 / 1000) 69 | 70 | print("Solar Cell Bus Voltage 2: %3.2f V " % busvoltage2) 71 | print("Solar Cell Shunt Voltage 2: %3.2f mV " % shuntvoltage2) 72 | print("Solar Cell Load Voltage 2: %3.2f V" % loadvoltage2) 73 | print("Solar Cell Current 2: %3.2f mA" % current_mA2) 74 | print 75 | 76 | shuntvoltage3 = 0 77 | busvoltage3 = 0 78 | current_mA3 = 0 79 | loadvoltage3 = 0 80 | 81 | busvoltage3 = ina3221.getBusVoltage_V(OUTPUT_CHANNEL) 82 | shuntvoltage3 = ina3221.getShuntVoltage_mV(OUTPUT_CHANNEL) 83 | current_mA3 = ina3221.getCurrent_mA(OUTPUT_CHANNEL) 84 | loadvoltage3 = busvoltage3 + (shuntvoltage3 / 1000) 85 | 86 | print("Output Bus Voltage 3: %3.2f V " % busvoltage3) 87 | print("Output Shunt Voltage 3: %3.2f mV " % shuntvoltage3) 88 | print("Output Load Voltage 3: %3.2f V" % loadvoltage3) 89 | print("Output Current 3: %3.2f mA" % current_mA3) 90 | print() 91 | 92 | 93 | 94 | # 95 | time.sleep(2.0) 96 | --------------------------------------------------------------------------------