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  }