1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/si70xx: Add support for Si705x sensors

The Silicon Labs Si705x sensors (Si7050/1/3/4/5) are very similar to the
Si7021 sensors featuring only a temperature sensor and no humidity
sensor. The only difference between the Si705x is the temperature
accuracy of the reading, ranging from +/- 0.1 C in the Si7051 to +/- 1 C
in the Si7050.

This patch adds support for this family of sensors extending the
functionality of the existing si70xx driver. Following the style of
other modules, this implements a pseudomodule per supported chip, adding
si7050, si7051, si7053, si7054 and si7055 pseudomodules.

As a minor change this patch also implements the missing
si70xx_get_serial, si70xx_get_id and si70xx_get_revision functions that
were declared in the si70xx.h header but implemented as private
functions. The si70xx_get_id() may be relevant for the application to
know at run time exactly which version of the hardware is installed.

The updated test running with a Si7051 shows the following output, which
seems consistent with the room temperature conditions during the test.

```
make SI70XX_VARIANT=si7051 -C tests/driver_si70xx/ all flash
```

```
SI70XX temperature and humidity sensor test application
Initializing sensor...
[OK]
Found SI7051 sensor, revision 32
temperature: 24.71 C
temperature: 24.69 C
```
This commit is contained in:
iosabi 2020-04-18 19:52:54 +00:00
parent dec82b2475
commit f72efb1daf
8 changed files with 105 additions and 44 deletions

View File

@ -7,10 +7,19 @@
*/
/**
* @defgroup drivers_si70xx Si7006/13/20/21 temperature and humidity sensors
* @defgroup drivers_si70xx Si7006/13/20/21/5x temperature and humidity sensors
* @ingroup drivers_sensors
* @ingroup drivers_saul
* @brief Driver for the Si7006/13/20/21 temperature and humidity sensor
* @brief Driver for the Si7006/13/20/21/5x temperature and humidity sensor
*
* The Si70xx driver supports a range of similar temperature and humidity
* sensors from Silicon Labs.
*
* The Si7006/13/20/21 sensors support both temperature and relative humidity
* reading, while the Si7050/1/3/4/5 sensors only provide a temperature reading
* varying in accuracy between +/- 0.1 C to +/- 1.0 C depending on the model.
*
* For any of the Si705x models, use the pseudo module @p si705x.
*
* This driver provides @ref drivers_saul capabilities.
* @{
@ -30,6 +39,17 @@
extern "C" {
#endif
/**
* @brief Compile time macro telling whether the chip has a humidity sensor.
*/
#if MODULE_SI7050 || MODULE_SI7051 || MODULE_SI7053 || MODULE_SI7054 || \
MODULE_SI7055
/* Si705x sensors don't have a humidity sensor hardware, only temperature. */
#define SI70XX_HAS_HUMIDITY_SENSOR 0
#else
#define SI70XX_HAS_HUMIDITY_SENSOR 1
#endif
/**
* @brief Driver return codes
*/
@ -67,13 +87,17 @@ typedef struct {
*/
int si70xx_init(si70xx_t *dev, const si70xx_params_t *params);
#if SI70XX_HAS_HUMIDITY_SENSOR || DOXYGEN
/**
* @brief Read the relative humidity from the sensor. Uses clock stretching.
*
* This function is only available in models that have a humidity sensor.
*
* @param[in] dev device descriptor
* @return relative humidity in centi-percent (times 100)
*/
uint16_t si70xx_get_relative_humidity(const si70xx_t *dev);
#endif /* SI70XX_HAS_HUMIDITY_SENSOR || DOXYGEN */
/**
* @brief Read the current temperature from the sensor. Uses clock stretching.
@ -84,15 +108,19 @@ uint16_t si70xx_get_relative_humidity(const si70xx_t *dev);
*/
int16_t si70xx_get_temperature(const si70xx_t *dev);
#if SI70XX_HAS_HUMIDITY_SENSOR || DOXYGEN
/**
* @brief Read the relative humidity and temperature from the sensor. Uses
* clock stretching.
*
* This function is only available in models that have a humidity sensor.
*
* @param[in] dev device descriptor
* @param[out] humidity pointer to relative humidity (in centi-percent)
* @param[out] temperature pointer to temperature (in centi-degrees Celsius)
*/
void si70xx_get_both(const si70xx_t *dev, uint16_t *humidity, int16_t *temperature);
#endif /* SI70XX_HAS_HUMIDITY_SENSOR || DOXYGEN */
/**
* @brief Read the sensor serial number.

View File

@ -29,6 +29,15 @@
*/
#define SI70XX_NUM ARRAY_SIZE(si70xx_params)
/**
* @brief Define the number of SAUL registry entries
*/
#if SI70XX_HAS_HUMIDITY_SENSOR
#define SI70XX_SAUL_ENTRIES_NUM 2
#else
#define SI70XX_SAUL_ENTRIES_NUM 1
#endif
/**
* @brief Allocation of memory for device descriptors
*/
@ -37,7 +46,7 @@ static si70xx_t si70xx_devs[SI70XX_NUM];
/**
* @brief Memory for the SAUL registry entries
*/
static saul_reg_t saul_entries[SI70XX_NUM * 2];
static saul_reg_t saul_entries[SI70XX_NUM * SI70XX_SAUL_ENTRIES_NUM];
/**
* @brief Define the number of saul info
@ -56,6 +65,7 @@ void auto_init_si70xx(void)
{
assert(SI70XX_INFO_NUM == SI70XX_NUM);
unsigned entry = 0;
for (unsigned i = 0; i < SI70XX_NUM; i++) {
LOG_DEBUG("[auto_init_saul] initializing SI70xx #%u\n", i);
@ -65,17 +75,17 @@ void auto_init_si70xx(void)
}
/* temperature */
saul_entries[i * 2].dev = &si70xx_devs[i];
saul_entries[i * 2].name = si70xx_saul_info[i].name;
saul_entries[i * 2].driver = &si70xx_temperature_saul_driver;
saul_entries[entry].dev = &si70xx_devs[i];
saul_entries[entry].name = si70xx_saul_info[i].name;
saul_entries[entry].driver = &si70xx_temperature_saul_driver;
saul_reg_add(&saul_entries[entry++]);
#if SI70XX_HAS_HUMIDITY_SENSOR
/* relative humidity */
saul_entries[(i * 2) + 1].dev = &si70xx_devs[i];
saul_entries[(i * 2) + 1].name = si70xx_saul_info[i].name;
saul_entries[(i * 2) + 1].driver = \
&si70xx_relative_humidity_saul_driver;
saul_reg_add(&saul_entries[i * 2]);
saul_reg_add(&saul_entries[(i * 2) + 1]);
saul_entries[entry].dev = &si70xx_devs[i];
saul_entries[entry].name = si70xx_saul_info[i].name;
saul_entries[entry].driver = &si70xx_relative_humidity_saul_driver;
saul_reg_add(&saul_entries[entry++]);
#endif /* SI70XX_HAS_HUMIDITY_SENSOR */
}
}

View File

@ -55,15 +55,25 @@ extern "C" {
* @{
*/
#if defined(MODULE_SI7006)
#define SI70XX_ID (0x06)
#define SI70XX_ID (6)
#elif defined(MODULE_SI7013)
#define SI70XX_ID (0x0D)
#define SI70XX_ID (13)
#elif defined(MODULE_SI7020)
#define SI70XX_ID (0x14)
#define SI70XX_ID (20)
#elif defined(MODULE_SI7021)
#define SI70XX_ID (0x15)
#define SI70XX_ID (21)
#elif defined(MODULE_SI7050)
#define SI70XX_ID (50)
#elif defined(MODULE_SI7051)
#define SI70XX_ID (51)
#elif defined(MODULE_SI7053)
#define SI70XX_ID (53)
#elif defined(MODULE_SI7054)
#define SI70XX_ID (54)
#elif defined(MODULE_SI7055)
#define SI70XX_ID (55)
#else
#error "Please provide a valid Si70xx variant (Si7006/13/20/21)"
#error "Please provide a valid Si70xx variant (Si7006/13/20/21/5X)"
#endif
#define SI70XX_REVISION_1 (0xFF)

View File

@ -53,10 +53,7 @@ static uint16_t _do_measure(const si70xx_t *dev, uint8_t command)
return ((uint16_t)result[0] << 8) + (result[1] & 0xfc);
}
/**
* @brief Internal helper function that reads the device serial number.
*/
static uint64_t _get_serial(const si70xx_t *dev)
uint64_t si70xx_get_serial(const si70xx_t *dev)
{
uint8_t out[2];
uint8_t in_first[8] = { 0 };
@ -95,18 +92,12 @@ static uint64_t _get_serial(const si70xx_t *dev)
return (((uint64_t) id_first) << 32) + id_second;
}
/**
* @brief Internal helper function that reads the device identifier.
*/
static uint8_t _get_id(const si70xx_t *dev)
uint8_t si70xx_get_id(const si70xx_t *dev)
{
return (_get_serial(dev) >> 24) & 0xff;
return (si70xx_get_serial(dev) >> 24) & 0xff;
}
/**
* @brief Internal helper function that reads the device serial revision.
*/
static uint8_t _get_revision(const si70xx_t *dev)
uint8_t si70xx_get_revision(const si70xx_t *dev)
{
uint8_t out[2];
uint8_t in = 0;
@ -128,17 +119,19 @@ static uint8_t _get_revision(const si70xx_t *dev)
static int _test_device(const si70xx_t *dev)
{
uint8_t revision = _get_revision(dev);
uint8_t revision = si70xx_get_revision(dev);
if (revision != SI70XX_REVISION_1 && revision != SI70XX_REVISION_2) {
DEBUG("[ERROR] Bad device revision (%d).\n", revision);
return -SI70XX_ERR_NODEV;
}
uint8_t id = _get_id(dev);
uint8_t id = si70xx_get_id(dev);
if (id != SI70XX_ID) {
DEBUG("[ERROR] Not a valid Si7006/13/20/21 device\n");
const bool valid_id = (id == SI70XX_ID);
if (!valid_id) {
DEBUG("[ERROR] Not a valid Si7006/13/20/21/5x device: %u\n",
(unsigned)id);
return -SI70XX_ERR_NODEV;;
}

View File

@ -31,6 +31,7 @@ static int read_temperature(const void *dev, phydat_t *res)
return 1;
}
#if SI70XX_HAS_HUMIDITY_SENSOR
static int read_relative_humidity(const void *dev, phydat_t *res)
{
res->val[0] = (int32_t) si70xx_get_relative_humidity((const si70xx_t *)dev);
@ -39,6 +40,7 @@ static int read_relative_humidity(const void *dev, phydat_t *res)
return 1;
}
#endif /* SI70XX_HAS_HUMIDITY_SENSOR */
const saul_driver_t si70xx_temperature_saul_driver = {
.read = read_temperature,
@ -46,8 +48,10 @@ const saul_driver_t si70xx_temperature_saul_driver = {
.type = SAUL_SENSE_TEMP
};
#if SI70XX_HAS_HUMIDITY_SENSOR
const saul_driver_t si70xx_relative_humidity_saul_driver = {
.read = read_relative_humidity,
.write = saul_notsup,
.type = SAUL_SENSE_HUM
};
#endif /* SI70XX_HAS_HUMIDITY_SENSOR */

View File

@ -262,6 +262,11 @@ PSEUDOMODULES += si7006
PSEUDOMODULES += si7013
PSEUDOMODULES += si7020
PSEUDOMODULES += si7021
PSEUDOMODULES += si7050
PSEUDOMODULES += si7051
PSEUDOMODULES += si7053
PSEUDOMODULES += si7054
PSEUDOMODULES += si7055
#include variants of tmp00x drivers as pseudo modules
PSEUDOMODULES += tmp006

View File

@ -1,6 +1,8 @@
include ../Makefile.tests_common
# This test should also work with Si7006, Si7013 and Si7020 variants.
USEMODULE += si7021
# This test should also work with si7006, si7013, si7020 and si705x variants.
SI70XX_VARIANT ?= si7021
USEMODULE += $(SI70XX_VARIANT)
include $(RIOTBASE)/Makefile.include

View File

@ -29,10 +29,10 @@ int main(void)
{
si70xx_t dev;
puts("SI7021 temperature and humidity sensor test application");
puts("SI70XX temperature and humidity sensor test application");
/* initialize the sensor */
printf("Initializing sensor... ");
puts("Initializing sensor... ");
if (si70xx_init(&dev, &si70xx_params[0]) == 0) {
puts("[OK]");
@ -42,13 +42,17 @@ int main(void)
return 1;
}
printf("Found SI70%02d sensor, revision %d\n", si70xx_get_id(&dev),
si70xx_get_revision(&dev));
/* read temperature and humidity every 1 seconds */
bool both = false;
int16_t temperature;
uint16_t humidity;
while (1) {
int16_t temperature;
#if SI70XX_HAS_HUMIDITY_SENSOR
uint16_t humidity;
/* rotate the way of getting the data */
if (both) {
si70xx_get_both(&dev, &humidity, &temperature);
@ -57,12 +61,17 @@ int main(void)
temperature = si70xx_get_temperature(&dev);
humidity = si70xx_get_relative_humidity(&dev);
}
#else /* SI70XX_HAS_HUMIDITY_SENSOR */
temperature = si70xx_get_temperature(&dev);
#endif /* SI70XX_HAS_HUMIDITY_SENSOR */
both = !both;
/* display results */
#if SI70XX_HAS_HUMIDITY_SENSOR
printf("relative humidity: %d.%02d\n", humidity / 100, humidity % 100);
printf("temperature: %d.%02d C\n", temperature / 100, temperature % 100);
#endif /* SI70XX_HAS_HUMIDITY_SENSOR */
printf("temperature: %d.%02d C\n", temperature / 100,
temperature % 100);
/* sleep between measurements */
xtimer_msleep(1000);