gobot.io/x/gobot/v2@v2.1.0/drivers/i2c/ina3221_driver.go (about) 1 package i2c 2 3 // INA3221Driver is a driver for the Texas Instruments INA3221 device. The INA3221 is a three-channel 4 // current and bus voltage monitor with an I2C and SMBUS compatible interface. 5 // 6 // INA3221 data sheet and specifications can be found at http://www.ti.com/product/INA3221 7 // 8 // This module was tested with SwitchDoc Labs INA3221 breakout board found at http://www.switchdoc.com/ 9 10 // INA3221Channel type that defines which INA3221 channel to read from. 11 type INA3221Channel uint8 12 13 const ( 14 ina3221DefaultAddress = 0x40 // 1000000 (A0+A1=GND) 15 ina3221Read uint8 = 0x01 16 ina3221RegConfig uint8 = 0x00 // CONFIG REGISTER (R/W) 17 ina3221ConfigReset uint16 = 0x8000 // Reset Bit 18 ina3221ConfigEnableChan1 uint16 = 0x4000 // Enable INA3221 Channel 1 19 ina3221ConfigEnableChan2 uint16 = 0x2000 // Enable INA3221 Channel 2 20 ina3221ConfigEnableChan3 uint16 = 0x1000 // Enable INA3221 Channel 3 21 ina3221ConfigAvg2 uint16 = 0x0800 // AVG Samples Bit 2 - See table 3 spec 22 ina3221ConfigAvg1 uint16 = 0x0400 // AVG Samples Bit 1 - See table 3 spec 23 ina3221ConfigAvg0 uint16 = 0x0200 // AVG Samples Bit 0 - See table 3 spec 24 ina3221ConfigVBusCT2 uint16 = 0x0100 // VBUS bit 2 Conversion time - See table 4 spec 25 ina3221ConfigVBusCT1 uint16 = 0x0080 // VBUS bit 1 Conversion time - See table 4 spec 26 ina3221ConfigVBusCT0 uint16 = 0x0040 // VBUS bit 0 Conversion time - See table 4 spec 27 ina3221ConfigVShCT2 uint16 = 0x0020 // Vshunt bit 2 Conversion time - See table 5 spec 28 ina3221ConfigVShCT1 uint16 = 0x0010 // Vshunt bit 1 Conversion time - See table 5 spec 29 ina3221ConfigVShCT0 uint16 = 0x0008 // Vshunt bit 0 Conversion time - See table 5 spec 30 ina3221ConfigMode2 uint16 = 0x0004 // Operating Mode bit 2 - See table 6 spec 31 ina3221ConfigMode1 uint16 = 0x0002 // Operating Mode bit 1 - See table 6 spec 32 ina3221ConfigMode0 uint16 = 0x0001 // Operating Mode bit 0 - See table 6 spec 33 ina3221RegShuntVoltage1 uint8 = 0x01 // SHUNT VOLTAGE REGISTER (R) 34 ina3221RegBusVoltage1 uint8 = 0x02 // BUS VOLTAGE REGISTER (R) 35 ina3221ShuntResistorValue float64 = 0.1 // default shunt resistor value of 0.1 Ohm 36 37 INA3221Channel1 INA3221Channel = 1 38 INA3221Channel2 INA3221Channel = 2 39 INA3221Channel3 INA3221Channel = 3 40 ) 41 42 // INA3221Driver is a driver for the INA3221 three-channel current and bus voltage monitoring device. 43 type INA3221Driver struct { 44 *Driver 45 halt chan bool 46 } 47 48 // NewINA3221Driver creates a new driver with the specified i2c interface. 49 // Params: 50 // c Connector - the Adaptor to use with this Driver 51 // 52 // Optional params: 53 // i2c.WithBus(int): bus to use with this driver 54 // i2c.WithAddress(int): address to use with this driver 55 func NewINA3221Driver(c Connector, options ...func(Config)) *INA3221Driver { 56 i := &INA3221Driver{ 57 Driver: NewDriver(c, "INA3221", ina3221DefaultAddress), 58 } 59 i.afterStart = i.initialize 60 61 for _, option := range options { 62 option(i) 63 } 64 65 return i 66 } 67 68 // GetBusVoltage gets the bus voltage in Volts 69 func (i *INA3221Driver) GetBusVoltage(channel INA3221Channel) (float64, error) { 70 value, err := i.getBusVoltageRaw(channel) 71 if err != nil { 72 return 0, err 73 } 74 75 return float64(value) * .001, nil 76 } 77 78 // GetShuntVoltage Gets the shunt voltage in mV 79 func (i *INA3221Driver) GetShuntVoltage(channel INA3221Channel) (float64, error) { 80 value, err := i.getShuntVoltageRaw(channel) 81 if err != nil { 82 return 0, err 83 } 84 85 return float64(value) * float64(.005), nil 86 } 87 88 // GetCurrent gets the current value in mA, taking into account the config settings and current LSB 89 func (i *INA3221Driver) GetCurrent(channel INA3221Channel) (float64, error) { 90 value, err := i.GetShuntVoltage(channel) 91 if err != nil { 92 return 0, err 93 } 94 95 ma := value / ina3221ShuntResistorValue 96 return ma, nil 97 } 98 99 // GetLoadVoltage gets the load voltage in mV 100 func (i *INA3221Driver) GetLoadVoltage(channel INA3221Channel) (float64, error) { 101 bv, err := i.GetBusVoltage(channel) 102 if err != nil { 103 return 0, err 104 } 105 106 sv, err := i.GetShuntVoltage(channel) 107 if err != nil { 108 return 0, err 109 } 110 111 return bv + (sv / 1000.0), nil 112 } 113 114 // getBusVoltageRaw gets the raw bus voltage (16-bit signed integer, so +-32767) 115 func (i *INA3221Driver) getBusVoltageRaw(channel INA3221Channel) (int16, error) { 116 val, err := i.readWordFromRegister(ina3221RegBusVoltage1 + (uint8(channel)-1)*2) 117 if err != nil { 118 return 0, err 119 } 120 121 value := int32(val) 122 if value > 0x7FFF { 123 value -= 0x10000 124 } 125 126 return int16(value), nil 127 } 128 129 // getShuntVoltageRaw gets the raw shunt voltage (16-bit signed integer, so +-32767) 130 func (i *INA3221Driver) getShuntVoltageRaw(channel INA3221Channel) (int16, error) { 131 val, err := i.readWordFromRegister(ina3221RegShuntVoltage1 + (uint8(channel)-1)*2) 132 if err != nil { 133 return 0, err 134 } 135 136 value := int32(val) 137 if value > 0x7FFF { 138 value -= 0x10000 139 } 140 141 return int16(value), nil 142 } 143 144 // reads word from supplied register address 145 func (i *INA3221Driver) readWordFromRegister(reg uint8) (uint16, error) { 146 val, err := i.connection.ReadWordData(reg) 147 if err != nil { 148 return 0, err 149 } 150 151 return uint16(((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8)), nil 152 } 153 154 // initialize initializes the INA3221 device 155 func (i *INA3221Driver) initialize() error { 156 config := ina3221ConfigEnableChan1 | 157 ina3221ConfigEnableChan2 | 158 ina3221ConfigEnableChan3 | 159 ina3221ConfigAvg1 | 160 ina3221ConfigVBusCT2 | 161 ina3221ConfigVShCT2 | 162 ina3221ConfigMode2 | 163 ina3221ConfigMode1 | 164 ina3221ConfigMode0 165 166 return i.connection.WriteBlockData(ina3221RegConfig, []byte{byte(config >> 8), byte(config & 0x00FF)}) 167 }