ina228/ina238: correctly set ADC range

It turns out that we set the ADC range incorrectly leading to the
measured current being capped at a certain level as the ADC on the
sensor saturates.

Instead, we need to set the range according to the formula given in the
interface datasheet.
This commit is contained in:
Julian Oes 2025-05-14 12:37:11 +12:00 committed by Ramon Roche
parent 3af9a3f76e
commit 117f198891
4 changed files with 34 additions and 4 deletions

View File

@ -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;

View File

@ -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))

View File

@ -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<uint16_t>(INA238_CONST * _current_lsb * _rshunt);

View File

@ -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 */