mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-21 23:19:00 +00:00
@@ -0,0 +1,202 @@
|
||||
package ina219
|
||||
|
||||
import (
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/internal/legacy"
|
||||
)
|
||||
|
||||
// An INA219 device.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint16
|
||||
config Config
|
||||
}
|
||||
|
||||
// Create a new INA219 device with the default configuration
|
||||
// and the given I2C bus at the default address.
|
||||
//
|
||||
// Set Address after New to change the address.
|
||||
//
|
||||
// Call Configure after New to write the configuration to the
|
||||
// device. If you don't call Configure, the device may have a
|
||||
// different configuration and the power divider and current
|
||||
// multiplier are probably wrong.
|
||||
func New(bus drivers.I2C) Device {
|
||||
return Device{
|
||||
bus: bus,
|
||||
Address: Address,
|
||||
config: Config32V2A,
|
||||
}
|
||||
}
|
||||
|
||||
// Set the configuration for the device. This only changes the
|
||||
// configuration in memory, not on the device. Call Configure
|
||||
// to write the configuration to the device.
|
||||
func (d *Device) SetConfig(config Config) {
|
||||
d.config = config
|
||||
}
|
||||
|
||||
// Write the current configuration to the device.
|
||||
func (d *Device) Configure() (err error) {
|
||||
if err = d.WriteRegister(
|
||||
RegConfig,
|
||||
d.config.RegisterValue(),
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = d.WriteRegister(
|
||||
RegCalibration,
|
||||
d.config.Calibration.RegisterValue(),
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var readConfig Config
|
||||
// make sure the configuration is read back correctly
|
||||
if readConfig, err = d.ReadConfig(); err != nil {
|
||||
return
|
||||
} else if readConfig.RegisterValue() != d.config.RegisterValue() {
|
||||
err = ErrConfigMismatch{}
|
||||
} else if readConfig.Calibration.RegisterValue() != d.config.Calibration.RegisterValue() {
|
||||
err = ErrConfigMismatch{}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Trigger a conversion. This is only necessary if the device is in
|
||||
// trigger mode. In continuous mode (the default), the device will
|
||||
// automatically trigger conversions and this has no effect. See
|
||||
// config.go.
|
||||
//
|
||||
// Triggering a conversion or reading the "power" register resets
|
||||
// the conversion ready bit.
|
||||
func (d *Device) Trigger() (err error) {
|
||||
// Only trigger if the mode is one of the triggered modes.
|
||||
if ModeTriggered(d.config.Mode) {
|
||||
err = d.WriteRegister(RegConfig, d.config.RegisterValue())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Measurements reads the bus voltage, shunt voltage, current, and power
|
||||
// from the device.
|
||||
func (d *Device) Measurements() (
|
||||
busVoltage int16,
|
||||
shuntVoltage int16,
|
||||
current float32,
|
||||
power float32,
|
||||
err error,
|
||||
) {
|
||||
// Attempt to read bus voltage first, so we can check for overflow
|
||||
// or conversion not ready.
|
||||
if busVoltage, err = d.BusVoltage(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Read the rest of the values, reading Power last, which resets
|
||||
// the conversion ready bit (relevant for triggered modes).
|
||||
if shuntVoltage, err = d.ShuntVoltage(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if current, err = d.Current(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if power, err = d.Power(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BusVoltage reads the "bus" voltage in millivolts.
|
||||
//
|
||||
// It returns an error if the value is invalid due to overflow
|
||||
// or if the conversion is not ready yet. In a continuous mode
|
||||
// there should always be a measurement available after the
|
||||
// device is ready. See above notes on Trigger.
|
||||
func (d *Device) BusVoltage() (voltage int16, err error) {
|
||||
val, err := d.ReadRegister(RegBusVoltage)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// The overflow bit is set, so the values are invalid.
|
||||
if val&(1<<0) != 0 {
|
||||
err = ErrOverflow{}
|
||||
return
|
||||
}
|
||||
|
||||
// The conversion is not ready yet.
|
||||
if ModeTriggered(d.config.Mode) && val&(1<<1) != 0 {
|
||||
err = ErrNotReady{}
|
||||
return
|
||||
}
|
||||
|
||||
voltage = (int16(val) >> 3) * 4
|
||||
return
|
||||
}
|
||||
|
||||
// ShuntVoltage reads the "shunt" voltage in 100ths of a millivolt.
|
||||
func (d *Device) ShuntVoltage() (voltage int16, err error) {
|
||||
return d.ReadRegister(RegShuntVoltage)
|
||||
}
|
||||
|
||||
// Current reads the current in milliamps.
|
||||
func (d *Device) Current() (current float32, err error) {
|
||||
val, err := d.ReadRegister(RegCurrent)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
current = float32(val) / d.config.CurrentDivider
|
||||
return
|
||||
}
|
||||
|
||||
// Power reads the power in milliwatts.
|
||||
func (d *Device) Power() (power float32, err error) {
|
||||
val, err := d.ReadRegister(RegPower)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
power = float32(val) * d.config.PowerMultiplier
|
||||
return
|
||||
}
|
||||
|
||||
// Read the configuration from the device.
|
||||
func (d *Device) ReadConfig() (config Config, err error) {
|
||||
var cfg, cal int16
|
||||
if cfg, err = d.ReadRegister(RegConfig); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cal, err = d.ReadRegister(RegCalibration); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
config = NewConfig(cfg, cal)
|
||||
return
|
||||
}
|
||||
|
||||
// Read a register from the device.
|
||||
func (d *Device) ReadRegister(reg uint8) (val int16, err error) {
|
||||
buf := make([]byte, 2)
|
||||
|
||||
err = legacy.ReadRegister(d.bus, uint8(d.Address), reg, buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
val = int16(buf[0])<<8 | int16(buf[1]&0xff)
|
||||
return
|
||||
}
|
||||
|
||||
// Write to a register on the device.
|
||||
func (d *Device) WriteRegister(reg uint8, val uint16) error {
|
||||
buf := []byte{byte(val >> 8), byte(val & 0xff)}
|
||||
return legacy.WriteRegister(d.bus, uint8(d.Address), reg, buf)
|
||||
}
|
||||
Reference in New Issue
Block a user