mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.0 INA226
This commit is contained in:
parent
4f7b4641cf
commit
42b353bc73
@ -1,21 +1,11 @@
|
||||
// FILE: INA266.h
|
||||
// FILE: INA226.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.6
|
||||
// VERSION: 0.2.0
|
||||
// DATE: 2021-05-18
|
||||
// PURPOSE: Arduino library for INA266 power sensor
|
||||
// PURPOSE: Arduino library for INA226 power sensor
|
||||
// URL: https://github.com/RobTillaart/INA226
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2021-05-18 initial version
|
||||
// 0.1.1 2021-06-21 improved calibration + added functions
|
||||
// 0.1.2 2021-06-22 add check of parameters of several functions + unit tests
|
||||
// add getShunt() , getMaxCurrent()
|
||||
// 0.1.3 2021-06-22 add getCurrentLSB_uA() + improve examples
|
||||
// fix for calibration
|
||||
// 0.1.4 2021-08-07 fix getCurrent()
|
||||
// 0.1.5 2021-11-05 update build-CI, add badges
|
||||
// fix address in constructor.
|
||||
// 0.1.6 2021-12-20 update library.json, license, minor edits
|
||||
// HISTORY: see releaseNotes.md
|
||||
|
||||
|
||||
#include "INA226.h"
|
||||
@ -40,7 +30,7 @@ INA226::INA226(const uint8_t address, TwoWire *wire)
|
||||
{
|
||||
_address = address;
|
||||
_wire = wire;
|
||||
// as these
|
||||
// not calibrated values by default.
|
||||
_current_LSB = 0;
|
||||
_maxCurrent = 0;
|
||||
_shunt = 0;
|
||||
@ -79,14 +69,7 @@ bool INA226::isConnected()
|
||||
//
|
||||
float INA226::getShuntVoltage()
|
||||
{
|
||||
uint16_t val = _readRegister(INA226_SHUNT_VOLTAGE);
|
||||
if (val & 0x8000)
|
||||
{
|
||||
val = val & 0x7FFF;
|
||||
val = val ^ 0x7FFF;
|
||||
val++;
|
||||
return val * -2.5e-6;
|
||||
}
|
||||
int16_t val = _readRegister(INA226_SHUNT_VOLTAGE);
|
||||
return val * 2.5e-6; // fixed 2.50 uV
|
||||
}
|
||||
|
||||
@ -107,14 +90,7 @@ float INA226::getPower()
|
||||
|
||||
float INA226::getCurrent()
|
||||
{
|
||||
uint16_t val = _readRegister(INA226_CURRENT);
|
||||
if (val & 0x8000)
|
||||
{
|
||||
val = val & 0x7FFF;
|
||||
val = val ^ 0x7FFF;
|
||||
val++;
|
||||
return val * -_current_LSB;
|
||||
}
|
||||
int16_t val = _readRegister(INA226_CURRENT);
|
||||
return val * _current_LSB;
|
||||
}
|
||||
|
||||
@ -128,7 +104,10 @@ void INA226::reset()
|
||||
uint16_t mask = _readRegister(INA226_CONFIGURATION);
|
||||
mask |= 0x800;
|
||||
_writeRegister(INA226_CONFIGURATION, mask);
|
||||
// reset calibration?
|
||||
// reset calibration
|
||||
_current_LSB = 0;
|
||||
_maxCurrent = 0;
|
||||
_shunt = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -198,30 +177,49 @@ uint8_t INA226::getShuntVoltageConversionTime()
|
||||
//
|
||||
bool INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
|
||||
{
|
||||
if (maxCurrent > 20 || maxCurrent < 0.001) return false;
|
||||
// #define printdebug true
|
||||
uint32_t calib = 0;
|
||||
uint32_t factor = 1;
|
||||
|
||||
if ((maxCurrent > 20) || (maxCurrent < 0.001)) return false;
|
||||
if (shunt < 0.001) return false;
|
||||
|
||||
_current_LSB = maxCurrent * 3.0517578125e-5; // maxCurrent / 32768;
|
||||
|
||||
#ifdef printdebug
|
||||
Serial.println();
|
||||
Serial.print("normalize:\t");
|
||||
Serial.println(normalize ? " true":" false");
|
||||
Serial.print("initial current_LSB:\t");
|
||||
Serial.print(_current_LSB, 8);
|
||||
Serial.println(" uA / bit");
|
||||
#endif
|
||||
|
||||
// normalize the LSB to a round number
|
||||
// LSB will increase
|
||||
if (normalize)
|
||||
{
|
||||
// Serial.print("current_LSB:\t");
|
||||
// Serial.println(_current_LSB, 10);
|
||||
uint32_t factor = 1;
|
||||
calib = round(0.00512 / (_current_LSB * shunt));
|
||||
_current_LSB = 0.00512 / (calib * shunt);
|
||||
|
||||
#ifdef printdebug
|
||||
Serial.print("Prescale current_LSB:\t");
|
||||
Serial.print(_current_LSB, 8);
|
||||
Serial.println(" uA / bit");
|
||||
#endif
|
||||
|
||||
// auto scale current_LSB
|
||||
factor = 1;
|
||||
while (_current_LSB < 1)
|
||||
{
|
||||
_current_LSB *= 10;
|
||||
factor *= 10;
|
||||
}
|
||||
_current_LSB = 10.0 / factor;
|
||||
// Serial.print("current_LSB:\t");
|
||||
// Serial.println(_current_LSB, 10);
|
||||
_current_LSB = 1.0 / factor;
|
||||
}
|
||||
|
||||
// auto-scale
|
||||
uint32_t calib = round(0.00512 / (_current_LSB * shunt));
|
||||
// auto scale calibration
|
||||
calib = round(0.00512 / (_current_LSB * shunt));
|
||||
while (calib > 65535)
|
||||
{
|
||||
_current_LSB *= 10;
|
||||
@ -229,11 +227,25 @@ bool INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
|
||||
}
|
||||
_writeRegister(INA226_CALIBRATION, calib);
|
||||
|
||||
// Serial.print("Calibration:\t");
|
||||
// Serial.println(calib);
|
||||
|
||||
_maxCurrent = _current_LSB * 32768.0;
|
||||
_shunt = shunt;
|
||||
|
||||
#ifdef printdebug
|
||||
Serial.print("factor:\t");
|
||||
Serial.println(factor);
|
||||
Serial.print("Final current_LSB:\t");
|
||||
Serial.print(_current_LSB, 8);
|
||||
Serial.println(" uA / bit");
|
||||
Serial.print("Calibration:\t");
|
||||
Serial.println(calib);
|
||||
Serial.print("Max current:\t");
|
||||
Serial.print(_maxCurrent);
|
||||
Serial.println(" A");
|
||||
Serial.print("Shunt:\t");
|
||||
Serial.print(_shunt, 8);
|
||||
Serial.println(" ohm");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
// FILE: INA266.h
|
||||
// FILE: INA226.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.6
|
||||
// VERSION: 0.2.0
|
||||
// DATE: 2021-05-18
|
||||
// PURPOSE: Arduino library for INA266 power sensor
|
||||
// PURPOSE: Arduino library for INA226 power sensor
|
||||
// URL: https://github.com/RobTillaart/INA226
|
||||
//
|
||||
// Read the datasheet for the details
|
||||
@ -14,7 +14,7 @@
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define INA226_LIB_VERSION (F("0.1.6"))
|
||||
#define INA226_LIB_VERSION (F("0.2.0"))
|
||||
|
||||
|
||||
// set by setAlertRegister
|
||||
@ -77,8 +77,10 @@ public:
|
||||
// mandatory to set these!
|
||||
// maxCurrent = 0.001 .. 20
|
||||
// shunt >= 0.001
|
||||
bool setMaxCurrentShunt(float macCurrent = 20.0, float shunt = 0.002,
|
||||
bool setMaxCurrentShunt(float macCurrent = 20.0,
|
||||
float shunt = 0.002,
|
||||
bool normalize = true);
|
||||
bool isCalibrated() { return _current_LSB != 0.0; };
|
||||
|
||||
// these return zero if not calibrated!
|
||||
float getCurrentLSB() { return _current_LSB; };
|
||||
|
@ -21,9 +21,9 @@ Not all functionality is tested / investigated.
|
||||
The INA226 is a voltage, current and power measurement device. a few important maxima.
|
||||
(See datasheet, chapter 6)
|
||||
|
||||
| description | max | unit |
|
||||
|:--------------|------:|-------:|
|
||||
| bus voltage | 36 | Volt |
|
||||
| description | max | unit | notes |
|
||||
|:--------------|------:|-------:|:------|
|
||||
| bus voltage | 36 | Volt | unclear for how long.
|
||||
| shunt voltage | 80 | mVolt |
|
||||
| current | 20 | Ampere |
|
||||
|
||||
@ -36,7 +36,7 @@ See datasheet - table 2 - datasheet.
|
||||
|
||||
## About Measurements
|
||||
|
||||
Calibration is mandatory to get **getCurrent()** and **getPower()** to work.
|
||||
Calibration with **setMaxCurrentShunt()** is mandatory to get **getCurrent()** and **getPower()** to work.
|
||||
|
||||
Some initial tests shows that the readings do not 100% add up.
|
||||
I expect this is caused by fluctuations in my power supply used and
|
||||
@ -53,18 +53,30 @@ always check and verify what is on the shunt and even verify with a DMM that thi
|
||||
With the calibration function **setMaxCurrentShunt()** one can just set the actual value and even
|
||||
compensate slightly if readings are structural too low or too high.
|
||||
|
||||
I noted that the **getPower()** function does not always equal **getBusVoltage()** times **getCurrent()**
|
||||
Cause is rounding/trunking maths and time of measurement. You might prefer to multiply those values yourself
|
||||
to get extra digits. Please be aware that more digits is not always more exact (think significant digits)
|
||||
I noted that the **getPower()** function does not always equal **getBusVoltage()** times **getCurrent()**.
|
||||
Cause is rounding/trunking maths and time of measurement.
|
||||
You might prefer to multiply those values yourself to get extra digits.
|
||||
Please be aware that more digits is not always more exact (think significant digits)
|
||||
|
||||
The example sketch **INA226_setMaxCurrentShunt.ino** switches between two calibration modes.
|
||||
It shows the **INA266** sensor needs time to accommodate to this change.
|
||||
In practice you should call **setMaxCurrentShunt()** only once in **setup()**
|
||||
In practice you should call **setMaxCurrentShunt()** only once in **setup()**.
|
||||
|
||||
|
||||
## Versions
|
||||
|
||||
#### 0.2.0
|
||||
|
||||
- **reset()** also resets the calibration (current_lsb, maxCurrent and shunt),
|
||||
thereby forcing the user to redo the calibration call with **setMaxCurrentShunt()**.
|
||||
- fixes issue #11 => a factor 10 bug in current_lsb.
|
||||
- some edits in readme.md.
|
||||
- added **bool isCalibrated()**.
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
read datasheet for details
|
||||
read datasheet for details.
|
||||
|
||||
|
||||
### Constructor
|
||||
@ -84,34 +96,40 @@ the sensor. Also the value is not meaningful if there is no shunt connected.
|
||||
|
||||
- **float getShuntVoltage()** idem.
|
||||
- **float getBusVoltage()** idem. Max 36 Volt.
|
||||
- **float getCurrent()** is the current through the shunt in Ampere
|
||||
- **float getPower()** is the current x BusVoltage in Watt
|
||||
- **float getCurrent()** is the current through the shunt in Ampere.
|
||||
- **float getPower()** is the current x BusVoltage in Watt.
|
||||
|
||||
Helper functions to get the right scale
|
||||
Helper functions to get the right scale.
|
||||
|
||||
- **float getBusVoltage_mV()** idem, in millivolts
|
||||
- **float getShuntVoltage_mV()** idem, in millivolts
|
||||
- **float getCurrent_mA()** idem in milliAmpere
|
||||
- **float getPower_mW()** idem in milliWatt
|
||||
- **float getShuntVoltage_uV()** idem microVolt
|
||||
- **float getCurrent_uA()** idem in microAmpere
|
||||
- **float getPower_uW()** idem, in microWatt
|
||||
- **float getBusVoltage_mV()** idem, in millivolts.
|
||||
- **float getShuntVoltage_mV()** idem, in millivolts.
|
||||
- **float getCurrent_mA()** idem in milliAmpere.
|
||||
- **float getPower_mW()** idem in milliWatt.
|
||||
- **float getShuntVoltage_uV()** idem microVolt.
|
||||
- **float getCurrent_uA()** idem in microAmpere.
|
||||
- **float getPower_uW()** idem, in microWatt.
|
||||
|
||||
|
||||
### Configuration
|
||||
|
||||
Note: the conversion time runs in the background and if done value is stored in a register. The core functions read from the registers, so they are not blocked, but just get the same value if no new is ready.
|
||||
Note: the conversion time runs in the background and if done value is stored in a register.
|
||||
The core functions read from the registers, so they are not blocked,
|
||||
but just get the same value if no new is ready.
|
||||
|
||||
- **void reset()** software power on reset
|
||||
- **bool setAverage(uint8_t avg = 0)** see table below
|
||||
(0 = default ==> 1 read), returns false if parameter > 7
|
||||
- **uint8_t getAverage()** returns the value set. Note this is not the count of samples.
|
||||
- **bool setBusVoltageConversionTime(uint8_t bvct = 4)** see table below
|
||||
(4 = default ==> 1.1 ms), returns false if parameter > 7
|
||||
- **uint8_t getBusVoltageConversionTime()** return the value set. Note this is not a unit of time.
|
||||
- **bool setShuntVoltageConversionTime(uint8_t svct = 4)** see table below
|
||||
(4 = default ==> 1.1 ms), returns false if parameter > 7
|
||||
- **uint8_t getShuntVoltageConversionTime()** return the value set. Note this is not a unit of time.
|
||||
- **void reset()** software power on reset.
|
||||
This implies calibration with **setMaxCurrentShunt()** needs to be redone.
|
||||
- **bool setAverage(uint8_t avg = 0)** see table below.
|
||||
(0 = default ==> 1 read), returns false if parameter > 7.
|
||||
- **uint8_t getAverage()** returns the value set. See table below.
|
||||
Note this is not the count of samples.
|
||||
- **bool setBusVoltageConversionTime(uint8_t bvct = 4)** see table below.
|
||||
(4 = default ==> 1.1 ms), returns false if parameter > 7.
|
||||
- **uint8_t getBusVoltageConversionTime()** return the value set.
|
||||
Note the value returned is not a unit of time.
|
||||
- **bool setShuntVoltageConversionTime(uint8_t svct = 4)** see table below.
|
||||
(4 = default ==> 1.1 ms), returns false if parameter > 7.
|
||||
- **uint8_t getShuntVoltageConversionTime()** return the value set.
|
||||
Note the value returned is not a unit of time.
|
||||
|
||||
|
||||
| Average | # samples | notes |
|
||||
@ -153,11 +171,16 @@ set the calibration register based upon the shunt and the max ampere.
|
||||
From this the LSB is derived.
|
||||
Note the function will round up the LSB to nearest round value by default.
|
||||
This may cause loss of precision. The function may force normalization if underflow detected.
|
||||
- **float getCurrentLSB()** returns the LSB == precision of the calibration
|
||||
- **float getCurrentLSB_uA()** returns the LSB == precision of the calibration
|
||||
- **float getShunt()** returns the value set for the shunt
|
||||
The user **must** check the return value == true, otherwise the calibration register is **not** set.
|
||||
- **bool isCalibrated()** returns true if CurrentLSB has been calculated by **setMaxCurrentShunt()**.
|
||||
- **float getCurrentLSB()** returns the LSB in Ampere == precision of the calibration.
|
||||
- **float getCurrentLSB_mA()** returns the LSB in milliampere.
|
||||
- **float getCurrentLSB_uA()** returns the LSB in microampere.
|
||||
- **float getShunt()** returns the value set for the shunt.
|
||||
- **float getMaxCurrent()** returns the value for the maxCurrent which can be corrected.
|
||||
|
||||
To print these values one might use https://github.com/RobTillaart/printHelpers
|
||||
|
||||
|
||||
### Operating mode
|
||||
|
||||
@ -215,6 +238,11 @@ The alert line falls when alert is reached.
|
||||
- **uint16_t getDieID()** should return 0x2260
|
||||
|
||||
|
||||
### debugging
|
||||
|
||||
- **uint16_t getRegister(uint8_t reg)** fetch registers directly, for debugging only.
|
||||
|
||||
|
||||
## Operational
|
||||
|
||||
See examples..
|
||||
@ -223,14 +251,20 @@ See examples..
|
||||
## Future
|
||||
|
||||
- test different loads (low edge)
|
||||
- test unit tests
|
||||
- expand unit tests possible?
|
||||
- test examples
|
||||
- investigate alert functions / interface
|
||||
- improve readme.md
|
||||
- disconnected load, can it be recognized?
|
||||
- **lastError()** do we need this...
|
||||
- disconnected load,
|
||||
- can it be recognized? => current drop?
|
||||
- **lastError()** do we need this
|
||||
- if **BVCT SVCT** is set to 6 or 7
|
||||
- does the long timing affects RTOS? ==> yield()
|
||||
- cache configuration ? ==> 2 bytes
|
||||
- **float getCurrentLSB_mA()** wrapper?
|
||||
- **bool isCalibrated()**
|
||||
|
||||
|
||||
- what is gained? updates are faster.
|
||||
- 15 times used,
|
||||
- separate release notes.
|
||||
- can the calibration math be optimized
|
||||
- integer only?
|
||||
- less iterations?
|
||||
- local var for current_lsb?
|
||||
- ??
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/INA226.git"
|
||||
},
|
||||
"version": "0.1.6",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=INA226
|
||||
version=0.1.6
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for INA226 power sensor
|
||||
|
43
libraries/INA226/releaseNotes.md
Normal file
43
libraries/INA226/releaseNotes.md
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
# INA226 library
|
||||
|
||||
## Release notes
|
||||
|
||||
|
||||
## 0.2.0 2022-02-02
|
||||
- fix #11 normalize
|
||||
- fix #13 simplify sign handling shunt and current
|
||||
- add releaseNotes.md
|
||||
|
||||
## 0.1.6 2021-12-20
|
||||
- update library.json,
|
||||
- license,
|
||||
- minor edits
|
||||
|
||||
## 0.1.5 2021-11-05
|
||||
- update build-CI,
|
||||
- add badges in readme.md
|
||||
- fix address in constructor
|
||||
|
||||
## 0.1.4 2021-08-07
|
||||
- fix getCurrent()
|
||||
|
||||
## 0.1.3 2021-06-22
|
||||
- add getCurrentLSB_uA()
|
||||
- improve examples
|
||||
- fix for calibration
|
||||
|
||||
## 0.1.2 2021-06-22
|
||||
- add check of parameters of several functions
|
||||
- add unit tests
|
||||
- add getShunt()
|
||||
- add getMaxCurrent()
|
||||
|
||||
## 0.1.1 2021-06-21
|
||||
- improved calibration
|
||||
- added functions
|
||||
|
||||
## 0.1.0 2021-05-18
|
||||
- initial version
|
||||
|
||||
|
@ -50,9 +50,11 @@ unittest(test_constructor)
|
||||
{
|
||||
|
||||
INA226 INA(0x40);
|
||||
|
||||
|
||||
assertTrue(INA.begin());
|
||||
assertTrue(INA.isConnected());
|
||||
|
||||
assertFalse(INA.isCalibrated());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user