From f48c91bd077c073fecf5749e475f386600393055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Mon, 18 Dec 2017 17:06:09 +0100 Subject: [PATCH] Support for BME280 sensor --- code/espurna/config/prototypes.h | 4 +- code/espurna/config/sensors.h | 20 +++- code/espurna/sensor.ino | 7 +- code/espurna/sensors/BME280Sensor.h | 170 ++++++++++++++++++++++++++++ code/platformio.ini | 1 + 5 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 code/espurna/sensors/BME280Sensor.h diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 1d5b0a65..61f7cba1 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -78,11 +78,13 @@ template bool idbSend(const char * topic, unsigned char id, T payloa #if DS18B20_SUPPORT #include #endif - #if PMSX003_SUPPORT #include #include #endif +#if BME280_SUPPORT +#include +#endif // ----------------------------------------------------------------------------- // Utils diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 06c83919..8eb4c1ef 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -58,6 +58,24 @@ #define SI7021_ADDRESS 0x40 #endif +//-------------------------------------------------------------------------------- +// BME280 +// Enable support by passing BME280_SUPPORT=1 build flag +//-------------------------------------------------------------------------------- + +#ifndef BME280_SUPPORT +#define BME280_SUPPORT 0 +#endif + +#ifndef BME280_ADDRESS +#define BME280_ADDRESS 0x76 +#endif + +#define BME280_MODE 1 // 1 for forced mode, 3 for normal mode +#define BME280_TEMPERATURE 1 // Oversampling for temperature (set to 0 to disable magnitude) +#define BME280_HUMIDITY 1 // Oversampling for humidity (set to 0 to disable magnitude) +#define BME280_PRESSURE 1 // Oversampling for pressure (set to 0 to disable magnitude) + //-------------------------------------------------------------------------------- // DS18B20 temperature sensor // Enable support by passing DS18B20_SUPPORT=1 build flag @@ -206,7 +224,7 @@ //-------------------------------------------------------------------------------- #ifndef PMSX003_SUPPORT -#define PMSX003_SUPPORT 1 +#define PMSX003_SUPPORT 0 #endif #define PMS_RX_PIN 13 diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 88e237ed..e1685bd6 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -242,6 +242,11 @@ void sensorInit() { sensorRegister(new SI7021Sensor(SI7021_ADDRESS)); #endif + #if BME280_SUPPORT + #include "sensors/BME280Sensor.h" + sensorRegister(new BME280Sensor(BME280_ADDRESS)); + #endif + #if ANALOG_SUPPORT #include "sensors/AnalogSensor.h" sensorRegister(new AnalogSensor(ANALOG_PIN)); @@ -261,7 +266,7 @@ void sensorInit() { #include "sensors/EmonADS1X15Sensor.h" sensorRegister(new EmonADS1X15Sensor(EMON_ADS1X15_I2C_ADDRESS, EMON_ADS1X15_ADS1115, EMON_ADS1X15_PORT_MASK, EMON_MAINS_VOLTAGE, EMON_ADS1X15_ADC_BITS, EMON_ADS1X15_REFERENCE_VOLTAGE, EMON_ADS1X15_CURRENT_RATIO)); #endif - + #if PMSX003_SUPPORT #include "sensors/PMSX003Sensor.h" sensorRegister(new PMSX003Sensor(PMS_RX_PIN, PMS_TX_PIN)); diff --git a/code/espurna/sensors/BME280Sensor.h b/code/espurna/sensors/BME280Sensor.h new file mode 100644 index 00000000..7b7acb43 --- /dev/null +++ b/code/espurna/sensors/BME280Sensor.h @@ -0,0 +1,170 @@ +// ----------------------------------------------------------------------------- +// BME280 Sensor +// ----------------------------------------------------------------------------- + +#pragma once + +#include "Arduino.h" +#include "BaseSensor.h" +#include + +#define BME280_ERROR_UNKNOW_CHIP -1 + +class BME280Sensor : public BaseSensor { + + public: + + BME280Sensor(unsigned char address = BME280_ADDRESS): BaseSensor() { + + // Cache + _address = address; + _measurement_delay = bmeMeasurementTime(); + + #if BME280_TEMPERATURE > 0 + ++_count; + #endif + #if BME280_HUMIDITY > 0 + ++_count; + #endif + #if BME280_PRESSURE > 0 + ++_count; + #endif + + // Init + bme = new BME280(); + bme->settings.commInterface = I2C_MODE; + bme->settings.I2CAddress = _address; + bme->settings.runMode = BME280_MODE; + bme->settings.tStandby = 0; + bme->settings.filter = 0; + bme->settings.tempOverSample = BME280_TEMPERATURE; + bme->settings.pressOverSample = BME280_PRESSURE; + bme->settings.humidOverSample = BME280_HUMIDITY; + + // Fix when not measuring temperature, t_fine should have a sensible value + if (BME280_TEMPERATURE == 0) bme->t_fine = 100000; // aprox 20ÂșC + + // Make sure sensor had enough time to turn on. BME280 requires 2ms to start up + delay(10); + + // Check sensor correctly initialized + unsigned char response = bme->begin(); + if (response == 0x60) { + _ready = true; + } else { + _error = BME280_ERROR_UNKNOW_CHIP; + } + + } + + // Descriptive name of the sensor + String name() { + char buffer[20]; + snprintf(buffer, sizeof(buffer), "BME280 @ I2C (0x%02X)", _address); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return name(); + } + + // Type for slot # index + magnitude_t type(unsigned char index) { + if (index < _count) { + _error = SENSOR_ERROR_OK; + unsigned char i = 0; + #if BME280_TEMPERATURE > 0 + if (index == i++) return MAGNITUDE_TEMPERATURE; + #endif + #if BME280_HUMIDITY > 0 + if (index == i++) return MAGNITUDE_HUMIDITY; + #endif + #if BME280_PRESSURE > 0 + if (index == i) return MAGNITUDE_PRESSURE; + #endif + } + _error = SENSOR_ERROR_OUT_OF_RANGE; + return MAGNITUDE_NONE; + } + + // Pre-read hook (usually to populate registers with up-to-date data) + virtual void pre() { + + if (!_ready) { + _error = BME280_ERROR_UNKNOW_CHIP; + return; + } + + #if BME280_MODE == 1 + bmeForceRead(); + #endif + + } + + // Current value for slot # index + double value(unsigned char index) { + + if (index < _count) { + _error = SENSOR_ERROR_OK; + unsigned char i = 0; + #if BME280_TEMPERATURE > 0 + if (index == i++) return bme->readTempC(); + #endif + #if BME280_HUMIDITY > 0 + if (index == i++) return bme->readFloatHumidity(); + #endif + #if BME280_PRESSURE > 0 + if (index == i) return bme->readFloatPressure() / 100; + #endif + } + _error = SENSOR_ERROR_OUT_OF_RANGE; + return 0; + } + + protected: + + unsigned long bmeMeasurementTime() { + + // Measurement Time (as per BME280 datasheet section 9.1) + // T_max(ms) = 1.25 + // + (2.3 * T_oversampling) + // + (2.3 * P_oversampling + 0.575) + // + (2.4 * H_oversampling + 0.575) + // ~ 9.3ms for current settings + + double t = 1.25; + #if BME280_TEMPERATURE > 0 + t += (2.3 * BME280_TEMPERATURE); + #endif + #if BME280_HUMIDITY > 0 + t += (2.4 * BME280_HUMIDITY + 0.575); + #endif + #if BME280_PRESSURE > 0 + t += (2.3 * BME280_PRESSURE + 0.575); + #endif + + return round(t + 1); // round up + + } + + void bmeForceRead() { + + // We set the sensor in "forced mode" to force a reading. + // After the reading the sensor will go back to sleep mode. + uint8_t value = bme->readRegister(BME280_CTRL_MEAS_REG); + value = (value & 0xFC) + 0x01; + bme->writeRegister(BME280_CTRL_MEAS_REG, value); + + delay(_measurement_delay); + + } + + // --------------------------------------------------------------------- + + BME280 * bme; + unsigned char _address; + unsigned long _measurement_delay; + bool _ready = false; + +}; diff --git a/code/platformio.ini b/code/platformio.ini index 485dbf59..717466ae 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -21,6 +21,7 @@ lib_deps = NtpClientLib OneWire Brzo I2C + SparkFun BME280 https://github.com/krosk93/espsoftwareserial#a770677 PMS Library https://bitbucket.org/xoseperez/justwifi.git#1.1.4