Skip to content

Commit

Permalink
Merge pull request #15684 from iosabi/drv_si705x
Browse files Browse the repository at this point in the history
drivers/si70xx: Add support for Si705x sensors
  • Loading branch information
basilfx committed Apr 21, 2021
2 parents 9e29754 + f72efb1 commit cc645c0
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 44 deletions.
32 changes: 30 additions & 2 deletions drivers/include/si70xx.h
Expand Up @@ -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.
* @{
Expand All @@ -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
*/
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down
32 changes: 21 additions & 11 deletions drivers/saul/init_devs/auto_init_si70xx.c
Expand Up @@ -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
*/
Expand All @@ -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
Expand All @@ -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);

Expand All @@ -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 */
}
}
20 changes: 15 additions & 5 deletions drivers/si70xx/include/si70xx_internals.h
Expand Up @@ -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)
Expand Down
27 changes: 10 additions & 17 deletions drivers/si70xx/si70xx.c
Expand Up @@ -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 };
Expand Down Expand Up @@ -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;
Expand All @@ -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;;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/si70xx/si70xx_saul.c
Expand Up @@ -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);
Expand All @@ -39,15 +40,18 @@ 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,
.write = saul_notsup,
.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 */
5 changes: 5 additions & 0 deletions makefiles/pseudomodules.inc.mk
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions tests/driver_si70xx/Makefile
@@ -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
23 changes: 16 additions & 7 deletions tests/driver_si70xx/main.c
Expand Up @@ -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]");
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit cc645c0

Please sign in to comment.