drivers: sensor: ina230: fix current sign issue

Fix sign handling for ina230 current calculation.

Signed-off-by: Eric Holmberg <eric.holmberg@northriversystems.co.nz>
This commit is contained in:
Eric Holmberg 2023-08-16 21:54:28 +12:00 committed by Maureen Helm
commit f5b78270bc
4 changed files with 40 additions and 20 deletions

View file

@ -29,8 +29,8 @@ static int ina230_channel_get(const struct device *dev, enum sensor_channel chan
{
struct ina230_data *data = dev->data;
const struct ina230_config *const config = dev->config;
uint32_t bus_uv, current_ua, power_uw;
int32_t sign;
uint32_t bus_uv, power_uw;
int32_t current_ua;
switch (chan) {
case SENSOR_CHAN_VOLTAGE:
@ -42,21 +42,12 @@ static int ina230_channel_get(const struct device *dev, enum sensor_channel chan
break;
case SENSOR_CHAN_CURRENT:
if (data->current & INA23X_CURRENT_SIGN_BIT) {
current_ua = ~data->current + 1U;
sign = -1;
} else {
current_ua = data->current;
sign = 1;
}
/* see datasheet "Programming" section for reference */
current_ua = current_ua * config->current_lsb;
current_ua = data->current * config->current_lsb;
/* convert to fractional amperes */
val->val1 = sign * (int32_t)(current_ua / 1000000U);
val->val2 = sign * (int32_t)(current_ua % 1000000U);
val->val1 = current_ua / 1000000L;
val->val2 = current_ua % 1000000L;
break;
case SENSOR_CHAN_POWER:

View file

@ -34,7 +34,7 @@
struct ina230_data {
const struct device *dev;
uint16_t current;
int16_t current;
uint16_t bus_voltage;
uint16_t power;
#ifdef CONFIG_INA230_TRIGGER

View file

@ -12,11 +12,6 @@
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/util_macro.h>
/**
* @brief Macro used to test if the current's sign bit is set
*/
#define INA23X_CURRENT_SIGN_BIT BIT(15)
/**
* @brief Macro used to check if the current's LSB is 1mA
*/

View file

@ -89,6 +89,39 @@ static void test_shunt_cal(struct ina230_fixture *fixture)
"Expected %d, got %d", shunt_register_expected, shunt_register_actual);
}
static void test_current(struct ina230_fixture *fixture)
{
/* 16-bit signed value for current register */
const int16_t current_reg_vectors[] = {
32767,
1000,
100,
1,
0,
-1,
-100,
-1000,
-32768,
};
for (int idx = 0; idx < ARRAY_SIZE(current_reg_vectors); idx++) {
struct sensor_value sensor_val;
int16_t current_register = current_reg_vectors[idx];
double current_expected_A = fixture->current_lsb_uA * 1e-6 * current_register;
/* set current reading */
ina230_mock_set_register(fixture->mock->data, INA230_REG_CURRENT, current_register);
/* Verify sensor value is correct */
zassert_ok(sensor_sample_fetch(fixture->dev));
zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_CURRENT, &sensor_val));
double current_actual_A = sensor_value_to_double(&sensor_val);
zexpect_within(current_expected_A, current_actual_A, fixture->current_lsb_uA*1e-6,
"Expected %.6f A, got %.6f A", current_expected_A, current_actual_A);
}
}
static void test_bus_voltage(struct ina230_fixture *fixture)
{
zassert_not_null(fixture->mock);
@ -174,6 +207,7 @@ static struct ina230_fixture fixtures[] = {
#define INA230_TESTS(inst) \
ZTEST(ina230_##inst, test_datasheet_example) { test_datasheet_example(&fixtures[inst]); } \
ZTEST(ina230_##inst, test_shunt_cal) { test_shunt_cal(&fixtures[inst]); } \
ZTEST(ina230_##inst, test_current) { test_current(&fixtures[inst]); } \
ZTEST(ina230_##inst, test_bus_voltage) { test_bus_voltage(&fixtures[inst]); } \
ZTEST(ina230_##inst, test_power) { test_power(&fixtures[inst]); } \
ZTEST_SUITE(ina230_##inst, NULL, NULL, NULL, NULL, NULL);