diff --git a/libraries/INA226/CHANGELOG.md b/libraries/INA226/CHANGELOG.md index 8f96d986..4e02e49f 100644 --- a/libraries/INA226/CHANGELOG.md +++ b/libraries/INA226/CHANGELOG.md @@ -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 diff --git a/libraries/INA226/INA226.cpp b/libraries/INA226/INA226.cpp index 3c724b73..77551de0 100644 --- a/libraries/INA226/INA226.cpp +++ b/libraries/INA226/INA226.cpp @@ -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; - factor *= 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++; + } + } while( (i < 4) && (!result) ); // factor < 10000 + + if (result == false) { // not succeeded to normalize. + _current_LSB = 0; + return INA226_ERR_NORMALIZE_FAILED; } - _current_LSB = 1.0 / factor; + + #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 - calib = round(0.00512 / (_current_LSB * shunt)); + // 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"); diff --git a/libraries/INA226/INA226.h b/libraries/INA226/INA226.h index 21c37afb..142a66fa 100644 --- a/libraries/INA226/INA226.h +++ b/libraries/INA226/INA226.h @@ -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; }; diff --git a/libraries/INA226/README.md b/libraries/INA226/README.md index 565246e5..28338cf5 100644 --- a/libraries/INA226/README.md +++ b/libraries/INA226/README.md @@ -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. diff --git a/libraries/INA226/library.json b/libraries/INA226/library.json index 1513fc1d..4c2cbc57 100644 --- a/libraries/INA226/library.json +++ b/libraries/INA226/library.json @@ -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": "*", diff --git a/libraries/INA226/library.properties b/libraries/INA226/library.properties index 1982a19b..a5467d89 100644 --- a/libraries/INA226/library.properties +++ b/libraries/INA226/library.properties @@ -1,5 +1,5 @@ name=INA226 -version=0.5.0 +version=0.5.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for INA226 power sensor