From 08564d0e3f519a38adf8cde0bf83207635a6dd55 Mon Sep 17 00:00:00 2001 From: Warren Guy <5602790+warrenguy@users.noreply.github.com> Date: Wed, 25 Sep 2024 05:45:33 +0100 Subject: [PATCH 1/5] add INA219 driver --- ina219/config.go | 183 ++++++++++++++++++++++++++++++++++++++++++ ina219/errors.go | 9 +++ ina219/ina219.go | 190 ++++++++++++++++++++++++++++++++++++++++++++ ina219/registers.go | 13 +++ 4 files changed, 395 insertions(+) create mode 100644 ina219/config.go create mode 100644 ina219/errors.go create mode 100644 ina219/ina219.go create mode 100644 ina219/registers.go diff --git a/ina219/config.go b/ina219/config.go new file mode 100644 index 000000000..4c0217915 --- /dev/null +++ b/ina219/config.go @@ -0,0 +1,183 @@ +package ina219 + +type Config struct { + // BusVoltageRange sets the bus voltage range. + BusVoltageRange BusVoltageRange + + // PGA sets the programmable gain amplifier. + PGA PGA + + // BusADC sets the bus ADC resolution. + BusADC BusADC + + // ShuntADC sets the shunt ADC resolution. + ShuntADC ShuntADC + + // Mode sets the operating mode. + Mode Mode + + // Calibration sets the calibration value for the expected + // voltage and current values. + Calibration Calibration + + // 1000 / uA per bit + CurrentDivider float32 + + // 1mW per bit + PowerMultiplier float32 +} + +// RegisterValue returns the register value of the configuration. +func (c *Config) RegisterValue() uint16 { + return c.BusVoltageRange.RegisterValue() | + c.PGA.RegisterValue() | + c.BusADC.RegisterValue() | + c.ShuntADC.RegisterValue() | + c.Mode.RegisterValue() +} + +// Generate a new configuration from a register value. +func NewConfig(config int16, calibration int16) Config { + return Config{ + BusVoltageRange: BusVoltageRange(config >> 13 & 0x1), + PGA: PGA(config >> 11 & 0x3), + BusADC: BusADC(config >> 7 & 0xF), + ShuntADC: ShuntADC(config >> 3 & 0xF), + Mode: Mode(config & 0x7), + Calibration: Calibration(calibration), + } +} + +// Configurations from +// https://github.com/adafruit/Adafruit_INA219/blob/master/Adafruit_INA219.cpp +var ( + // Config32V2A is a configuration for a 32V 2A range. + Config32V2A = Config{ + BusVoltageRange: Range32V, + PGA: PGA8, + BusADC: ADC12, + ShuntADC: SADC12, + Mode: ModeContShuntBus, + Calibration: Calibration16V400mA, + CurrentDivider: 10.0, + PowerMultiplier: 2.0, + } + + // Config32V1A is a configuration for a 32V 1A range. + Config32V1A = Config{ + BusVoltageRange: Range32V, + PGA: PGA8, + BusADC: ADC12, + ShuntADC: SADC12, + Mode: ModeContShuntBus, + Calibration: Calibration32V1A, + CurrentDivider: 25.0, + PowerMultiplier: 0.8, + } + + // Config16V400mA is a configuration for a 16V 400mA range. + Config16V400mA = Config{ + BusVoltageRange: Range16V, + PGA: PGA1, + BusADC: ADC12, + ShuntADC: SADC12, + Mode: ModeContShuntBus, + Calibration: Calibration16V400mA, + CurrentDivider: 20.0, + PowerMultiplier: 1.0, + } +) + +// BusVoltageRange is the bus voltage range. +type BusVoltageRange int8 + +const ( + Range16V BusVoltageRange = 0 // 0-16V + Range32V BusVoltageRange = 1 // 0-32V +) + +func (r BusVoltageRange) RegisterValue() uint16 { + return uint16(r) << 13 +} + +// PGA is the programmable gain amplifier. +type PGA int8 + +const ( + PGA1 PGA = 0 // 40mV + PGA2 PGA = 1 // 80mV + PGA4 PGA = 2 // 160mV + PGA8 PGA = 3 // 320mV +) + +func (p PGA) RegisterValue() uint16 { + return uint16(p) << 11 +} + +// BusADC is the bus ADC resolution. +type BusADC int8 + +const ( + ADC9 BusADC = 0 // 9-bit + ADC10 BusADC = 1 // 10-bit + ADC11 BusADC = 2 // 11-bit + ADC12 BusADC = 3 // 12-bit +) + +func (b BusADC) RegisterValue() uint16 { + return uint16(b) << 7 +} + +// ShuntADC is the shunt ADC resolution. +type ShuntADC int8 + +const ( + SADC9 ShuntADC = 0 // 9-bit + SADC10 ShuntADC = 1 // 10-bit + SADC11 ShuntADC = 2 // 11-bit + SADC12 ShuntADC = 3 // 12-bit +) + +func (s ShuntADC) RegisterValue() uint16 { + return uint16(s) << 3 +} + +// Mode is the operating mode. +type Mode int8 + +const ( + ModePowerDown Mode = 0 // power-down + ModeTrigShunt Mode = 1 // triggered shunt voltage + ModeTrigBus Mode = 2 // triggered bus voltage + ModeTrigShuntBus Mode = 3 // triggered shunt and bus voltage + ModeADCOff Mode = 4 // ADC off + ModeContShunt Mode = 5 // continuous shunt voltage + ModeContBus Mode = 6 // continuous bus voltage + ModeContShuntBus Mode = 7 // continuous shunt and bus voltage +) + +// ModeTriggered is a mask for triggered modes. +const ModeTriggeredMask Mode = 0x4 + +// ModeTriggered returns true if the mode is a triggered mode. +func ModeTriggered(m Mode) bool { + return m != ModePowerDown && m&ModeTriggeredMask == 0 +} + +func (m Mode) RegisterValue() uint16 { + return uint16(m) +} + +// Calibration is the calibration register for the INA219. Values from: +// https://github.com/adafruit/Adafruit_INA219/blob/master/Adafruit_INA219.cpp +type Calibration uint16 + +const ( + Calibration32V2A Calibration = 4096 + Calibration32V1A Calibration = 10240 + Calibration16V400mA Calibration = 8192 +) + +func (c Calibration) RegisterValue() uint16 { + return uint16(c) +} diff --git a/ina219/errors.go b/ina219/errors.go new file mode 100644 index 000000000..040dc18eb --- /dev/null +++ b/ina219/errors.go @@ -0,0 +1,9 @@ +package ina219 + +type ErrOverflow struct{} + +func (e ErrOverflow) Error() string { return "overflow" } + +type ErrNotReady struct{} + +func (e ErrNotReady) Error() string { return "not ready" } diff --git a/ina219/ina219.go b/ina219/ina219.go new file mode 100644 index 000000000..7f12134b0 --- /dev/null +++ b/ina219/ina219.go @@ -0,0 +1,190 @@ +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 + } + + err = d.WriteRegister( + RegCalibration, + d.config.Calibration.RegisterValue(), + ) + + 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 int32, + 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 int32, 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 val&(1<<1) != 0 { + err = ErrNotReady{} + return + } + + voltage = (int32(val) >> 3) * 4 + return +} + +// ShuntVoltage reads the "shunt" voltage in 100ths of a volt. +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) +} diff --git a/ina219/registers.go b/ina219/registers.go new file mode 100644 index 000000000..f1bae3afc --- /dev/null +++ b/ina219/registers.go @@ -0,0 +1,13 @@ +package ina219 + +// The default I2C address for this device. +const Address = 0x40 + +const ( + RegConfig uint8 = 0x0 + RegShuntVoltage uint8 = 0x1 + RegBusVoltage uint8 = 0x2 + RegPower uint8 = 0x3 + RegCurrent uint8 = 0x4 + RegCalibration uint8 = 0x5 +) From 9acb9a01e44e39846b11c9aa87eabeb7b1ee8eb2 Mon Sep 17 00:00:00 2001 From: Warren Guy <5602790+warrenguy@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:22:33 +0100 Subject: [PATCH 2/5] tests --- ina219/ina219.go | 8 +- ina219/ina219_test.go | 232 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 ina219/ina219_test.go diff --git a/ina219/ina219.go b/ina219/ina219.go index 7f12134b0..513958595 100644 --- a/ina219/ina219.go +++ b/ina219/ina219.go @@ -71,7 +71,7 @@ func (d *Device) Trigger() (err error) { // Measurements reads the bus voltage, shunt voltage, current, and power // from the device. func (d *Device) Measurements() ( - busVoltage int32, + busVoltage int16, shuntVoltage int16, current float32, power float32, @@ -106,7 +106,7 @@ func (d *Device) Measurements() ( // 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 int32, err error) { +func (d *Device) BusVoltage() (voltage int16, err error) { val, err := d.ReadRegister(RegBusVoltage) if err != nil { return @@ -119,12 +119,12 @@ func (d *Device) BusVoltage() (voltage int32, err error) { } // The conversion is not ready yet. - if val&(1<<1) != 0 { + if ModeTriggered(d.config.Mode) && val&(1<<1) != 0 { err = ErrNotReady{} return } - voltage = (int32(val) >> 3) * 4 + voltage = (int16(val) >> 3) * 4 return } diff --git a/ina219/ina219_test.go b/ina219/ina219_test.go new file mode 100644 index 000000000..f5a12abd4 --- /dev/null +++ b/ina219/ina219_test.go @@ -0,0 +1,232 @@ +package ina219 + +import ( + "fmt" + "testing" + + qt "github.com/frankban/quicktest" + "tinygo.org/x/drivers/tester" +) + +func TestDefaultAddress(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + dev := New(bus) + c.Assert(dev.Address, qt.Equals, uint16(Address)) +} + +func TestBusVoltage(t *testing.T) { + t.Run("valid", func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegBusVoltage: (4200 << 3) / 4, // 4.2V + } + bus.AddDevice(fake) + + dev := New(bus) + voltage, err := dev.BusVoltage() + c.Assert(err, qt.IsNil) + c.Assert(voltage, qt.Equals, int16(4200)) + }) + + t.Run("overflow", func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegBusVoltage: (1 >> 0), // overflow + } + bus.AddDevice(fake) + + dev := New(bus) + _, err := dev.BusVoltage() + c.Assert(err, qt.Not(qt.IsNil)) + c.Assert(err, qt.ErrorMatches, ErrOverflow{}.Error()) + }) + + t.Run("not ready", func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegBusVoltage: ((4200 << 3) / 4) | (1 << 1), // not ready + } + bus.AddDevice(fake) + + dev := New(bus) + dev.config.Mode = ModeTrigBus + _, err := dev.BusVoltage() + c.Assert(err, qt.Not(qt.IsNil)) + c.Assert(err, qt.ErrorMatches, ErrNotReady{}.Error()) + }) +} + +func TestShuntVoltage(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegShuntVoltage: 0x1234, + } + bus.AddDevice(fake) + + dev := New(bus) + voltage, err := dev.ShuntVoltage() + c.Assert(err, qt.IsNil) + c.Assert(voltage, qt.Equals, int16(0x1234)) +} + +func TestCurrent(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegCurrent: 420 * 6.9, // 420mA + } + bus.AddDevice(fake) + + dev := New(bus) + dev.config.CurrentDivider = 6.9 + current, err := dev.Current() + c.Assert(err, qt.IsNil) + c.Assert(current, qt.Equals, float32(420)) +} + +func TestPower(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegPower: 420 / 0.8, // 420mW + } + bus.AddDevice(fake) + + dev := New(bus) + dev.config.PowerMultiplier = 0.8 + power, err := dev.Power() + c.Assert(err, qt.IsNil) + c.Assert(power, qt.Equals, float32(420)) +} + +func TestReadConfig(t *testing.T) { + // use the default configurations + for _, tc := range []Config{ + Config16V400mA, + Config32V2A, + Config32V1A, + } { + n := fmt.Sprintf("%x/%x", tc.RegisterValue(), tc.Calibration.RegisterValue()) + t.Run(n, func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + fake.Registers = map[uint8]uint16{ + RegConfig: tc.RegisterValue(), + RegCalibration: tc.Calibration.RegisterValue(), + } + bus.AddDevice(fake) + + dev := New(bus) + config, err := dev.ReadConfig() + c.Assert(err, qt.IsNil) + c.Assert(config.BusADC, qt.Equals, tc.BusADC) + c.Assert(config.BusVoltageRange, qt.Equals, tc.BusVoltageRange) + c.Assert(config.Calibration, qt.Equals, tc.Calibration) + c.Assert(config.Mode, qt.Equals, tc.Mode) + c.Assert(config.PGA, qt.Equals, tc.PGA) + c.Assert(config.ShuntADC, qt.Equals, tc.ShuntADC) + }) + } +} + +func TestWriteConfig(t *testing.T) { + // use the default configurations + for _, tc := range []Config{ + Config16V400mA, + Config32V2A, + Config32V1A, + } { + n := fmt.Sprintf("%x/%x", tc.RegisterValue(), tc.Calibration.RegisterValue()) + t.Run(n, func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + bus.AddDevice(fake) + fake.Registers = map[uint8]uint16{ + RegConfig: 0, + RegCalibration: 0, + } + + dev := New(bus) + dev.config = tc + err := dev.Configure() + c.Assert(err, qt.IsNil) + c.Assert(fake.Registers[RegConfig], qt.Equals, tc.RegisterValue()) + c.Assert(fake.Registers[RegCalibration], qt.Equals, tc.Calibration.RegisterValue()) + }) + } +} + +func TestSetConfig(t *testing.T) { + for _, tc := range []Config{ + Config16V400mA, + Config32V2A, + Config32V1A, + } { + n := fmt.Sprintf("%x/%x", tc.RegisterValue(), tc.Calibration.RegisterValue()) + t.Run(n, func(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + dev := New(bus) + dev.SetConfig(tc) + c.Assert(dev.config, qt.Equals, tc) + }) + } +} + +func TestTrigger(t *testing.T) { + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + bus.AddDevice(fake) + fake.Registers = map[uint8]uint16{ + RegConfig: Config32V2A.RegisterValue(), + } + + dev := New(bus) + dev.config = Config32V2A + dev.config.Mode = ModeTrigBus + err := dev.Trigger() + c.Assert(err, qt.IsNil) + c.Assert(fake.Registers[RegConfig], qt.Equals, dev.config.RegisterValue()) +} + +func TestMeasurements(t *testing.T) { + bvVal := int16(4200) + svVal := int16(1234) + iVal := float32(420) + pVal := float32(420) + + c := qt.New(t) + bus := tester.NewI2CBus(c) + fake := tester.NewI2CDevice16(c, Address) + bus.AddDevice(fake) + fake.Registers = map[uint8]uint16{ + RegBusVoltage: uint16(((4200 << 3) / 4) | (1 << 1)), + RegShuntVoltage: uint16(svVal), + RegCurrent: uint16(iVal * Config16V400mA.CurrentDivider), + RegPower: uint16(pVal / Config16V400mA.PowerMultiplier), + } + + dev := New(bus) + dev.config = Config16V400mA + bv, sv, i, p, err := dev.Measurements() + c.Assert(err, qt.IsNil) + c.Assert(bv, qt.Equals, bvVal) + c.Assert(sv, qt.Equals, svVal) + c.Assert(i, qt.Equals, iVal) + c.Assert(p, qt.Equals, pVal) + +} From f354f60140dc74c9b53d6fafd7ae3ac0766a008d Mon Sep 17 00:00:00 2001 From: Warren Guy <5602790+warrenguy@users.noreply.github.com> Date: Sun, 29 Sep 2024 12:45:05 +0100 Subject: [PATCH 3/5] smoketest --- examples/ina219/main.go | 29 +++++++++++++++++++++++++++++ smoketest.sh | 1 + 2 files changed, 30 insertions(+) create mode 100644 examples/ina219/main.go diff --git a/examples/ina219/main.go b/examples/ina219/main.go new file mode 100644 index 000000000..0235eff1f --- /dev/null +++ b/examples/ina219/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/ina219" +) + +func main() { + machine.I2C0.Configure(machine.I2CConfig{}) + + dev := ina219.New(machine.I2C0) + dev.Configure() + + for { + busVoltage, shuntVoltage, current, power, err := dev.Measurements() + if err != nil { + println("Error reading measurements", err) + } + + println("Bus Voltage:", busVoltage, "V") + println("Shunt Voltage:", shuntVoltage, "V") + println("Current:", current, "mA") + println("Power:", power, "mW") + + time.Sleep(10 * time.Millisecond) + } +} diff --git a/smoketest.sh b/smoketest.sh index 1237d8501..2c000d60e 100755 --- a/smoketest.sh +++ b/smoketest.sh @@ -108,6 +108,7 @@ tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/tim tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8591/ tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go +tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina219/main.go tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/ tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/ From 79973be0e8edea3e2e9f6c95f666723abc6d7ae4 Mon Sep 17 00:00:00 2001 From: Warren Guy <5602790+warrenguy@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:21:47 +0100 Subject: [PATCH 4/5] config readback --- ina219/errors.go | 4 ++++ ina219/ina219.go | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ina219/errors.go b/ina219/errors.go index 040dc18eb..fe078fcb6 100644 --- a/ina219/errors.go +++ b/ina219/errors.go @@ -7,3 +7,7 @@ func (e ErrOverflow) Error() string { return "overflow" } type ErrNotReady struct{} func (e ErrNotReady) Error() string { return "not ready" } + +type ErrConfigMismatch struct{} + +func (e ErrConfigMismatch) Error() string { return "config mismatch" } diff --git a/ina219/ina219.go b/ina219/ina219.go index 513958595..77a59786a 100644 --- a/ina219/ina219.go +++ b/ina219/ina219.go @@ -45,10 +45,22 @@ func (d *Device) Configure() (err error) { return } - err = d.WriteRegister( + 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 } From 885f07a8a43cb79f9f94bad5093ce534476a0f9d Mon Sep 17 00:00:00 2001 From: Warren Guy <5602790+warrenguy@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:34:28 +0100 Subject: [PATCH 5/5] shunt voltage unit correction --- examples/ina219/main.go | 2 +- ina219/ina219.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ina219/main.go b/examples/ina219/main.go index 0235eff1f..50fcba20a 100644 --- a/examples/ina219/main.go +++ b/examples/ina219/main.go @@ -20,7 +20,7 @@ func main() { } println("Bus Voltage:", busVoltage, "V") - println("Shunt Voltage:", shuntVoltage, "V") + println("Shunt Voltage:", shuntVoltage/100, "mV") println("Current:", current, "mA") println("Power:", power, "mW") diff --git a/ina219/ina219.go b/ina219/ina219.go index 77a59786a..0f7c2991d 100644 --- a/ina219/ina219.go +++ b/ina219/ina219.go @@ -140,7 +140,7 @@ func (d *Device) BusVoltage() (voltage int16, err error) { return } -// ShuntVoltage reads the "shunt" voltage in 100ths of a volt. +// ShuntVoltage reads the "shunt" voltage in 100ths of a millivolt. func (d *Device) ShuntVoltage() (voltage int16, err error) { return d.ReadRegister(RegShuntVoltage) }