Skip to content

Commit 7c3d5eb

Browse files
committed
modules: sensor: add warmup delays to prevent CCS811 early read failures
CCS811 sensor needs 5-second stabilization after init before valid readings. Added configurable per-sensor warmup periods with tracking to skip reads during warmup. - CCS811: 5000ms warmup, BME280/HM3301: 100ms - Individual sensor warmup completion tracking - Partial data handling during warmup The change fixes the regression introduced in PR #15 where removing the global warmup delay caused CCS811 to fail with -EAGAIN during the first few read attempts after system initialization. Refs: #16 Signed-off-by: Natalia Pluta <pluta.natalia.m@gmail.com>
1 parent 8f6404c commit 7c3d5eb

2 files changed

Lines changed: 134 additions & 5 deletions

File tree

app/src/modules/sensor/Kconfig.sensor

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ config SENSOR_MODULE_MAX_RETRIES
4646
help
4747
Maximum number of recovery attempts before giving up.
4848

49+
# Sensor-specific warmup configurations
50+
config SENSOR_MODULE_WARMUP_ENABLE
51+
bool "Enable sensor warmup periods"
52+
default y
53+
help
54+
Enable warmup delays for sensors that need stabilization time
55+
before providing accurate readings.
56+
57+
config SENSOR_MODULE_CCS811_WARMUP_MS
58+
int "CCS811 warmup period (ms)"
59+
default 5000
60+
depends on SENSOR_MODULE_WARMUP_ENABLE
61+
help
62+
Warmup time required for CCS811 sensor before first valid reading.
63+
CCS811 needs time to stabilize after power-on or reset.
64+
65+
config SENSOR_MODULE_BME280_WARMUP_MS
66+
int "BME280 warmup period (ms)"
67+
default 100
68+
depends on SENSOR_MODULE_WARMUP_ENABLE
69+
help
70+
Warmup time required for BME280 sensor before first valid reading.
71+
72+
config SENSOR_MODULE_HM3301_WARMUP_MS
73+
int "HM3301 warmup period (ms)"
74+
default 100
75+
depends on SENSOR_MODULE_WARMUP_ENABLE
76+
help
77+
Warmup time required for HM3301 sensor before first valid reading.
78+
4979
config CCS811_ENV_COMPENSATION
5080
bool "Enable environmental compensation for CCS811"
5181
default y

app/src/modules/sensor/sensor_module.c

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
LOG_MODULE_REGISTER(sensor_module, CONFIG_SENSOR_MODULE_LOG_LEVEL);
1212

1313
/* Macro for type-safe sensor state object initialization */
14-
#define SENSOR_STATE_OBJECT_INIT() \
15-
{ \
16-
.ctx = {0}, .current_state = SENSOR_MODULE_STATE_INIT, .current_data = {0}, \
17-
.error_count = 0, .max_retries = 0, .last_read_time = 0, .read_timeout_ms = 0 \
14+
#define SENSOR_STATE_OBJECT_INIT() \
15+
{ \
16+
.ctx = {0}, .current_state = SENSOR_MODULE_STATE_INIT, .current_data = {0}, \
17+
.error_count = 0, .max_retries = 0, .last_read_time = 0, .read_timeout_ms = 0, \
18+
IF_ENABLED(CONFIG_SENSOR_MODULE_WARMUP_ENABLE, \
19+
(.sensor_init_time = 0, .sensor_warmup_complete = {false},)) \
1820
}
1921

2022
/* ZBUS subscriber for sensor requests */
@@ -56,6 +58,12 @@ struct sensor_state_object {
5658
/* Timing */
5759
int64_t last_read_time;
5860
int64_t read_timeout_ms;
61+
62+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
63+
/* Sensor warmup tracking */
64+
int64_t sensor_init_time;
65+
bool sensor_warmup_complete[SENSOR_TYPE_COUNT];
66+
#endif
5967
};
6068

6169
/* Forward declarations for state functions */
@@ -115,6 +123,11 @@ static void update_sensor_health(struct sensor_health *health, bool success);
115123
static const char *get_sensor_name(enum sensor_type type);
116124
static void sensor_set_state(struct sensor_state_object *ctx, enum sensor_module_state new_state);
117125

126+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
127+
static bool is_sensor_warmup_complete(enum sensor_type type);
128+
static int64_t get_sensor_warmup_time(enum sensor_type type);
129+
#endif
130+
118131
#ifdef CONFIG_CCS811_ENV_COMPENSATION
119132
static int update_ccs811_env_data(const struct sensor_value *temp, const struct sensor_value *hum);
120133
static void handle_ccs811_env_compensation(const struct sensor_value *temp,
@@ -246,6 +259,14 @@ static void sensor_state_init_run(void *obj)
246259
return;
247260
}
248261

262+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
263+
/* Initialize warmup timing */
264+
ctx->sensor_init_time = k_uptime_get();
265+
for (int i = 0; i < SENSOR_TYPE_COUNT; i++) {
266+
ctx->sensor_warmup_complete[i] = false;
267+
}
268+
#endif
269+
249270
/* Initialize context with configured values */
250271
ctx->error_count = 0;
251272
ctx->max_retries = sensor_state_obj.max_retries;
@@ -292,6 +313,15 @@ static void sensor_state_reading_run(void *obj)
292313
continue;
293314
}
294315

316+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
317+
/* Check if sensor warmup is complete */
318+
if (!is_sensor_warmup_complete(i)) {
319+
LOG_DBG("Sensor SM: %s warmup not complete, skipping read",
320+
get_sensor_name(i));
321+
continue;
322+
}
323+
#endif
324+
295325
int ret = read_sensor_data(i, &ctx->current_data);
296326
if (ret == 0) {
297327
successful_reads++;
@@ -319,18 +349,43 @@ static void sensor_state_reading_run(void *obj)
319349
}
320350
}
321351

322-
/* Count enabled sensors */
352+
/* Count enabled sensors that have completed warmup */
323353
int enabled_sensor_count = 0;
324354
for (int i = 0; i < SENSOR_TYPE_COUNT; i++) {
325355
if (sensors[i].enabled) {
356+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
357+
if (is_sensor_warmup_complete(i)) {
358+
enabled_sensor_count++;
359+
}
360+
#else
326361
enabled_sensor_count++;
362+
#endif
327363
}
328364
}
329365

330366
/* Only publish data if at least one sensor read successfully */
331367
if (successful_reads == 0) {
368+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
369+
/* Check if any sensors are still warming up */
370+
bool any_warming = false;
371+
for (int i = 0; i < SENSOR_TYPE_COUNT; i++) {
372+
if (sensors[i].enabled && !is_sensor_warmup_complete(i)) {
373+
any_warming = true;
374+
break;
375+
}
376+
}
377+
378+
if (any_warming) {
379+
LOG_DBG("Sensor SM: No readings yet - sensors still warming up");
380+
sensor_set_state(ctx, SENSOR_MODULE_STATE_IDLE);
381+
} else {
382+
LOG_ERR("Sensor SM: All sensors failed, entering error state");
383+
sensor_set_state(ctx, SENSOR_MODULE_STATE_ERROR);
384+
}
385+
#else
332386
LOG_ERR("Sensor SM: All sensors failed, entering error state");
333387
sensor_set_state(ctx, SENSOR_MODULE_STATE_ERROR);
388+
#endif
334389
} else if (successful_reads < enabled_sensor_count) {
335390
LOG_WRN("Sensor SM: Partial sensor failure (%d/%d successful), but publishing "
336391
"available data",
@@ -703,3 +758,47 @@ static void sensor_set_state(struct sensor_state_object *ctx, enum sensor_module
703758
ctx->current_state = new_state;
704759
smf_set_state(SMF_CTX(ctx), &sensor_states[new_state]);
705760
}
761+
762+
#ifdef CONFIG_SENSOR_MODULE_WARMUP_ENABLE
763+
/* Helper function to get warmup time for a sensor type */
764+
static int64_t get_sensor_warmup_time(enum sensor_type type)
765+
{
766+
switch (type) {
767+
case SENSOR_TYPE_BME280:
768+
return CONFIG_SENSOR_MODULE_BME280_WARMUP_MS;
769+
case SENSOR_TYPE_CCS811:
770+
return CONFIG_SENSOR_MODULE_CCS811_WARMUP_MS;
771+
case SENSOR_TYPE_HM3301:
772+
return CONFIG_SENSOR_MODULE_HM3301_WARMUP_MS;
773+
default:
774+
return 0;
775+
}
776+
}
777+
778+
/* Helper function to check if sensor warmup is complete */
779+
static bool is_sensor_warmup_complete(enum sensor_type type)
780+
{
781+
if (type >= SENSOR_TYPE_COUNT) {
782+
return false;
783+
}
784+
785+
/* Check if already marked as complete */
786+
if (sensor_state_obj.sensor_warmup_complete[type]) {
787+
return true;
788+
}
789+
790+
/* Check if warmup time has elapsed */
791+
int64_t elapsed_time = k_uptime_get() - sensor_state_obj.sensor_init_time;
792+
int64_t warmup_time = get_sensor_warmup_time(type);
793+
794+
if (elapsed_time >= warmup_time) {
795+
/* Mark as complete and log */
796+
sensor_state_obj.sensor_warmup_complete[type] = true;
797+
LOG_INF("Sensor SM: %s warmup complete after %lld ms", get_sensor_name(type),
798+
elapsed_time);
799+
return true;
800+
}
801+
802+
return false;
803+
}
804+
#endif /* CONFIG_SENSOR_MODULE_WARMUP_ENABLE */

0 commit comments

Comments
 (0)