From ad7ea5b74b9da02d63363429f54469ea5cb63b88 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 14 May 2024 08:54:10 -0400 Subject: [PATCH] sht4x - Fix sporadic measurement errors by applying TIME_TO_TICKS() macro from SHT3x driver to ensure the delay time is at least 1 more tick than desired Replace pdMS_TO_TICKS() with TIME_TO_TICKS(). FreeRTOS vTaskDelay() (https://www.freertos.org/a00127.html) does NOT guarantee that the delay time is at least the ticks specified, relative to time. The SHT4x has timing constraints that are required to be followed for the part to be ready to respond. In the case where the delay was 10ms and the FreeRTOS tick time is 10ms vTaskDelay(1) was being called. Measurement via oscilloscope confirmed that most of the time the delay was 10ms + 2-5ms, but sometimes it was 6ms or 7ms. In the cases where the delay was <10ms, the SHT4x would not respond to the 'read measurement' phase of taking a measurement, resulting in i2cdev logging an error, and the measurement call failing. --- components/sht4x/sht4x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/sht4x/sht4x.c b/components/sht4x/sht4x.c index 2ff0e41d..9308cdba 100644 --- a/components/sht4x/sht4x.c +++ b/components/sht4x/sht4x.c @@ -44,6 +44,11 @@ #define I2C_FREQ_HZ 1000000 // 1MHz +// due to the fact that ticks can be smaller than portTICK_PERIOD_MS, one and +// a half tick period added to the duration to be sure that waiting time for +// the results is long enough +#define TIME_TO_TICKS(ms) (1 + ((ms) + (portTICK_PERIOD_MS-1) + portTICK_PERIOD_MS/2 ) / portTICK_PERIOD_MS) + static const char *TAG = "sht4x"; #define CMD_RESET 0x94 @@ -225,7 +230,7 @@ esp_err_t sht4x_init(sht4x_t *dev) dev->heater = SHT4X_HEATER_OFF; sht4x_raw_data_t s; - CHECK(exec_cmd(dev, CMD_SERIAL, pdMS_TO_TICKS(10), s)); + CHECK(exec_cmd(dev, CMD_SERIAL, TIME_TO_TICKS(10), s)); dev->serial = ((uint32_t)s[0] << 24) | ((uint32_t)s[1] << 16) | ((uint32_t)s[3] << 8) | s[4]; return sht4x_reset(dev); @@ -273,7 +278,7 @@ size_t sht4x_get_measurement_duration(sht4x_t *dev) { if (!dev) return 0; - size_t res = pdMS_TO_TICKS(get_duration_ms(dev)); + size_t res = TIME_TO_TICKS(get_duration_ms(dev)); return res == 0 ? 1 : res; }