diff --git a/src/drivers/power_monitor/ina228/ina228.cpp b/src/drivers/power_monitor/ina228/ina228.cpp index 6505a7d65e..e586590470 100644 --- a/src/drivers/power_monitor/ina228/ina228.cpp +++ b/src/drivers/power_monitor/ina228/ina228.cpp @@ -59,8 +59,6 @@ INA228::INA228(const I2CSPIDriverConfig &config, int battery_index) : _max_current = fvalue; } - _range = _max_current > (MAX_CURRENT - 1.0f) ? INA228_ADCRANGE_HIGH : INA228_ADCRANGE_LOW; - fvalue = INA228_SHUNT; _rshunt = fvalue; ph = param_find("INA228_SHUNT"); @@ -69,6 +67,21 @@ INA228::INA228(const I2CSPIDriverConfig &config, int battery_index) : _rshunt = fvalue; } + // According to page 8.2.2.1, page 36/48 of the INA228 interface datasheet (Rev. A), + // the requirement is: R_SHUNT < V_SENSE_MAX / I_MAX + // therefore: R_SHUNT * I_MAX < V_SENSE_MAX + // and so if V_SENSE_MAX is bigger, we need to use the bigger ADC range to avoid + // the device from capping the measured current. + + const float v_sense_max = _rshunt * _max_current; + + if (v_sense_max > INA228_ADCRANGE_LOW_V_SENSE) { + _range = INA228_ADCRANGE_HIGH; + + } else { + _range = INA228_ADCRANGE_LOW; + } + ph = param_find("INA228_CONFIG"); int32_t value = INA228_ADCCONFIG; _config = (uint16_t)value; diff --git a/src/drivers/power_monitor/ina228/ina228.h b/src/drivers/power_monitor/ina228/ina228.h index ee15f75eab..46e152ff00 100644 --- a/src/drivers/power_monitor/ina228/ina228.h +++ b/src/drivers/power_monitor/ina228/ina228.h @@ -293,6 +293,8 @@ using namespace time_literals; #define INA228_VSCALE 1.95e-04f /* LSB of voltage is 195.3125 uV/LSB */ #define INA228_TSCALE 7.8125e-03f /* LSB of temperature is 7.8125 mDegC/LSB */ +#define INA228_ADCRANGE_LOW_V_SENSE 0.04096f // ± 40.96 mV + #define swap16(w) __builtin_bswap16((w)) #define swap32(d) __builtin_bswap32((d)) #define swap64(q) __builtin_bswap64((q)) diff --git a/src/drivers/power_monitor/ina238/ina238.cpp b/src/drivers/power_monitor/ina238/ina238.cpp index ff3f193385..298942dbe4 100644 --- a/src/drivers/power_monitor/ina238/ina238.cpp +++ b/src/drivers/power_monitor/ina238/ina238.cpp @@ -55,8 +55,6 @@ INA238::INA238(const I2CSPIDriverConfig &config, int battery_index) : _max_current = fvalue; } - _range = _max_current > (DEFAULT_MAX_CURRENT - 1.0f) ? INA238_ADCRANGE_HIGH : INA238_ADCRANGE_LOW; - fvalue = DEFAULT_SHUNT; _rshunt = fvalue; ph = param_find("INA238_SHUNT"); @@ -65,6 +63,21 @@ INA238::INA238(const I2CSPIDriverConfig &config, int battery_index) : _rshunt = fvalue; } + // According to page 8.2.2.1, page 33/48 of the INA238 interface datasheet (Rev. A), + // the requirement is: R_SHUNT < V_SENSE_MAX / I_MAX + // therefore: R_SHUNT * I_MAX < V_SENSE_MAX + // and so if V_SENSE_MAX is bigger, we need to use the bigger ADC range to avoid + // the device from capping the measured current. + + const float v_sense_max = _rshunt * _max_current; + + if (v_sense_max > INA238_ADCRANGE_LOW_V_SENSE) { + _range = INA238_ADCRANGE_HIGH; + + } else { + _range = INA238_ADCRANGE_LOW; + } + _current_lsb = _max_current / INA238_DN_MAX; _shunt_calibration = static_cast(INA238_CONST * _current_lsb * _rshunt); diff --git a/src/drivers/power_monitor/ina238/ina238.h b/src/drivers/power_monitor/ina238/ina238.h index 9d260fd711..7d888aef54 100644 --- a/src/drivers/power_monitor/ina238/ina238.h +++ b/src/drivers/power_monitor/ina238/ina238.h @@ -75,6 +75,8 @@ using namespace ina238; #define INA238_VSCALE 3.125e-03f /* LSB of voltage is 3.1255 mV/LSB */ #define INA238_TSCALE 7.8125e-03f /* LSB of temperature is 7.8125 mDegC/LSB */ +#define INA238_ADCRANGE_LOW_V_SENSE 0.04096f // ± 40.96 mV + #define DEFAULT_MAX_CURRENT 327.68f /* Amps */ #define DEFAULT_SHUNT 0.0003f /* Shunt is 300 uOhm */