From 62da8aa283fcd0e505f5f3ed775757da77e2de6b Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Tue, 3 Apr 2018 13:46:08 +0200 Subject: [PATCH] Initial checkin of empty MCP9808 driver --- include/mgos_mcp9808.h | 54 ++++++++++++++++++++++++ src/main.c | 19 ++++++++- src/mgos_mcp9808.c | 82 +++++++++++++++++++++++++++++++++++++ src/mgos_mcp9808_internal.h | 36 ++++++++++++++++ 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 include/mgos_mcp9808.h create mode 100644 src/mgos_mcp9808.c create mode 100644 src/mgos_mcp9808_internal.h diff --git a/include/mgos_mcp9808.h b/include/mgos_mcp9808.h new file mode 100644 index 0000000..5fb7d05 --- /dev/null +++ b/include/mgos_mcp9808.h @@ -0,0 +1,54 @@ +#pragma once + +#include "mgos.h" +#include "mgos_i2c.h" + +#define MGOS_MCP9808_READ_DELAY (2) + +#ifdef __cplusplus +extern "C" { +#endif + +struct mgos_mcp9808; + +/* + * Initialize a MCP9808 on the I2C bus `i2c` at address specified in `i2caddr` + * parameter (default MCP9808 is on address 0x18). The sensor will be polled for + * validity, upon success a new `struct mgos_mcp9808` is allocated and + * returned. If the device could not be found, NULL is returned. + */ +struct mgos_mcp9808 *mgos_mcp9808_create(struct mgos_i2c *i2c, uint8_t i2caddr); + +/* + * Destroy the data structure associated with a MCP9808 device. The reference + * to the pointer of the `struct mgos_mcp9808` has to be provided, and upon + * successful destruction, its associated memory will be freed and the pointer + * set to NULL. + */ +void mgos_mcp9808_destroy(struct mgos_mcp9808 **sensor); + +/* + * The sensor will be polled for its temperature and humidity data. If the poll + * has occured in the last `MGOS_MCP9808_READ_DELAY` seconds, the cached data is + * used (so as not to repeatedly poll the bus upon subsequent calls). + */ +bool mgos_mcp9808_read(struct mgos_mcp9808 *sensor); + +/* + * The sensor will be polled for its temperature and humidity data. If the poll + * has occured in the last `MGOS_MCP9808_READ_DELAY` seconds, the cached data is + * used (so as not to repeatedly poll the bus upon subsequent calls). + * + * The return value is the temperature of the sensor in Celsius, or NAN if no + * data was found. + */ +float mgos_mcp9808_getTemperature(struct mgos_mcp9808 *sensor); + +/* + * Initialization function for MGOS -- currently a noop. + */ +bool mgos_mcp9808_i2c_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/main.c b/src/main.c index 1657754..c9dce46 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,11 @@ #include "mgos_sht31.h" #include "mgos_si7021.h" #include "mgos_htu21df.h" +#include "mgos_mcp9808.h" #include #include -#define I2CBUSNR 7 +#define I2CBUSNR 5 void i2c_scanner(struct mgos_i2c *i2c) { int i; @@ -76,11 +77,23 @@ bool do_htu21df(struct mgos_htu21df *sensor) { return true; } +bool do_mcp9808(struct mgos_mcp9808 *sensor) { + float temp; + + if (!sensor) return false; + + temp=mgos_mcp9808_getTemperature(sensor); + LOG(LL_INFO, ("temperature=%.2fC", temp)); + + return true; +} + int main() { struct mgos_i2c *i2c; struct mgos_si7021 *si7021; struct mgos_sht31 *sht31; struct mgos_htu21df *htu21df; + struct mgos_mcp9808 *mcp9808; if (!mgos_i2c_open(I2CBUSNR)) { LOG(LL_ERROR, ("Cannot open I2C bus %u", I2CBUSNR)); @@ -102,6 +115,9 @@ int main() { if (!(htu21df = mgos_htu21df_create(i2c, 0x40))) LOG(LL_ERROR, ("Cannot create HTU21DF device")); + if (!(mcp9808 = mgos_mcp9808_create(i2c, 0x18))) + LOG(LL_ERROR, ("Cannot create MCP9808 device")); + for (;;) { do_sht31(sht31); do_si7021(si7021); @@ -112,6 +128,7 @@ int main() { mgos_sht31_destroy(&sht31); mgos_si7021_destroy(&si7021); mgos_htu21df_destroy(&htu21df); + mgos_mcp9808_destroy(&mcp9808); return 0; } diff --git a/src/mgos_mcp9808.c b/src/mgos_mcp9808.c new file mode 100644 index 0000000..ff54497 --- /dev/null +++ b/src/mgos_mcp9808.c @@ -0,0 +1,82 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mgos.h" +#include "mgos_mcp9808_internal.h" +#include "mgos_i2c.h" + +// Datasheet: +// https://cdn-shop.adafruit.com/datasheets/MCP9808.pdf + +// Private functions follow +// Private functions end + +// Public functions follow +struct mgos_mcp9808 *mgos_mcp9808_create(struct mgos_i2c *i2c, uint8_t i2caddr) { + struct mgos_mcp9808 *sensor; + + if (!i2c) return NULL; + + sensor=calloc(1, sizeof(struct mgos_mcp9808)); + if (!sensor) return NULL; + sensor->i2caddr=i2caddr; + sensor->i2c=i2c; + sensor->last_read_time=0; + + // Check for the right chip. + if (false) { + LOG(LL_INFO, ("MCP9808 created at I2C 0x%02x", i2caddr)); + return sensor; + } + + LOG(LL_ERROR, ("Failed to create MCP9808 at I2C 0x%02x", i2caddr)); + free(sensor); + return NULL; +} + +void mgos_mcp9808_destroy(struct mgos_mcp9808 **sensor) { + if (!*sensor) return; + free (*sensor); + *sensor=NULL; + return; +} + +bool mgos_mcp9808_read(struct mgos_mcp9808 *sensor) { + double now = mg_time(); + + if (!sensor || !sensor->i2c) + return false; + + if (now - sensor->last_read_time < MGOS_MCP9808_READ_DELAY) { + return true; + } + // Read out sensor data here + // + LOG(LL_DEBUG, ("temperature=%.2fC", sensor->temperature)); + sensor->last_read_time=now; + return true; +} + +float mgos_mcp9808_getTemperature(struct mgos_mcp9808 *sensor) { + if (!mgos_mcp9808_read(sensor)) return NAN; + + return sensor->temperature; +} + +bool mgos_mcp9808_i2c_init(void) { + return true; +} +// Public functions end diff --git a/src/mgos_mcp9808_internal.h b/src/mgos_mcp9808_internal.h new file mode 100644 index 0000000..2a20fec --- /dev/null +++ b/src/mgos_mcp9808_internal.h @@ -0,0 +1,36 @@ +#pragma once + +#include "mgos.h" +#include "mgos_i2c.h" +#include "mgos_mcp9808.h" +#include + +#define MGOS_MCP9808_DEFAULT_I2CADDR (0x18) + +#define MGOS_MCP9808_MEAS_HIGHREP_STRETCH (0x2C06) +#define MGOS_MCP9808_MEAS_MEDREP_STRETCH (0x2C0D) +#define MGOS_MCP9808_MEAS_LOWREP_STRETCH (0x2C10) +#define MGOS_MCP9808_MEAS_HIGHREP (0x2400) +#define MGOS_MCP9808_MEAS_MEDREP (0x240B) +#define MGOS_MCP9808_MEAS_LOWREP (0x2416) +#define MGOS_MCP9808_READSTATUS (0xF32D) +#define MGOS_MCP9808_CLEARSTATUS (0x3041) +#define MGOS_MCP9808_SOFTRESET (0x30A2) +#define MGOS_MCP9808_HEATEREN (0x306D) +#define MGOS_MCP9808_HEATERDIS (0x3066) + +#ifdef __cplusplus +extern "C" { +#endif + +struct mgos_mcp9808 { + struct mgos_i2c *i2c; + uint8_t i2caddr; + double last_read_time; + + float temperature; +}; + +#ifdef __cplusplus +} +#endif