From 9f0cdbb821a5ecec9388cc0f06db392ae7d39ae0 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Mon, 2 Apr 2018 22:36:46 +0200 Subject: [PATCH] Initial driver for HTU21DF --- src/main.c | 25 ++++++++++++--- src/mgos_htu21df.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- src/mgos_sht31.c | 1 + 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index bfc3e32..1657754 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include "mgos_i2c.h" #include "mgos_sht31.h" #include "mgos_si7021.h" +#include "mgos_htu21df.h" #include #include @@ -63,10 +64,23 @@ bool do_si7021(struct mgos_si7021 *sensor) { return true; } +bool do_htu21df(struct mgos_htu21df *sensor) { + float temp, humid; + + if (!sensor) return false; + + temp=mgos_htu21df_getTemperature(sensor); + humid=mgos_htu21df_getHumidity(sensor); + LOG(LL_INFO, ("temperature=%.2fC humidity=%.1f%%", temp, humid)); + + return true; +} + int main() { struct mgos_i2c *i2c; struct mgos_si7021 *si7021; struct mgos_sht31 *sht31; + struct mgos_htu21df *htu21df; if (!mgos_i2c_open(I2CBUSNR)) { LOG(LL_ERROR, ("Cannot open I2C bus %u", I2CBUSNR)); @@ -79,22 +93,25 @@ int main() { i2c_scanner(i2c); - if (!(sht31 = mgos_sht31_create(i2c, 0x44))) { + if (!(sht31 = mgos_sht31_create(i2c, 0x44))) LOG(LL_ERROR, ("Cannot create SHT31 device")); - } - if (!(si7021 = mgos_si7021_create(i2c, 0x40))) { + if (!(si7021 = mgos_si7021_create(i2c, 0x40))) LOG(LL_ERROR, ("Cannot create SI7021 device")); - } + + if (!(htu21df = mgos_htu21df_create(i2c, 0x40))) + LOG(LL_ERROR, ("Cannot create HTU21DF device")); for (;;) { do_sht31(sht31); do_si7021(si7021); + do_htu21df(htu21df); sleep(5); } mgos_sht31_destroy(&sht31); mgos_si7021_destroy(&si7021); + mgos_htu21df_destroy(&htu21df); return 0; } diff --git a/src/mgos_htu21df.c b/src/mgos_htu21df.c index 0de346a..e97fcac 100644 --- a/src/mgos_htu21df.c +++ b/src/mgos_htu21df.c @@ -22,11 +22,36 @@ // https://cdn-shop.adafruit.com/datasheets/1899_HTU21D.pdf // Private functions follow +static bool mgos_htu21df_cmd(struct mgos_htu21df *sensor, uint8_t cmd) { + + if (!sensor || !sensor->i2c) + return false; + + if (!mgos_i2c_write(sensor->i2c, sensor->i2caddr, &cmd, 1, true)) { + LOG(LL_ERROR, ("I2C=0x%02x cmd=%u (0x%02x) write error", sensor->i2caddr, cmd, cmd)); + return false; + } + LOG(LL_DEBUG, ("I2C=0x%02x cmd=%u (0x%02x) write success", sensor->i2caddr, cmd, cmd)); + return true; +} + +static uint8_t crc8(const uint8_t *data, int len) { + const uint8_t poly=0x31; + uint8_t crc=0x00; + + for (int j=len; j; --j) { + crc^=*data++; + for (int i=8; i; --i) + crc=(crc & 0x80) ? (crc << 1) ^ poly : (crc << 1); + } + return crc; +} // Private functions end // Public functions follow struct mgos_htu21df *mgos_htu21df_create(struct mgos_i2c *i2c, uint8_t i2caddr) { struct mgos_htu21df *sensor; + uint8_t version; if (!i2c) return NULL; @@ -36,8 +61,23 @@ struct mgos_htu21df *mgos_htu21df_create(struct mgos_i2c *i2c, uint8_t i2caddr) sensor->i2c=i2c; sensor->last_read_time=0; - LOG(LL_INFO, ("HTU21DF created at I2C 0x%02x", i2caddr)); - return sensor; + mgos_htu21df_cmd(sensor, MGOS_HTU21DF_RESET); + mgos_usleep(25000); + + mgos_htu21df_cmd(sensor, MGOS_HTU21DF_READREG); + if (!mgos_i2c_read(sensor->i2c, sensor->i2caddr, &version, 1, false)) { + LOG(LL_ERROR, ("Could not read command")); + free(sensor); + return NULL; + } + if (version == 0x02) { + LOG(LL_INFO, ("HTU21DF created at I2C 0x%02x", i2caddr)); + return sensor; + } + + LOG(LL_ERROR, ("Failed to create HTU21DF at I2C 0x%02x", i2caddr)); + free(sensor); + return NULL; } void mgos_htu21df_destroy(struct mgos_htu21df **sensor) { @@ -58,7 +98,42 @@ bool mgos_htu21df_read(struct mgos_htu21df *sensor) { } // Read out sensor data here // + uint8_t data[3]; + + mgos_htu21df_cmd(sensor, MGOS_HTU21DF_READTEMP); + if (!mgos_i2c_read(sensor->i2c, sensor->i2caddr, data, 3, false)) { + LOG(LL_ERROR, ("Could not read command")); + return false; + } + if (data[2] != crc8(data, 2)) { + LOG(LL_ERROR, ("CRC error on temperature data")); + return false; + } + uint16_t temp = (data[0]<<8)+data[1]; + float temperature = temp; + temperature *= 175.72; + temperature /= 65536; + temperature -= 46.85; + sensor->temperature=temperature; + + mgos_htu21df_cmd(sensor, MGOS_HTU21DF_READHUM); + if (!mgos_i2c_read(sensor->i2c, sensor->i2caddr, data, 3, false)) { + LOG(LL_ERROR, ("Could not read command")); + return false; + } + if (data[2] != crc8(data, 2)) { + LOG(LL_ERROR, ("CRC error on temperature data")); + return false; + } + + uint16_t hum = (data[0]<<8)+data[1]; + float humidity = hum; + humidity *= 125; + humidity /= 65536; + humidity -= 6; + sensor->humidity=humidity; + LOG(LL_DEBUG, ("temperature=%.2fC humidity=%.1f%%", sensor->temperature, sensor->humidity)); sensor->last_read_time=now; return true; diff --git a/src/mgos_sht31.c b/src/mgos_sht31.c index 82ea114..9ac4757 100644 --- a/src/mgos_sht31.c +++ b/src/mgos_sht31.c @@ -96,6 +96,7 @@ struct mgos_sht31 *mgos_sht31_create(struct mgos_i2c *i2c, uint8_t i2caddr) { return sensor; } + LOG(LL_ERROR, ("Failed to create SHT31 at I2C 0x%02x", i2caddr)); free(sensor); return NULL; }