diff --git a/drivers/sensor/ina23x/ina237.c b/drivers/sensor/ina23x/ina237.c index 183e1079d90..987d0e5c0b1 100644 --- a/drivers/sensor/ina23x/ina237.c +++ b/drivers/sensor/ina23x/ina237.c @@ -31,58 +31,36 @@ LOG_MODULE_REGISTER(INA237, CONFIG_SENSOR_LOG_LEVEL); */ #define INA237_DIETEMP_TO_uDegC(x) (((x) >> 4) * 125000) +static void micro_s32_to_sensor_value(struct sensor_value *val, int32_t value_microX) +{ + val->val1 = value_microX / 1000000L; + val->val2 = value_microX % 1000000L; +} + static int ina237_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { - struct ina237_data *data = dev->data; + const struct ina237_data *data = dev->data; const struct ina237_config *config = dev->config; - uint32_t bus_uv, current_ua, power_uw; - int32_t temp_uDegC; - int32_t sign = 1; switch (chan) { case SENSOR_CHAN_VOLTAGE: - bus_uv = INA237_BUS_VOLTAGE_TO_uV(data->bus_voltage); - - val->val1 = bus_uv / 1000000U; - val->val2 = bus_uv % 1000000U; + micro_s32_to_sensor_value(val, INA237_BUS_VOLTAGE_TO_uV(data->bus_voltage)); 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 "Current and Power calculations" section */ - current_ua = current_ua * config->current_lsb; - - /* convert to fractional amperes */ - val->val1 = sign * (int32_t)(current_ua / 1000000U); - val->val2 = sign * (int32_t)(current_ua % 1000000U); + micro_s32_to_sensor_value(val, data->current * config->current_lsb); break; case SENSOR_CHAN_POWER: /* see datasheet "Current and Power calculations" section */ - power_uw = (data->power * INA237_POWER_SCALING * config->current_lsb) / 10000U; - - /* convert to fractional watts */ - val->val1 = (int32_t)(power_uw / 1000000U); - val->val2 = (int32_t)(power_uw % 1000000U); + micro_s32_to_sensor_value(val, + (data->power * INA237_POWER_SCALING * config->current_lsb) / 10000U); break; case SENSOR_CHAN_DIE_TEMP: - temp_uDegC = INA237_DIETEMP_TO_uDegC(data->die_temp); - - val->val1 = temp_uDegC / 1000000L; - val->val2 = abs(temp_uDegC) % 1000000L; - - if (temp_uDegC < 0) { - val->val2 = -val->val2; - } + micro_s32_to_sensor_value(val, INA237_DIETEMP_TO_uDegC(data->die_temp)); break; default: diff --git a/drivers/sensor/ina23x/ina237.h b/drivers/sensor/ina23x/ina237.h index 68b866e2f52..892700b366a 100644 --- a/drivers/sensor/ina23x/ina237.h +++ b/drivers/sensor/ina23x/ina237.h @@ -37,7 +37,7 @@ struct ina237_data { const struct device *dev; - uint16_t current; + int16_t current; uint16_t bus_voltage; uint32_t power; int16_t die_temp; diff --git a/tests/drivers/sensor/ina237/src/ina237_test.c b/tests/drivers/sensor/ina237/src/ina237_test.c index 7d6747e828e..b3e1bc56849 100644 --- a/tests/drivers/sensor/ina237/src/ina237_test.c +++ b/tests/drivers/sensor/ina237/src/ina237_test.c @@ -44,6 +44,39 @@ ZTEST(ina237_0, test_default_config) * * @param fixture */ +static void test_current(struct ina237_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 */ + ina237_mock_set_register(fixture->mock->data, INA237_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 ina237_fixture *fixture) { zassert_not_null(fixture->mock); @@ -128,6 +161,7 @@ static struct ina237_fixture fixtures[] = { /* Create a test suite for each enabled ina237 device node */ #define INA237_TESTS(inst) \ + ZTEST(ina237_##inst, test_current) { test_current(&fixtures[inst]); } \ ZTEST(ina237_##inst, test_bus_voltage) { test_bus_voltage(&fixtures[inst]); } \ ZTEST(ina237_##inst, test_temperature) { test_temperature(&fixtures[inst]); } \ ZTEST_SUITE(ina237_##inst, NULL, NULL, NULL, NULL, NULL);