0.5.1 INA226

This commit is contained in:
Rob Tillaart 2023-12-10 17:26:56 +01:00
parent a79de888fa
commit 06a71fd185
6 changed files with 88 additions and 36 deletions

View File

@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.5.1] - 2023-12-10
- reimplementation of **setMaxCurrentShunt()**,
- thanks to tileiar
- update readme.md
- minor edits
## [0.5.0] - 2023-12-04
- Fix #31, refactor API - support ESP32-S3
- update readme.md

View File

@ -1,6 +1,6 @@
// FILE: INA226.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.5.0
// VERSION: 0.5.1
// DATE: 2021-05-18
// PURPOSE: Arduino library for INA226 power sensor
// URL: https://github.com/RobTillaart/INA226
@ -178,11 +178,13 @@ uint8_t INA226::getShuntVoltageConversionTime()
//
int INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
{
// https://github.com/RobTillaart/INA226/pull/29
// #define printdebug true
// fix #16 - datasheet 6.5 Electrical Characteristics
// rounded value to 80 mV
float shuntVoltage = abs(maxCurrent * shunt);
float shuntVoltage = maxCurrent * shunt;
if (shuntVoltage > 0.080) return INA226_ERR_SHUNTVOLTAGE_HIGH;
if (maxCurrent < 0.001) return INA226_ERR_MAXCURRENT_LOW;
if (shunt < INA226_MINIMAL_SHUNT) return INA226_ERR_SHUNT_LOW;
@ -194,42 +196,82 @@ int INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
Serial.print("normalize:\t");
Serial.println(normalize ? " true":" false");
Serial.print("initial current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.print(_current_LSB * 1e+6, 1);
Serial.println(" uA / bit");
#endif
uint32_t calib = 0;
uint32_t factor = 1;
// normalize the LSB to a round number
// LSB will increase
if (normalize)
{
calib = round(0.00512 / (_current_LSB * shunt));
_current_LSB = 0.00512 / (calib * shunt);
/*
check if maxCurrent (normal) or shunt resistor
(due to unusual low resistor values in relation to maxCurrent) determines currentLSB
we have to take the upper value for currentLSB
calculation of currentLSB based on shunt resistor and calibration register limits (2 bytes)
cal = 0.00512 / ( shunt * currentLSB )
cal(max) = 2^16-1
currentLSB(min) = 0.00512 / ( shunt * cal(max) )
currentLSB(min) ~= 0.00512 / ( shunt * 2^16 )
currentLSB(min) ~= 2^9 * 1e-5 / ( shunt * 2^16 )
currentLSB(min) ~= 1e-5 / 2^7 / shunt
currentLSB(min) ~= 7.8125e-8 / shunt
*/
if ( 7.8125e-8 / shunt > _current_LSB ) {
// shunt resistor determines currentLSB -> take this a starting point for currentLSB
_current_LSB = 7.8125e-8 / shunt;
}
#ifdef printdebug
Serial.print("Prescale current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.print(_current_LSB * 1e+6, 1);
Serial.println(" uA / bit");
#endif
// auto scale current_LSB
factor = 1;
while (_current_LSB < 1)
{
_current_LSB *= 10;
// normalize _current_LSB to a value of 1, 2 or 5 * 1e-6 to 1e-3
// convert float to int
uint16_t currentLSB_uA = float(_current_LSB * 1e+6);
currentLSB_uA++; // ceil() would be more precise, but uses 176 bytes of flash.
uint16_t factor = 1; // 1uA to 1000uA
uint8_t i = 0; // 1 byte loop reduces footprint
bool result = false;
do {
if ( 1 * factor >= currentLSB_uA) {
_current_LSB = 1 * factor * 1e-6;
result = true;
} else if ( 2 * factor >= currentLSB_uA) {
_current_LSB = 2 * factor * 1e-6;
result = true;
} else if ( 5 * factor >= currentLSB_uA) {
_current_LSB = 5 * factor * 1e-6;
result = true;
} else {
factor *= 10;
i++;
}
_current_LSB = 1.0 / factor;
} while( (i < 4) && (!result) ); // factor < 10000
if (result == false) { // not succeeded to normalize.
_current_LSB = 0;
return INA226_ERR_NORMALIZE_FAILED;
}
// auto scale calibration
calib = round(0.00512 / (_current_LSB * shunt));
#ifdef printdebug
Serial.print("After scale current_LSB:\t");
Serial.print(_current_LSB * 1e+6, 1);
Serial.println(" uA / bit");
#endif
// done
}
// auto scale calibration if needed.
uint32_t calib = round(0.00512 / (_current_LSB * shunt));
while (calib > 65535)
{
_current_LSB *= 10;
calib /= 10;
_current_LSB *= 2;
calib >>= 1;
}
_writeRegister(INA226_CALIBRATION, calib);
@ -237,19 +279,17 @@ int INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
_shunt = shunt;
#ifdef printdebug
Serial.print("factor:\t");
Serial.println(factor);
Serial.print("Final current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.print(_current_LSB * 1e+6, 1);
Serial.println(" uA / bit");
Serial.print("Calibration:\t");
Serial.println(calib);
Serial.print("Max current:\t");
Serial.print(_maxCurrent);
Serial.print(_maxCurrent, 3);
Serial.println(" A");
Serial.print("Shunt:\t");
Serial.print(_shunt, 8);
Serial.println(" ohm");
Serial.print(_shunt, 4);
Serial.println(" Ohm");
Serial.print("ShuntV:\t");
Serial.print(shuntVoltage, 4);
Serial.println(" Volt");

View File

@ -1,7 +1,7 @@
#pragma once
// FILE: INA226.h
// AUTHOR: Rob Tillaart
// VERSION: 0.5.0
// VERSION: 0.5.1
// DATE: 2021-05-18
// PURPOSE: Arduino library for INA226 power sensor
// URL: https://github.com/RobTillaart/INA226
@ -14,7 +14,7 @@
#include "Wire.h"
#define INA226_LIB_VERSION (F("0.5.0"))
#define INA226_LIB_VERSION (F("0.5.1"))
// set by setAlertRegister
@ -37,7 +37,7 @@
#define INA226_ERR_SHUNTVOLTAGE_HIGH 0x8000
#define INA226_ERR_MAXCURRENT_LOW 0x8001
#define INA226_ERR_SHUNT_LOW 0x8002
#define INA226_ERR_NORMALIZE_FAILED 0x8003
// See issue #26
#define INA226_MINIMAL_SHUNT (0.001)
@ -88,7 +88,7 @@ public:
// shunt * maxCurrent < 81 mV
// maxCurrent >= 0.001
// shunt >= 0.001
int setMaxCurrentShunt(float macCurrent = 20.0,
int setMaxCurrentShunt(float maxCurrent = 20.0,
float shunt = 0.002,
bool normalize = true);
bool isCalibrated() { return _current_LSB != 0.0; };

View File

@ -215,8 +215,7 @@ Calibration is mandatory to get **getCurrent()** and **getPower()** to work.
- **int setMaxCurrentShunt(float ampere = 20.0, float ohm = 0.002, bool normalize = true)**
set the calibration register based upon the shunt and the max Ampere.
From this the LSB is derived.
The function may force normalization if underflow is detected.
From these two values the current_LSB is derived, the steps of the ADC when measuring current.
Returns Error code, see below.
- **bool isCalibrated()** returns true if CurrentLSB has been calculated by **setMaxCurrentShunt()**.
Value should not be zero.
@ -231,13 +230,18 @@ To print these values in scientific notation use https://github.com/RobTillaart/
#### About normalization
**setMaxCurrentShunt()** will round the LSB to nearest round value (typical 0.001) by default (normalize == true).
**setMaxCurrentShunt()** will round the current_LSB to nearest round value (typical 0.001) by default (normalize == true).
- The user **must** check the return value == 0x000, otherwise the calibration register is **not** set.
- Normalization typically gives smaller steps => improve precision
- Normalization can cause that the maxCurrent passed cannot be reached any more.
Solution is not to normalize if this max range is needed.
Note: in 0.5.1 the **setMaxCurrentShunt()** function is rewritten after it showed a bug when
normalize flag was set to true.
See https://github.com/RobTillaart/INA226/pull/29 for details of the discussion.
#### Error codes setMaxCurrentShunt
| descriptive name error | value | meaning |
@ -246,6 +250,7 @@ Solution is not to normalize if this max range is needed.
| INA226_ERR_SHUNTVOLTAGE_HIGH | 0x8000 | maxCurrent \* shunt > 80 mV
| INA226_ERR_MAXCURRENT_LOW | 0x8001 | maxCurrent < 0.001
| INA226_ERR_SHUNT_LOW | 0x8002 | shunt < 0.001
| INA226_ERR_NORMALIZE_FAILED | 0x8003 | not possible to normalize.
#### Operating mode
@ -309,7 +314,7 @@ The alert line falls when alert is reached.
- **uint16_t getDieID()** should return 0x2260
#### debugging
#### Debugging
- **uint16_t getRegister(uint8_t reg)** fetch registers directly, for debugging only.

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/INA226.git"
},
"version": "0.5.0",
"version": "0.5.1",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=INA226
version=0.5.0
version=0.5.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for INA226 power sensor