From 233d57b9377bb8b9f1d97499b4cffb1a8de32be3 Mon Sep 17 00:00:00 2001 From: Nikola Kovacs Date: Fri, 9 Nov 2018 02:36:39 +0100 Subject: [PATCH] ina219: Fix currentLSB calculation (#319) - currentLSB is supposed to be Maximum Expected Current / 2^15 2 << 15 is 2^16, not 2^15. - fix rounding error in powerLSB calculation - check for overflow in calibration - fix doc --- experimental/devices/ina219/doc.go | 2 +- experimental/devices/ina219/ina219.go | 12 +++-- .../devices/ina219/ina219_go1_7_test.go | 51 +++++++++---------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/experimental/devices/ina219/doc.go b/experimental/devices/ina219/doc.go index 8052977..ea93c07 100644 --- a/experimental/devices/ina219/doc.go +++ b/experimental/devices/ina219/doc.go @@ -8,7 +8,7 @@ // Calibration // // Calibration is recommended for accurate current and power measurements. -// Voltage measurements do not require sensor calibration. To calibrate meansure +// Voltage measurements do not require sensor calibration. To calibrate, measure // the actual value of the shunt resistor. // // Datasheet diff --git a/experimental/devices/ina219/ina219.go b/experimental/devices/ina219/ina219.go index fff1f0b..043045e 100644 --- a/experimental/devices/ina219/ina219.go +++ b/experimental/devices/ina219/ina219.go @@ -157,13 +157,16 @@ func (d *Dev) calibrate(sense physic.ElectricResistance, maxCurrent physic.Elect d.mu.Lock() defer d.mu.Unlock() - d.currentLSB = maxCurrent / (2 << 15) - d.powerLSB = physic.Power(d.currentLSB * 20) + d.currentLSB = maxCurrent / (1 << 15) + d.powerLSB = physic.Power((maxCurrent*20 + (1 << 14)) / (1 << 15)) // Calibration Register = 0.04096 / (current LSB * Shunt Resistance) // Where lsb is in Amps and resistance is in ohms. // Calibration register is 16 bits. - cal := uint16(calibratescale / (int64(d.currentLSB) * int64(sense))) - return d.m.WriteUint16(calibrationRegister, cal) + cal := calibratescale / (int64(d.currentLSB) * int64(sense)) + if cal >= (1 << 16) { + return errCalibrationOverflow + } + return d.m.WriteUint16(calibrationRegister, uint16(cal)) } // PowerMonitor represents measurements from ina219 sensor. @@ -189,4 +192,5 @@ var ( errMaxCurrentInvalid = errors.New("max current cannot be negative or zero") errRegisterOverflow = errors.New("bus voltage register overflow") errWritingToConfigRegister = errors.New("failed to write to configuration register") + errCalibrationOverflow = errors.New("calibration would exceed maximum scaling") ) diff --git a/experimental/devices/ina219/ina219_go1_7_test.go b/experimental/devices/ina219/ina219_go1_7_test.go index 83e2226..076074a 100644 --- a/experimental/devices/ina219/ina219_go1_7_test.go +++ b/experimental/devices/ina219/ina219_go1_7_test.go @@ -36,12 +36,12 @@ func TestNew(t *testing.T) { }{ {name: "defaults", tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, }, want: fields{ - currentLSB: 48828 * physic.NanoAmpere, - powerLSB: 976560 * physic.NanoWatt, + currentLSB: 97656 * physic.NanoAmpere, + powerLSB: 1953125 * physic.NanoWatt, }, }, {name: "badAddressOption", @@ -59,36 +59,36 @@ func TestNew(t *testing.T) { {name: "setAddress", opts: Opts{Address: 0x41}, tx: []i2ctest.IO{ - {Addr: 0x41, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x41, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x41, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, }, want: fields{ - currentLSB: 48828 * physic.NanoAmpere, - powerLSB: 976560 * physic.NanoWatt, + currentLSB: 97656 * physic.NanoAmpere, + powerLSB: 1953125 * physic.NanoWatt, }, err: nil, }, {name: "setMaxCurrent", opts: Opts{MaxCurrent: 1000 * physic.MilliAmpere}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x68, 0xdc}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x34, 0x6e}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, }, want: fields{ - currentLSB: 15258 * physic.NanoAmpere, - powerLSB: 305160 * physic.NanoWatt, + currentLSB: 30517 * physic.NanoAmpere, + powerLSB: 610352 * physic.NanoWatt, }, err: nil, }, {name: "setSenseResistor", - opts: Opts{SenseResistor: 10 * physic.MilliOhm}, + opts: Opts{SenseResistor: 20 * physic.MilliOhm}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x47, 0xae}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x51, 0xeb}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, }, want: fields{ - currentLSB: 48828 * physic.NanoAmpere, - powerLSB: 976560 * physic.NanoWatt, + currentLSB: 97656 * physic.NanoAmpere, + powerLSB: 1953125 * physic.NanoWatt, }, err: nil, }, @@ -103,7 +103,7 @@ func TestNew(t *testing.T) { }, {name: "errWritingToConfigRegister", tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister}, R: []byte{}}, }, want: fields{ @@ -177,7 +177,7 @@ func TestSense(t *testing.T) { err: errReadShunt, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{}}, }, @@ -187,7 +187,7 @@ func TestSense(t *testing.T) { err: errReadBus, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{0x00, 0x00}}, {Addr: 0x40, W: []byte{busVoltageRegister}, R: []byte{}}, @@ -198,7 +198,7 @@ func TestSense(t *testing.T) { err: errReadCurrent, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{0x00, 0x00}}, {Addr: 0x40, W: []byte{busVoltageRegister}, R: []byte{0x00, 0x00}}, @@ -210,7 +210,7 @@ func TestSense(t *testing.T) { err: errReadPower, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{0x00, 0x00}}, {Addr: 0x40, W: []byte{busVoltageRegister}, R: []byte{0x00, 0x00}}, @@ -223,7 +223,7 @@ func TestSense(t *testing.T) { err: nil, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{0x00, 0x00}}, {Addr: 0x40, W: []byte{busVoltageRegister}, R: []byte{0x00, 0x00}}, @@ -237,7 +237,7 @@ func TestSense(t *testing.T) { err: errRegisterOverflow, args: Opts{}, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{calibrationRegister, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{calibrationRegister, 0x10, 0x62}, R: []byte{}}, {Addr: 0x40, W: []byte{configRegister, 0x1f, 0xff}, R: []byte{}}, {Addr: 0x40, W: []byte{shuntVoltageRegister}, R: []byte{0x00, 0x00}}, {Addr: 0x40, W: []byte{busVoltageRegister}, R: []byte{0x00, 0x01}}, @@ -315,13 +315,12 @@ func TestCalibrate(t *testing.T) { err: errMaxCurrentInvalid, }, { - name: "errIO", + name: "errCalibrationOverflow", args: fields{ sense: physic.MilliOhm, maxCurrent: physic.Ampere, }, - err: stringErr, - errString: "unexpected Tx", + err: errCalibrationOverflow, }, { name: "default", @@ -330,11 +329,11 @@ func TestCalibrate(t *testing.T) { maxCurrent: 3200 * physic.MilliAmpere, }, want: fields{ - currentLSB: 48828 * physic.NanoAmpere, - powerLSB: 976560 * physic.NanoWatt, + currentLSB: 97656 * physic.NanoAmpere, + powerLSB: 1953125 * physic.NanoWatt, }, tx: []i2ctest.IO{ - {Addr: 0x40, W: []byte{0x05, 0x20, 0xc4}, R: []byte{}}, + {Addr: 0x40, W: []byte{0x05, 0x10, 0x62}, R: []byte{}}, }, err: nil, },