Skip to content

Commit aed7ae5

Browse files
JordanYatescfriedt
authored andcommitted
fuel_gauge: composite: switch to tick based sampling
To ensure that data is consistent across multiple sequential calls to `fuel_gauge_get_prop`, sensor_fetch is only called if a certain time period has passed since the previous sampling. This emulates the tick-based sampling of most dedicated fuel-gauge devices. Signed-off-by: Jordan Yates <[email protected]> tick
1 parent 7ea2804 commit aed7ae5

File tree

2 files changed

+60
-22
lines changed

2 files changed

+60
-22
lines changed

drivers/fuel_gauge/composite/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,12 @@ config FUEL_GAUGE_COMPOSITE
99
depends on DT_HAS_ZEPHYR_FUEL_GAUGE_COMPOSITE_ENABLED
1010
help
1111
Enable driver for the Zephyr composite fuel gauge device.
12+
13+
config FUEL_GAUGE_COMPOSITE_DATA_VALIDITY_MS
14+
int "Data from sensor_fetch is cached for this long"
15+
depends on FUEL_GAUGE_COMPOSITE
16+
default 150
17+
help
18+
To ensure that data is consistent across multiple calls to
19+
fuel_gauge_get_prop, sensor_fetch is only called if at least
20+
this long has passed since the previous call.

drivers/fuel_gauge/composite/fuel_gauge_composite.c

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ struct composite_config {
2121
enum battery_chemistry chemistry;
2222
};
2323

24-
static int composite_read_micro(const struct device *dev, enum sensor_channel chan, int *val)
24+
struct composite_data {
25+
k_ticks_t next_reading;
26+
};
27+
28+
static int composite_fetch(const struct device *dev)
2529
{
26-
struct sensor_value sensor_val;
2730
int rc;
2831

2932
rc = pm_device_runtime_get(dev);
@@ -34,23 +37,41 @@ static int composite_read_micro(const struct device *dev, enum sensor_channel ch
3437
if (rc < 0) {
3538
return rc;
3639
}
37-
rc = sensor_channel_get(dev, chan, &sensor_val);
38-
if (rc < 0) {
39-
return rc;
40-
}
41-
rc = pm_device_runtime_put(dev);
42-
if (rc < 0) {
43-
return rc;
44-
}
45-
*val = sensor_value_to_micro(&sensor_val);
46-
return 0;
40+
return pm_device_runtime_put(dev);
4741
}
4842

4943
static int composite_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
5044
union fuel_gauge_prop_val *val)
5145
{
5246
const struct composite_config *config = dev->config;
53-
int voltage, rc = 0;
47+
struct composite_data *data = dev->data;
48+
k_ticks_t now = k_uptime_ticks();
49+
struct sensor_value sensor_val;
50+
int64_t voltage;
51+
int rc = 0;
52+
53+
/* Validate at build time that equivalent channel output fields still match */
54+
BUILD_ASSERT(sizeof(val->absolute_state_of_charge) ==
55+
sizeof(val->relative_state_of_charge));
56+
BUILD_ASSERT(offsetof(union fuel_gauge_prop_val, absolute_state_of_charge) ==
57+
offsetof(union fuel_gauge_prop_val, relative_state_of_charge));
58+
BUILD_ASSERT(sizeof(val->current) == sizeof(val->avg_current));
59+
BUILD_ASSERT(offsetof(union fuel_gauge_prop_val, current) ==
60+
offsetof(union fuel_gauge_prop_val, avg_current));
61+
62+
if (now >= data->next_reading) {
63+
/* Trigger a sample on the input devices */
64+
rc = composite_fetch(config->battery_voltage);
65+
if ((rc == 0) && config->battery_current) {
66+
rc = composite_fetch(config->battery_current);
67+
}
68+
if (rc != 0) {
69+
return rc;
70+
}
71+
/* Update timestamp for next reading */
72+
data->next_reading =
73+
now + k_ms_to_ticks_near64(CONFIG_FUEL_GAUGE_COMPOSITE_DATA_VALIDITY_MS);
74+
}
5475

5576
switch (prop) {
5677
case FUEL_GAUGE_FULL_CHARGE_CAPACITY:
@@ -66,30 +87,36 @@ static int composite_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
6687
val->full_charge_capacity = config->charge_capacity_microamp_hours / 1000;
6788
break;
6889
case FUEL_GAUGE_VOLTAGE:
69-
rc = composite_read_micro(config->battery_voltage, SENSOR_CHAN_VOLTAGE,
70-
&val->voltage);
90+
rc = sensor_channel_get(config->battery_voltage, SENSOR_CHAN_VOLTAGE, &sensor_val);
91+
val->voltage = sensor_value_to_micro(&sensor_val);
7192
break;
7293
case FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE:
7394
case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE:
7495
if (config->ocv_lookup_table[0] == -1) {
7596
return -ENOTSUP;
7697
}
77-
rc = composite_read_micro(config->battery_voltage, SENSOR_CHAN_VOLTAGE, &voltage);
78-
val->relative_state_of_charge =
79-
battery_soc_lookup(config->ocv_lookup_table, voltage) / 1000;
98+
/* Fetch the voltage from the sensor */
99+
rc = sensor_channel_get(config->battery_voltage, SENSOR_CHAN_VOLTAGE, &sensor_val);
100+
voltage = sensor_value_to_micro(&sensor_val);
101+
if (rc == 0) {
102+
/* Convert voltage to state of charge */
103+
val->relative_state_of_charge =
104+
battery_soc_lookup(config->ocv_lookup_table, voltage) / 1000;
105+
}
80106
break;
81107
case FUEL_GAUGE_CURRENT:
108+
case FUEL_GAUGE_AVG_CURRENT:
82109
if (config->battery_current == NULL) {
83110
return -ENOTSUP;
84111
}
85-
rc = composite_read_micro(config->battery_current, SENSOR_CHAN_CURRENT,
86-
&val->current);
112+
rc = sensor_channel_get(config->battery_current, SENSOR_CHAN_CURRENT, &sensor_val);
113+
val->current = sensor_value_to_micro(&sensor_val);
87114
break;
88115
default:
89116
return -ENOTSUP;
90117
}
91118

92-
return 0;
119+
return rc;
93120
}
94121

95122
static DEVICE_API(fuel_gauge, composite_api) = {
@@ -106,7 +133,9 @@ static DEVICE_API(fuel_gauge, composite_api) = {
106133
DT_INST_PROP_OR(inst, charge_full_design_microamp_hours, 0), \
107134
.chemistry = BATTERY_CHEMISTRY_DT_GET(inst), \
108135
}; \
109-
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, NULL, &composite_##inst##_config, POST_KERNEL, \
136+
static struct composite_data composite_##inst##_data; \
137+
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &composite_##inst##_data, \
138+
&composite_##inst##_config, POST_KERNEL, \
110139
CONFIG_SENSOR_INIT_PRIORITY, &composite_api);
111140

112141
DT_INST_FOREACH_STATUS_OKAY(COMPOSITE_INIT)

0 commit comments

Comments
 (0)