gobot.io/x/gobot@v1.16.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 import ( 11 "gobot.io/x/gobot" 12 ) 13 14 // INA3221Channel type that defines which INA3221 channel to read from. 15 type INA3221Channel uint8 16 17 const ( 18 ina3221Address uint8 = 0x40 // 1000000 (A0+A1=GND) 19 ina3221Read uint8 = 0x01 20 ina3221RegConfig uint8 = 0x00 // CONFIG REGISTER (R/W) 21 ina3221ConfigReset uint16 = 0x8000 // Reset Bit 22 ina3221ConfigEnableChan1 uint16 = 0x4000 // Enable INA3221 Channel 1 23 ina3221ConfigEnableChan2 uint16 = 0x2000 // Enable INA3221 Channel 2 24 ina3221ConfigEnableChan3 uint16 = 0x1000 // Enable INA3221 Channel 3 25 ina3221ConfigAvg2 uint16 = 0x0800 // AVG Samples Bit 2 - See table 3 spec 26 ina3221ConfigAvg1 uint16 = 0x0400 // AVG Samples Bit 1 - See table 3 spec 27 ina3221ConfigAvg0 uint16 = 0x0200 // AVG Samples Bit 0 - See table 3 spec 28 ina3221ConfigVBusCT2 uint16 = 0x0100 // VBUS bit 2 Conversion time - See table 4 spec 29 ina3221ConfigVBusCT1 uint16 = 0x0080 // VBUS bit 1 Conversion time - See table 4 spec 30 ina3221ConfigVBusCT0 uint16 = 0x0040 // VBUS bit 0 Conversion time - See table 4 spec 31 ina3221ConfigVShCT2 uint16 = 0x0020 // Vshunt bit 2 Conversion time - See table 5 spec 32 ina3221ConfigVShCT1 uint16 = 0x0010 // Vshunt bit 1 Conversion time - See table 5 spec 33 ina3221ConfigVShCT0 uint16 = 0x0008 // Vshunt bit 0 Conversion time - See table 5 spec 34 ina3221ConfigMode2 uint16 = 0x0004 // Operating Mode bit 2 - See table 6 spec 35 ina3221ConfigMode1 uint16 = 0x0002 // Operating Mode bit 1 - See table 6 spec 36 ina3221ConfigMode0 uint16 = 0x0001 // Operating Mode bit 0 - See table 6 spec 37 ina3221RegShuntVoltage1 uint8 = 0x01 // SHUNT VOLTAGE REGISTER (R) 38 ina3221RegBusVoltage1 uint8 = 0x02 // BUS VOLTAGE REGISTER (R) 39 ina3221ShuntResistorValue float64 = 0.1 // default shunt resistor value of 0.1 Ohm 40 41 INA3221Channel1 INA3221Channel = 1 42 INA3221Channel2 INA3221Channel = 2 43 INA3221Channel3 INA3221Channel = 3 44 ) 45 46 // INA3221Driver is a driver for the INA3221 three-channel current and bus voltage monitoring device. 47 type INA3221Driver struct { 48 name string 49 connector Connector 50 connection Connection 51 Config 52 halt chan bool 53 } 54 55 // NewINA3221Driver creates a new driver with the specified i2c interface. 56 // Params: 57 // conn Connector - the Adaptor to use with this Driver 58 // 59 // Optional params: 60 // i2c.WithBus(int): bus to use with this driver 61 // i2c.WithAddress(int): address to use with this driver 62 func NewINA3221Driver(c Connector, options ...func(Config)) *INA3221Driver { 63 i := &INA3221Driver{ 64 name: gobot.DefaultName("INA3221"), 65 connector: c, 66 Config: NewConfig(), 67 } 68 69 for _, option := range options { 70 option(i) 71 } 72 73 return i 74 } 75 76 // Name returns the name of the device. 77 func (i *INA3221Driver) Name() string { 78 return i.name 79 } 80 81 // SetName sets the name of the device. 82 func (i *INA3221Driver) SetName(name string) { 83 i.name = name 84 } 85 86 // Connection returns the connection of the device. 87 func (i *INA3221Driver) Connection() gobot.Connection { 88 return i.connector.(gobot.Connection) 89 } 90 91 // Start initializes the INA3221 92 func (i *INA3221Driver) Start() error { 93 var err error 94 bus := i.GetBusOrDefault(i.connector.GetDefaultBus()) 95 address := i.GetAddressOrDefault(int(ina3221Address)) 96 97 if i.connection, err = i.connector.GetConnection(address, bus); err != nil { 98 return err 99 } 100 101 if err := i.initialize(); err != nil { 102 return err 103 } 104 105 return nil 106 } 107 108 // Halt halts the device. 109 func (i *INA3221Driver) Halt() error { 110 return nil 111 } 112 113 // GetBusVoltage gets the bus voltage in Volts 114 func (i *INA3221Driver) GetBusVoltage(channel INA3221Channel) (float64, error) { 115 value, err := i.getBusVoltageRaw(channel) 116 if err != nil { 117 return 0, err 118 } 119 120 return float64(value) * .001, nil 121 } 122 123 // GetShuntVoltage Gets the shunt voltage in mV 124 func (i *INA3221Driver) GetShuntVoltage(channel INA3221Channel) (float64, error) { 125 value, err := i.getShuntVoltageRaw(channel) 126 if err != nil { 127 return 0, err 128 } 129 130 return float64(value) * float64(.005), nil 131 } 132 133 // GetCurrent gets the current value in mA, taking into account the config settings and current LSB 134 func (i *INA3221Driver) GetCurrent(channel INA3221Channel) (float64, error) { 135 value, err := i.GetShuntVoltage(channel) 136 if err != nil { 137 return 0, err 138 } 139 140 ma := value / ina3221ShuntResistorValue 141 return ma, nil 142 } 143 144 // GetLoadVoltage gets the load voltage in mV 145 func (i *INA3221Driver) GetLoadVoltage(channel INA3221Channel) (float64, error) { 146 bv, err := i.GetBusVoltage(channel) 147 if err != nil { 148 return 0, err 149 } 150 151 sv, err := i.GetShuntVoltage(channel) 152 if err != nil { 153 return 0, err 154 } 155 156 return bv + (sv / 1000.0), nil 157 } 158 159 // getBusVoltageRaw gets the raw bus voltage (16-bit signed integer, so +-32767) 160 func (i *INA3221Driver) getBusVoltageRaw(channel INA3221Channel) (int16, error) { 161 val, err := i.readWordFromRegister(ina3221RegBusVoltage1 + (uint8(channel)-1)*2) 162 if err != nil { 163 return 0, err 164 } 165 166 value := int32(val) 167 if value > 0x7FFF { 168 value -= 0x10000 169 } 170 171 return int16(value), nil 172 } 173 174 // getShuntVoltageRaw gets the raw shunt voltage (16-bit signed integer, so +-32767) 175 func (i *INA3221Driver) getShuntVoltageRaw(channel INA3221Channel) (int16, error) { 176 val, err := i.readWordFromRegister(ina3221RegShuntVoltage1 + (uint8(channel)-1)*2) 177 if err != nil { 178 return 0, err 179 } 180 181 value := int32(val) 182 if value > 0x7FFF { 183 value -= 0x10000 184 } 185 186 return int16(value), nil 187 } 188 189 // reads word from supplied register address 190 func (i *INA3221Driver) readWordFromRegister(reg uint8) (uint16, error) { 191 val, err := i.connection.ReadWordData(reg) 192 if err != nil { 193 return 0, err 194 } 195 196 return uint16(((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8)), nil 197 } 198 199 // initialize initializes the INA3221 device 200 func (i *INA3221Driver) initialize() error { 201 config := ina3221ConfigEnableChan1 | 202 ina3221ConfigEnableChan2 | 203 ina3221ConfigEnableChan3 | 204 ina3221ConfigAvg1 | 205 ina3221ConfigVBusCT2 | 206 ina3221ConfigVShCT2 | 207 ina3221ConfigMode2 | 208 ina3221ConfigMode1 | 209 ina3221ConfigMode0 210 211 return i.connection.WriteBlockData(ina3221RegConfig, []byte{byte(config >> 8), byte(config & 0x00FF)}) 212 }