mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
Merge #19048
19048: drivers/sht2x: some small improvements r=benpicco a=gschorcht
### Contribution description
This PR provides the following improvements for the SHT2x driver:
- migration to `ztimer` 8a605517f5
and 367549940de3bd8910052334c34af028d4992741
- floating point arithmetics replaced by integer arithmetics f424caebbfec9f2be56aa2337c6cc09dba5b97d6
- fix of sleep times (typical times replaced by maximum times as recommended by the datasheet) 13615c72094b8541ee62c3e8ed5a36dc4d725fd0
- release of the I2C bus during sleep 9415c216cfab734520ef98dd00b350c22f342c60
- Kconfig configuration of sensor parameters added dadbbcb4c328350893db53ba6743d03cb34ecc1c
- no-hold mode is now the default mode instead of the hold mode
Regarding the sleep times: The typical measurement times were used as sleep times. According to the datasheet, typical measurements are only recommended for calculating energy consumption, while maximum values should be used for calculating waiting times in communication. Therefore, the typical time values were replaced by maximum time values for the sleep in no-hold mode.
Regarding the hold mode: In hold mode, the sensor uses clock stretching until the measurement results can be read by the MCU. This blocks both the I2C bus and the MCU during the entire measurement, which can take up to 85 ms if I2C is not interrupt-driven. Therefore, the no-hold mode is now used by default, where the calling thread sleeps during the measurement, but the MCU is not completely blocked. Furthermore, the hold mode requires that the MCU supports clock stretching. Even if the MCU supports clock stretching, the hold mode with clock stretching doesn't seem to work with different MCUs. I couldn't get it working for STM32 and ESP32.
Regarding the I2C bus during sleep: If the no-hold mode is used and the calling thread sleeps up to 85 ms, it makes sense to release the I2C bus until the measurement results are available.
### Testing procedure
`tests/driver_sht2x` should still work.
### Issues/PRs references
Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
b71df25282
@ -9,14 +9,14 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_sht2x SHT2X
|
||||
* @defgroup drivers_sht2x SHT2x Humidity and Temperature sensor
|
||||
* @ingroup drivers_sensors
|
||||
* @brief Device driver interface for the SHT2X sensor
|
||||
* @brief Device driver interface for the SHT2x sensor
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for the SHT2x temperature and
|
||||
* humidity sensor.
|
||||
* @brief Device driver implementation for the SHT2x humidity and
|
||||
* temperature humidity sensor.
|
||||
*
|
||||
* @author Kees Bakker <kees@sodaq.com>
|
||||
* @author George Psimenos <gp7g14@soton.ac.uk>
|
||||
@ -129,7 +129,7 @@ int sht2x_reset(sht2x_t* dev);
|
||||
* @brief Read temperature value from the given SHT2X device, returned in
|
||||
* centi °C
|
||||
*
|
||||
* @details Notice that this function will sleep (max 66 ms) when the
|
||||
* @details Notice that this function will sleep (max 85 ms) when the
|
||||
* @a measure_mode is set to @a SHT2X_MEASURE_MODE_NO_HOLD.
|
||||
*
|
||||
* @param[in] dev Device descriptor of SHT2X device to read from
|
||||
@ -143,7 +143,7 @@ int16_t sht2x_read_temperature(const sht2x_t* dev);
|
||||
* @brief Read humidity value from the given SHT2X device, returned in
|
||||
* centi %RH
|
||||
*
|
||||
* @details Notice that this function will sleep (max 22 ms) when the
|
||||
* @details Notice that this function will sleep (max 29 ms) when the
|
||||
* @a measure_mode is set to @a SHT2X_MEASURE_MODE_NO_HOLD.
|
||||
*
|
||||
* @param[in] dev Device descriptor of SHT2X device to read from
|
||||
|
@ -5,15 +5,66 @@
|
||||
# directory for more details.
|
||||
#
|
||||
|
||||
config MODULE_SHT2X
|
||||
bool "SHT2x temperature and humidity sensor"
|
||||
depends on HAS_PERIPH_I2C
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_PERIPH_I2C
|
||||
select MODULE_XTIMER
|
||||
|
||||
config HAVE_SHT2X
|
||||
bool
|
||||
select MODULE_SHT2X if MODULE_SAUL_DEFAULT
|
||||
help
|
||||
Indicates that a SHT2x temperature and humidity sensor is present.
|
||||
Indicates that a SHT2x humidity and temperature sensor is present.
|
||||
|
||||
menuconfig MODULE_SHT2X
|
||||
bool "SHT2x humidity and temperature sensor"
|
||||
depends on HAS_PERIPH_I2C
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_CHECKSUM
|
||||
select MODULE_PERIPH_I2C
|
||||
select MODULE_ZTIMER_MSEC
|
||||
|
||||
if MODULE_SHT2X
|
||||
|
||||
choice
|
||||
bool "Measurement Resolution"
|
||||
default SHT2X_RES_12_14BIT
|
||||
|
||||
config SHT2X_RES_12_14BIT
|
||||
bool "Humidity with 12 bit, Temperature with 14 bit"
|
||||
config SHT2X_RES_11_11BIT
|
||||
bool "Humidity with 11 bit, Temperature with 11 bit"
|
||||
config SHT2X_RES_10_13BIT
|
||||
bool "Humidity with 10 bit, Temperature with 13 bit"
|
||||
config SHT2X_RES_8_12BIT
|
||||
bool "Humidity with 8 bit, Temperature with 12 bit"
|
||||
help
|
||||
Measurement resolution
|
||||
endchoice
|
||||
|
||||
choice
|
||||
bool "Measurement Mode"
|
||||
default SHT2X_MEASURE_MODE_NO_HOLD
|
||||
|
||||
config SHT2X_MEASURE_MODE_NO_HOLD
|
||||
bool "No Hold"
|
||||
help
|
||||
In Hold mode the measurement is started and the sensor blocks the
|
||||
master by clock stretching until the measurement is finished. Thus,
|
||||
in this mode, both the I2C bus and the processor are blocked for the
|
||||
entire measurement duration, which can be up to 85 ms for temperature
|
||||
measurement and up to 29 ms for humidity measurement, depending on the
|
||||
resolution. Therefore, the no-hold mode should be used, where the
|
||||
measurement is started and a timer is used to fetch the results.
|
||||
This way neither the I2C bus nor the processor are blocked for the
|
||||
duration of the measurement. Furthermore, the hold mode requires that
|
||||
the MCU supports clock stretching.
|
||||
config SHT2X_MEASURE_MODE_HOLD
|
||||
bool "Hold"
|
||||
help
|
||||
In no-hold mode the measurement is started and a timer is used to
|
||||
fetch the results. This way neither the I2C bus nor the processor
|
||||
are blocked for the duration of the measurement.
|
||||
endchoice
|
||||
|
||||
config SHT2X_CRC_MODE
|
||||
bool "CRC check"
|
||||
help
|
||||
Enable to check the CRC of measurement data.
|
||||
|
||||
endif # MODULE_SHT2X
|
||||
|
@ -1,2 +1,3 @@
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += checksum
|
||||
USEMODULE += ztimer_msec
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Default configuration for SHT2X
|
||||
* @brief Default configuration for SHT2x humidity and temperature sensor
|
||||
*
|
||||
* @author Kees Bakker <kees@sodaq.com>
|
||||
* @author George Psimenos <gp7g14@soton.ac.uk>
|
||||
@ -30,26 +30,70 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !DOXYGEN
|
||||
/* Mapping of Kconfig defines to the respective driver enumeration values */
|
||||
|
||||
#if CONFIG_SHT2X_RES_12_14BIT
|
||||
#define CONFIG_SHT2X_RESOLUTION (SHT2X_RES_12_14BIT)
|
||||
#elif CONFIG_SHT2X_RES_11_11BIT
|
||||
#define CONFIG_SHT2X_RESOLUTION (SHT2X_RES_11_11BIT)
|
||||
#elif CONFIG_SHT2X_RES_10_13BIT
|
||||
#define CONFIG_SHT2X_RESOLUTION (SHT2X_RES_10_13BIT)
|
||||
#elif CONFIG_SHT2X_RES_8_12BIT
|
||||
#define CONFIG_SHT2X_RESOLUTION (SHT2X_RES_8_12BIT)
|
||||
#else
|
||||
#define CONFIG_SHT2X_RESOLUTION (SHT2X_RES_12_14BIT)
|
||||
#endif
|
||||
|
||||
#if CONFIG_SHT2X_MEASURE_MODE_HOLD
|
||||
#define CONFIG_SHT2X_MEASURE_MODE (SHT2X_MEASURE_MODE_HOLD)
|
||||
#elif CONFIG_SHT2X_MEASURE_MODE_NO_HOLD
|
||||
#define CONFIG_SHT2X_MEASURE_MODE (SHT2X_MEASURE_MODE_NO_HOLD)
|
||||
#else
|
||||
#define CONFIG_SHT2X_MEASURE_MODE (SHT2X_MEASURE_MODE_NO_HOLD)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SHT2X_CRC_MODE
|
||||
#define CONFIG_SHT2X_CRC_MODE (1)
|
||||
#endif
|
||||
|
||||
#endif /* !DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief Set default configuration parameters for the SHT2X
|
||||
* @name Default SHT2x hardware configuration
|
||||
* @{
|
||||
*/
|
||||
#ifndef SHT2X_PARAM_I2C_DEV
|
||||
/** I2C device used */
|
||||
#define SHT2X_PARAM_I2C_DEV (I2C_DEV(0))
|
||||
#endif
|
||||
|
||||
#ifndef SHT2X_PARAM_I2C_ADDR
|
||||
/** I2C slave slave of the SHT2x sensor */
|
||||
#define SHT2X_PARAM_I2C_ADDR (0x40)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Default sensor configuration for the SHT2x sensor
|
||||
* @{
|
||||
*/
|
||||
#ifndef SHT2X_PARAM_RESOLUTION
|
||||
#define SHT2X_PARAM_RESOLUTION (SHT2X_RES_12_14BIT)
|
||||
#endif
|
||||
#ifndef SHT2X_PARAM_MEASURE_MODE
|
||||
#define SHT2X_PARAM_MEASURE_MODE (SHT2X_MEASURE_MODE_HOLD)
|
||||
#endif
|
||||
#ifndef SHT2X_PARAM_CRC_MODE
|
||||
#define SHT2X_PARAM_CRC_MODE (1)
|
||||
/** SHT2x resolution */
|
||||
#define SHT2X_PARAM_RESOLUTION (CONFIG_SHT2X_RESOLUTION)
|
||||
#endif
|
||||
|
||||
#ifndef SHT2X_PARAM_MEASURE_MODE
|
||||
/** SHT2x measurement mode */
|
||||
#define SHT2X_PARAM_MEASURE_MODE (CONFIG_SHT2X_MEASURE_MODE)
|
||||
#endif
|
||||
|
||||
#ifndef SHT2X_PARAM_CRC_MODE
|
||||
/** SHT2x CRC mode */
|
||||
#define SHT2X_PARAM_CRC_MODE (CONFIG_SHT2X_CRC_MODE)
|
||||
#endif
|
||||
|
||||
/** Default SHT2x parameter set */
|
||||
#define SHT2X_PARAMS_DEFAULT {.i2c_dev = SHT2X_PARAM_I2C_DEV, \
|
||||
.i2c_addr = SHT2X_PARAM_I2C_ADDR, \
|
||||
.resolution = SHT2X_PARAM_RESOLUTION, \
|
||||
@ -58,6 +102,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#ifndef SHT2X_SAUL_INFO
|
||||
/** Default SAUL device info */
|
||||
#define SHT2X_SAUL_INFO { .name = "sht2x" }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 Kees Bakker, SODAQ
|
||||
* Copyright (C) 2017 George Psimenos
|
||||
* Copyright (C) 2018 Steffen Robertz
|
||||
* 2017 George Psimenos
|
||||
* 2018 Steffen Robertz
|
||||
* 2022 Gunar Schorcht
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -13,8 +14,8 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for the SHT2x temperature and
|
||||
* humidity sensor.
|
||||
* @brief Device driver implementation for the SHT2x humidity and
|
||||
* temperature humidity sensor.
|
||||
*
|
||||
* @author Kees Bakker <kees@sodaq.com>
|
||||
* @author George Psimenos <gp7g14@soton.ac.uk>
|
||||
@ -25,11 +26,13 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "checksum/crc8.h"
|
||||
#include "log.h"
|
||||
#include "periph/i2c.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "sht2x.h"
|
||||
#include "sht2x_params.h"
|
||||
#include "periph/i2c.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -93,7 +96,7 @@ int sht2x_init(sht2x_t* dev, const sht2x_params_t* params)
|
||||
return SHT2X_ERR_I2C;
|
||||
}
|
||||
/* wait 15 ms for device to reset */
|
||||
xtimer_msleep(15);
|
||||
ztimer_sleep(ZTIMER_MSEC, 15);
|
||||
|
||||
uint8_t userreg;
|
||||
uint8_t userreg2;
|
||||
@ -158,7 +161,7 @@ int16_t sht2x_read_temperature(const sht2x_t* dev)
|
||||
if (i2c_result != SHT2X_OK) {
|
||||
return INT16_MIN;
|
||||
}
|
||||
return (-46.85 + 175.72 / 65536.0 * raw_value) * 100;
|
||||
return ((17572 * raw_value) / 65536) - 4685;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -176,7 +179,7 @@ uint16_t sht2x_read_humidity(const sht2x_t *dev)
|
||||
if (i2c_result != SHT2X_OK) {
|
||||
return 0;
|
||||
}
|
||||
return 100 * (-6.0 + 125.0 / 65536.0 * raw_value);
|
||||
return ((12500 * raw_value) / 65536) - 600;
|
||||
}
|
||||
|
||||
static size_t _sht2x_add_ident_byte(uint8_t * buffer, size_t buflen, uint8_t b, size_t ix)
|
||||
@ -357,17 +360,24 @@ static int read_sensor_poll(const sht2x_t* dev, cmd_t command, uint16_t *val)
|
||||
uint8_t buffer[3];
|
||||
int i2c_result;
|
||||
|
||||
/* Acquire exclusive access */
|
||||
/* acquire the bus for exclusive access */
|
||||
i2c_acquire(_BUS);
|
||||
|
||||
DEBUG("[SHT2x] write command: addr=%02x cmd=%02x\n", _ADDR, (uint8_t)command);
|
||||
(void)i2c_write_byte(_BUS, _ADDR, (uint8_t)command, 0);
|
||||
/* release the bus for measurement duration */
|
||||
i2c_release(_BUS);
|
||||
|
||||
/* sleep for measurement duration */
|
||||
if (command == temp_no_hold_cmd) {
|
||||
sleep_during_temp_measurement(dev->params.resolution);
|
||||
} else {
|
||||
sleep_during_hum_measurement(dev->params.resolution);
|
||||
}
|
||||
|
||||
/* reacquire the bus for exclusive access */
|
||||
i2c_acquire(_BUS);
|
||||
|
||||
uint8_t ix = 0;
|
||||
for (; ix < MAX_RETRIES; ix++) {
|
||||
i2c_result = i2c_read_bytes(_BUS, _ADDR, buffer, sizeof(buffer), 0);
|
||||
@ -398,39 +408,27 @@ static int read_sensor_poll(const sht2x_t* dev, cmd_t command, uint16_t *val)
|
||||
return SHT2X_OK;
|
||||
}
|
||||
|
||||
static const uint16_t POLYNOMIAL = 0x131; /* P(x)=x^8+x^5+x^4+1 = 100110001 */
|
||||
static const uint8_t POLYNOMIAL = 0x31; /* P(x)=x^8+x^5+x^4+1 = 100110001 */
|
||||
/**
|
||||
* @brief Calculate 8-Bit checksum with given polynomial
|
||||
*/
|
||||
static uint8_t sht2x_checkcrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
uint8_t byteCtr;
|
||||
for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
|
||||
{
|
||||
crc ^= (data[byteCtr]);
|
||||
for (uint8_t bit = 8; bit > 0; --bit)
|
||||
{
|
||||
if ((crc & 0x80) != 0)
|
||||
crc = (crc << 1) ^ POLYNOMIAL;
|
||||
else
|
||||
crc = (crc << 1);
|
||||
}
|
||||
}
|
||||
if (crc != checksum)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return crc8(data, nbrOfBytes, POLYNOMIAL, 0) != checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the given SHT2X device
|
||||
* @brief Sleep during measurement
|
||||
*
|
||||
* @param[in] res The resolution bits in the User Register
|
||||
* @param[in] res The resolution bits in the User Register
|
||||
*
|
||||
* @details Sleep for the typical time it takes to complete the measurement
|
||||
* @details Sleep for the maximum time it takes to complete the measurement
|
||||
* this depends on the resolution and is taken from the datasheet.
|
||||
* Measurement time differs for temperature and humidity.
|
||||
*
|
||||
* @note According to the data sheet, typical times are recommended for
|
||||
* calculating energy consumption, while maximum values should be
|
||||
* used for calculating waiting times in communication.
|
||||
*/
|
||||
static void sleep_during_temp_measurement(sht2x_res_t res)
|
||||
{
|
||||
@ -438,19 +436,19 @@ static void sleep_during_temp_measurement(sht2x_res_t res)
|
||||
|
||||
switch (res) {
|
||||
case SHT2X_RES_12_14BIT:
|
||||
amount_ms = 66;
|
||||
amount_ms = 85;
|
||||
break;
|
||||
case SHT2X_RES_8_12BIT:
|
||||
amount_ms = 17;
|
||||
amount_ms = 22;
|
||||
break;
|
||||
case SHT2X_RES_10_13BIT:
|
||||
amount_ms = 33;
|
||||
amount_ms = 43;
|
||||
break;
|
||||
case SHT2X_RES_11_11BIT:
|
||||
amount_ms = 9;
|
||||
amount_ms = 11;
|
||||
break;
|
||||
}
|
||||
xtimer_msleep(amount_ms);
|
||||
ztimer_sleep(ZTIMER_MSEC, amount_ms);
|
||||
}
|
||||
|
||||
static void sleep_during_hum_measurement(sht2x_res_t resolution)
|
||||
@ -459,17 +457,17 @@ static void sleep_during_hum_measurement(sht2x_res_t resolution)
|
||||
|
||||
switch (resolution) {
|
||||
case SHT2X_RES_12_14BIT:
|
||||
amount_ms = 22;
|
||||
amount_ms = 29;
|
||||
break;
|
||||
case SHT2X_RES_8_12BIT:
|
||||
amount_ms = 3;
|
||||
amount_ms = 4;
|
||||
break;
|
||||
case SHT2X_RES_10_13BIT:
|
||||
amount_ms = 7;
|
||||
amount_ms = 9;
|
||||
break;
|
||||
case SHT2X_RES_11_11BIT:
|
||||
amount_ms = 12;
|
||||
amount_ms = 15;
|
||||
break;
|
||||
}
|
||||
xtimer_msleep(amount_ms);
|
||||
ztimer_sleep(ZTIMER_MSEC, amount_ms);
|
||||
}
|
||||
|
@ -3,6 +3,6 @@ include ../Makefile.tests_common
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
|
||||
USEMODULE += sht2x
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += ztimer_sec
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
@ -1,4 +1,4 @@
|
||||
# this file enables modules defined in Kconfig. Do not use this file for
|
||||
# application configuration. This is only needed during migration.
|
||||
CONFIG_MODULE_SHT2X=y
|
||||
CONFIG_MODULE_XTIMER=y
|
||||
CONFIG_MODULE_ZTIMER_SEC=y
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
#include "sht2x_params.h"
|
||||
#include "sht2x.h"
|
||||
#include "xtimer.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#define SLEEP_2S (2 * 1000 * 1000u) /* 2 seconds delay between printf */
|
||||
#define SLEEP_2S (2) /* 2 seconds delay between printf */
|
||||
|
||||
static void dump_buffer(const char* txt, uint8_t* buffer, size_t len);
|
||||
|
||||
@ -94,7 +94,7 @@ int main(void)
|
||||
);
|
||||
}
|
||||
|
||||
xtimer_usleep(SLEEP_2S);
|
||||
ztimer_sleep(ZTIMER_SEC, SLEEP_2S);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user