From 89ec34dc1d628127c48f4dd9de87b8392f5285b5 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sat, 21 Apr 2018 15:17:24 +0200 Subject: [PATCH] Add mgos_barometer API --- include/mgos_barometer.h | 54 ++++++++++++++++ src/main.c | 27 +++++++- src/mgos_barometer.c | 113 ++++++++++++++++++++++++++++++++++ src/mgos_barometer_internal.h | 52 ++++++++++++++++ src/mgos_barometer_mpl115.c | 62 +++++++++++++++++++ src/mgos_barometer_mpl115.h | 17 +++++ src/mgos_barometer_mpl3115.h | 0 7 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 include/mgos_barometer.h create mode 100644 src/mgos_barometer.c create mode 100644 src/mgos_barometer_internal.h create mode 100644 src/mgos_barometer_mpl115.c create mode 100644 src/mgos_barometer_mpl115.h create mode 100644 src/mgos_barometer_mpl3115.h diff --git a/include/mgos_barometer.h b/include/mgos_barometer.h new file mode 100644 index 0000000..f98f91d --- /dev/null +++ b/include/mgos_barometer.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#pragma once + +#include "mgos.h" +#include "mgos_i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum mgos_barometer_type { + BARO_NONE = 0, + BARO_MPL115 +}; + +struct mgos_barometer; + +struct mgos_barometer *mgos_barometer_create_i2c(struct mgos_i2c *i2c, uint8_t i2caddr, enum mgos_barometer_type type); +void mgos_barometer_destroy(struct mgos_barometer **sensor); +bool mgos_barometer_has_thermometer(struct mgos_barometer *sensor); +bool mgos_barometer_has_barometer(struct mgos_barometer *sensor); + +/* Read all available sensor data from the IMU */ +bool mgos_barometer_read(struct mgos_barometer *sensor); + +/* Return barometer data in units of Pascals */ +bool mgos_barometer_get_pressure(struct mgos_barometer *sensor, float *p); + +/* Return temperature data in units of Celcius */ +bool mgos_barometer_get_temperature(struct mgos_barometer *sensor, float *t); + +/* + * Initialization function for MGOS -- currently a noop. + */ +bool mgos_barometer_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/main.c b/src/main.c index bdee7be..4374ff0 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ #include "mgos_ccs811.h" #include "mgos_mpu9250.h" #include "mgos_imu.h" +#include "mgos_barometer.h" #include #include @@ -154,6 +155,22 @@ bool do_mpu9250(struct mgos_mpu9250 *sensor) { return true; } +bool do_baro(struct mgos_barometer *sensor) { + float pressure, temperature; + + if (!sensor) + return false; + + if (mgos_barometer_get_pressure(sensor, &pressure)) { + LOG(LL_INFO, ("Pressure %.2fPa", pressure)); + } + if (mgos_barometer_get_temperature(sensor, &temperature)) { + LOG(LL_INFO, ("Temperature %.2fC", temperature)); + } + + return true; +} + int main() { struct mgos_i2c * i2c; struct mgos_si7021 * si7021; @@ -162,6 +179,7 @@ int main() { struct mgos_mcp9808 *mcp9808; struct mgos_ccs811 * ccs811; struct mgos_mpu9250 *mpu9250; + struct mgos_barometer *baro; if (!mgos_i2c_open(I2CBUSNR)) { LOG(LL_ERROR, ("Cannot open I2C bus %u", I2CBUSNR)); @@ -187,6 +205,7 @@ int main() { * LOG(LL_ERROR, ("Cannot create CCS811 device")); */ + /* if (!(mpu9250 = mgos_mpu9250_create(i2c, 0x68))) { LOG(LL_ERROR, ("Cannot create MPU9250 device")); } else { @@ -195,6 +214,10 @@ int main() { mgos_mpu9250_set_magnetometer_scale(mpu9250, SCALE_14_BITS); mgos_mpu9250_set_magnetometer_speed(mpu9250, MAG_100_HZ); } + */ + if (!(baro=mgos_barometer_create_i2c(i2c, 0x60, BARO_MPL115))) { + LOG(LL_ERROR, ("Cannot create MPL115 barometer")); + } for (;;) { /* @@ -203,8 +226,9 @@ int main() { * do_htu21df(htu21df); * do_mcp9808(mcp9808); * do_ccs811(ccs811); + * do_mpu9250(mpu9250); */ - do_mpu9250(mpu9250); + do_baro(baro); sleep(1); } @@ -214,6 +238,7 @@ int main() { mgos_mcp9808_destroy(&mcp9808); mgos_ccs811_destroy(&ccs811); mgos_mpu9250_destroy(&mpu9250); + mgos_barometer_destroy(&baro); return 0; } diff --git a/src/mgos_barometer.c b/src/mgos_barometer.c new file mode 100644 index 0000000..81fea2e --- /dev/null +++ b/src/mgos_barometer.c @@ -0,0 +1,113 @@ +/* + * 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_barometer_internal.h" +#include "mgos_barometer_mpl115.h" +#include "mgos_barometer_mpl3115.h" + +// Private functions follow +// Private functions end + +// Public functions follow +struct mgos_barometer *mgos_barometer_create_i2c(struct mgos_i2c *i2c, uint8_t i2caddr, enum mgos_barometer_type type) { + struct mgos_barometer *sensor; + + if (!i2c) { + return NULL; + } + + sensor = calloc(1, sizeof(struct mgos_barometer)); + if (!sensor) { + return NULL; + } + memset(sensor, 0, sizeof(struct mgos_barometer)); + sensor->i2c=i2c; + sensor->i2caddr=i2caddr; + switch(type) { + case BARO_MPL115: + sensor->create = mgos_barometer_mpl115_create; + sensor->read = mgos_barometer_mpl115_read; + sensor->destroy = mgos_barometer_mpl115_destroy; + break; + default: + LOG(LL_ERROR, ("Unknown mgos_barometer_type %d", type)); + free(sensor); + return NULL; + } + if ((sensor->detect) && !sensor->detect(sensor)) { + LOG(LL_ERROR, ("Could not detect mgos_barometer_type %d at I2C 0x%02x", type, i2caddr)); + free(sensor); + return NULL; + } + + if ((sensor->create) && !sensor->create(sensor)) { + LOG(LL_ERROR, ("Could not create mgos_barometer_type %d at I2C 0x%02x", type, i2caddr)); + free(sensor); + return NULL; + } + + return sensor; +} + +void mgos_barometer_destroy(struct mgos_barometer **sensor) { + if (!*sensor) { + return; + } + if ((*sensor)->destroy && !(*sensor)->destroy(*sensor)) { + LOG(LL_ERROR, ("Could not destroy mgos_barometer_type %d at I2C 0x%02x", (*sensor)->type, (*sensor)->i2caddr)); + } + if ((*sensor)->user_data) free ((*sensor)->user_data); + free(*sensor); + *sensor = NULL; + return; +} + +bool mgos_barometer_has_thermometer(struct mgos_barometer *sensor) { + if (!sensor) return false; + return sensor->has_thermometer; +} + +bool mgos_barometer_has_barometer(struct mgos_barometer *sensor) { + if (!sensor) return false; + return sensor->has_barometer; +} + +bool mgos_barometer_read(struct mgos_barometer *sensor) { + if (!sensor) return false; + if (!sensor->read) return false; + return sensor->read(sensor); +} + +bool mgos_barometer_get_pressure(struct mgos_barometer *sensor, float *p) { + if (!mgos_barometer_has_barometer(sensor)) return false; + if (!mgos_barometer_read(sensor)) return false; + if (*p) *p=sensor->pressure; + return true; +} + +bool mgos_barometer_get_temperature(struct mgos_barometer *sensor, float *t) { + if (!mgos_barometer_has_thermometer(sensor)) return false; + if (!mgos_barometer_read(sensor)) return false; + if (*t) *t=sensor->temperature; + return true; +} + +bool mgos_barometer_init(void) { + return true; +} + +// Public functions end diff --git a/src/mgos_barometer_internal.h b/src/mgos_barometer_internal.h new file mode 100644 index 0000000..33d6ec5 --- /dev/null +++ b/src/mgos_barometer_internal.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#pragma once + +#include "mgos.h" +#include "mgos_barometer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Barometer +typedef bool (*mgos_barometer_mag_detect_fn)(struct mgos_barometer *dev); +typedef bool (*mgos_barometer_mag_create_fn)(struct mgos_barometer *dev); +typedef bool (*mgos_barometer_mag_destroy_fn)(struct mgos_barometer *dev); +typedef bool (*mgos_barometer_mag_read_fn)(struct mgos_barometer *dev); + +struct mgos_barometer { + struct mgos_i2c * i2c; + uint8_t i2caddr; + enum mgos_barometer_type type; + bool has_thermometer; + bool has_barometer; + + mgos_barometer_mag_detect_fn detect; + mgos_barometer_mag_create_fn create; + mgos_barometer_mag_destroy_fn destroy; + mgos_barometer_mag_read_fn read; + + void *user_data; + + float pressure; // in Pascals + float temperature; // in Celcius +}; + +#ifdef __cplusplus +} +#endif diff --git a/src/mgos_barometer_mpl115.c b/src/mgos_barometer_mpl115.c new file mode 100644 index 0000000..e7a6e82 --- /dev/null +++ b/src/mgos_barometer_mpl115.c @@ -0,0 +1,62 @@ +#include "mgos_barometer_mpl115.h" +#include "mgos_i2c.h" + +bool mgos_barometer_mpl115_create(struct mgos_barometer *dev) { + struct mgos_barometer_mpl115_data *mpl115_data; + + if (!dev) return false; + uint8_t data[8]; + if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, MPL115_REG_COEFF_BASE, 8, data)) + return false; + + mpl115_data=calloc(1, sizeof(struct mgos_barometer_mpl115_data)); + if (!mpl115_data) return false; + + mpl115_data->a0=(float)(((uint16_t) data[0] << 8) | data[1]) / 8.0; + mpl115_data->b1=(float)(((uint16_t) data[2] << 8) | data[3]) / 8192.0; + mpl115_data->b2=(float)(((uint16_t) data[4] << 8) | data[5]) / 16384.0; + mpl115_data->c12=(float)((((uint16_t) (data[6] << 8) | data[7])) >> 2) / 4194304.0; + dev->user_data=mpl115_data; + LOG(LL_DEBUG, ("Calibration data: a0=%.4f b1=%.4f b2=%.4f c12=%.4f", mpl115_data->a0, mpl115_data->b1, mpl115_data->b2, mpl115_data->c12)); + + dev->has_barometer=true; + dev->has_thermometer=true; + return true; +} + +bool mgos_barometer_mpl115_destroy(struct mgos_barometer *dev) { + if (!dev) return false; + if (dev->user_data) { + free(dev->user_data); + dev->user_data=NULL; + } + return true; +} + +bool mgos_barometer_mpl115_read(struct mgos_barometer *dev) { + struct mgos_barometer_mpl115_data *mpl115_data; + uint16_t Padc, Tadc; + float Pcomp; + + if (!dev) return false; + mpl115_data=(struct mgos_barometer_mpl115_data *) dev->user_data; + if (!mpl115_data) return false; + + if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, MPL115_REG_START, 0x00)) + return false; + + mgos_usleep(4000); + uint8_t data[4]; + if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, MPL115_REG_PRESSURE, 4, data)) + return false; + Padc=(((uint16_t) data[0] << 8) | data[1]) >> 6; + Tadc=(((uint16_t) data[2] << 8) | data[3]) >> 6; + + Pcomp= mpl115_data->a0 + (mpl115_data->b1 + mpl115_data->c12 * Tadc ) * Padc + mpl115_data->b2 * Tadc; + + dev->pressure= 1000*Pcomp*(65.0/1023) + 50.0; // Pascals + dev->temperature=((float) Tadc - 498.0F) / -5.35F +25.0F; // Celsius + + return true; +} + diff --git a/src/mgos_barometer_mpl115.h b/src/mgos_barometer_mpl115.h new file mode 100644 index 0000000..4e5d870 --- /dev/null +++ b/src/mgos_barometer_mpl115.h @@ -0,0 +1,17 @@ +#pragma once + +#include "mgos.h" +#include "mgos_barometer_internal.h" + +#define MPL115_REG_PRESSURE (0x00) +#define MPL115_REG_TEMPERATURE (0x02) +#define MPL115_REG_COEFF_BASE (0x04) +#define MPL115_REG_START (0x12) + +struct mgos_barometer_mpl115_data { + float a0, b1, b2, c12; +}; + +bool mgos_barometer_mpl115_create(struct mgos_barometer *dev); +bool mgos_barometer_mpl115_destroy(struct mgos_barometer *dev); +bool mgos_barometer_mpl115_read(struct mgos_barometer *dev); diff --git a/src/mgos_barometer_mpl3115.h b/src/mgos_barometer_mpl3115.h new file mode 100644 index 0000000..e69de29