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  }