From 8728d55b7bf2bc5712bff08291d704a1429b2310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Tue, 19 Dec 2017 22:51:30 +0100 Subject: [PATCH] Change sensor API, force parameter-less constructors --- code/espurna/config/sensors.h | 218 +++++++++++------------ code/espurna/sensor.ino | 188 ++++++++++++------- code/espurna/sensors/AnalogSensor.h | 19 +- code/espurna/sensors/BMX280Sensor.h | 101 +++++++---- code/espurna/sensors/BaseSensor.h | 3 + code/espurna/sensors/DHTSensor.h | 92 ++++++---- code/espurna/sensors/DallasSensor.h | 25 ++- code/espurna/sensors/DigitalSensor.h | 26 ++- code/espurna/sensors/EmonADC121Sensor.h | 109 +++++------- code/espurna/sensors/EmonADS1X15Sensor.h | 78 ++++++-- code/espurna/sensors/EmonAnalogSensor.h | 57 ++++-- code/espurna/sensors/EmonSensor.h | 71 +++++--- code/espurna/sensors/EventSensor.h | 32 +++- code/espurna/sensors/MHZ19Sensor.h | 28 ++- code/espurna/sensors/PMSX003Sensor.h | 35 +++- code/espurna/sensors/SI7021Sensor.h | 33 +++- 16 files changed, 721 insertions(+), 394 deletions(-) diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 89926fc7..6523dbf6 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -58,160 +58,146 @@ #define SENSOR_EVENTS_TOPIC "events" #define SENSOR_CO2_TOPIC "co2" +#define HUMIDITY_NORMAL 0 +#define HUMIDITY_COMFORTABLE 1 +#define HUMIDITY_DRY 2 +#define HUMIDITY_WET 3 + //-------------------------------------------------------------------------------- -// DHTXX temperature/humidity sensor -// Enable support by passing DHT_SUPPORT=1 build flag +// Analog sensor +// Enable support by passing ANALOG_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef DHT_SUPPORT -#define DHT_SUPPORT 0 -#endif - -#ifndef DHT_PIN -#define DHT_PIN 14 -#endif - -#ifndef DHT_TYPE -#define DHT_TYPE DHT22 +#ifndef ANALOG_SUPPORT +#define ANALOG_SUPPORT 0 #endif -#ifndef DHT_PULLUP -#define DHT_PULLUP 0 +#ifndef ANALOG_PIN +#define ANALOG_PIN 0 #endif -#define HUMIDITY_NORMAL 0 -#define HUMIDITY_COMFORTABLE 1 -#define HUMIDITY_DRY 2 -#define HUMIDITY_WET 3 - -//-------------------------------------------------------------------------------- -// SI7021 temperature & humidity sensor -// Enable support by passing SI7021_SUPPORT=1 build flag -//-------------------------------------------------------------------------------- - -#ifndef SI7021_SUPPORT -#define SI7021_SUPPORT 0 +#ifndef ANALOG_PIN_MODE +#define ANALOG_PIN_MODE INPUT #endif -#ifndef SI7021_ADDRESS -#define SI7021_ADDRESS 0x40 +#if ANALOG_SUPPORT + #undef ADC_VCC_ENABLED + #define ADC_VCC_ENABLED 0 #endif //-------------------------------------------------------------------------------- -// BMX280 +// BME280/BMP280 // Enable support by passing BMX280_SUPPORT=1 build flag //-------------------------------------------------------------------------------- #ifndef BMX280_SUPPORT -#define BMX280_SUPPORT 0 +#define BMX280_SUPPORT 0 #endif #ifndef BMX280_ADDRESS -#define BMX280_ADDRESS 0x76 +#define BMX280_ADDRESS 0 #endif -#define BMX280_MODE 1 // 1 for forced mode, 3 for normal mode -#define BMX280_TEMPERATURE 1 // Oversampling for temperature (set to 0 to disable magnitude) -#define BMX280_HUMIDITY 1 // Oversampling for humidity (set to 0 to disable magnitude, only for BME280) -#define BMX280_PRESSURE 1 // Oversampling for pressure (set to 0 to disable magnitude) +#define BMX280_MODE 1 // 1 for forced mode, 3 for normal mode +#define BMX280_TEMPERATURE 1 // Oversampling for temperature (set to 0 to disable magnitude) +#define BMX280_HUMIDITY 1 // Oversampling for humidity (set to 0 to disable magnitude, only for BME280) +#define BMX280_PRESSURE 1 // Oversampling for pressure (set to 0 to disable magnitude) //-------------------------------------------------------------------------------- -// DS18B20 temperature sensor +// Dallas OneWire temperature sensors // Enable support by passing DALLAS_SUPPORT=1 build flag //-------------------------------------------------------------------------------- #ifndef DALLAS_SUPPORT -#define DALLAS_SUPPORT 0 +#define DALLAS_SUPPORT 0 #endif #ifndef DALLAS_PIN -#define DALLAS_PIN 13 +#define DALLAS_PIN 13 #endif #ifndef DALLAS_PULLUP -#define DALLAS_PULLUP 1 +#define DALLAS_PULLUP 1 #endif -#define DALLAS_RESOLUTION 9 // Not used atm +#define DALLAS_RESOLUTION 9 // Not used atm //-------------------------------------------------------------------------------- -// Digital sensor -// Enable support by passing DIGITAL_SUPPORT=1 build flag +// DHTXX temperature/humidity sensor +// Enable support by passing DHT_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef DIGITAL_SUPPORT -#define DIGITAL_SUPPORT 0 -#endif - -#ifndef DIGITAL_PIN -#define DIGITAL_PIN 2 +#ifndef DHT_SUPPORT +#define DHT_SUPPORT 0 #endif -#ifndef DIGITAL_PIN_MODE -#define DIGITAL_PIN_MODE INPUT_PULLUP +#ifndef DHT_PIN +#define DHT_PIN 13 #endif -#ifndef DIGITAL_DEFAULT_STATE -#define DIGITAL_DEFAULT_STATE 1 +#ifndef DHT_TYPE +#define DHT_TYPE DHT22 #endif - //-------------------------------------------------------------------------------- -// Analog sensor -// Enable support by passing ANALOG_SUPPORT=1 build flag +// Digital sensor +// Enable support by passing DIGITAL_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef ANALOG_SUPPORT -#define ANALOG_SUPPORT 0 +#ifndef DIGITAL_SUPPORT +#define DIGITAL_SUPPORT 0 #endif -#ifndef ANALOG_PIN -#define ANALOG_PIN 0 +#ifndef DIGITAL_PIN +#define DIGITAL_PIN 2 #endif -#ifndef ANALOG_PIN_MODE -#define ANALOG_PIN_MODE INPUT +#ifndef DIGITAL_PIN_MODE +#define DIGITAL_PIN_MODE INPUT_PULLUP #endif -#if ANALOG_SUPPORT - #undef ADC_VCC_ENABLED - #define ADC_VCC_ENABLED 0 +#ifndef DIGITAL_DEFAULT_STATE +#define DIGITAL_DEFAULT_STATE 1 #endif //-------------------------------------------------------------------------------- -// Counter sensor -// Enable support by passing EVENTS_SUPPORT=1 build flag +// Energy Monitor general settings //-------------------------------------------------------------------------------- -#ifndef EVENTS_SUPPORT -#define EVENTS_SUPPORT 0 // Do not build with counter support by default -#endif +#define EMON_MAX_SAMPLES 1000 // Max number of samples to get +#define EMON_MAX_TIME 250 // Max time in ms to sample +#define EMON_FILTER_SPEED 512 // Mobile average filter speed +#define EMON_MAINS_VOLTAGE 230 // Mains voltage +#define EMON_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC +#define EMON_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) +#define EMON_REPORT_CURRENT 0 // Report current +#define EMON_REPORT_POWER 1 // Report power +#define EMON_REPORT_ENERGY 1 // Report energy -#ifndef EVENTS_PIN -#define EVENTS_PIN 2 // GPIO to monitor -#endif - -#ifndef EVENTS_PIN_MODE -#define EVENTS_PIN_MODE INPUT // INPUT, INPUT_PULLUP -#endif +//-------------------------------------------------------------------------------- +// Energy Monitor based on ADC121 +// Enable support by passing EMON_ADC121_SUPPORT=1 build flag +//-------------------------------------------------------------------------------- -#ifndef EVENTS_INTERRUPT_MODE -#define EVENTS_INTERRUPT_MODE RISING // RISING, FALLING, BOTH +#ifndef EMON_ADC121_SUPPORT +#define EMON_ADC121_SUPPORT 0 // Do not build support by default #endif -#define EVENTS_DEBOUNCE 50 // Do not register events within less than 10 millis +#define EMON_ADC121_I2C_ADDRESS 0x50 // I2C address of the ADC121 //-------------------------------------------------------------------------------- -// Energy Monitor general settings +// Energy Monitor based on ADS1X15 +// Enable support by passing EMON_ADS1X15_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#define EMON_MAX_SAMPLES 1000 // Max number of samples to get -#define EMON_MAX_TIME 250 // Max time in ms to sample -#define EMON_FILTER_SPEED 512 // Mobile average filter speed -#define EMON_MAINS_VOLTAGE 230 // Mains voltage -#define EMON_REPORT_CURRENT 0 // Report current -#define EMON_REPORT_POWER 1 // Report power -#define EMON_REPORT_ENERGY 1 // Report energy +#ifndef EMON_ADS1X15_SUPPORT +#define EMON_ADS1X15_SUPPORT 0 // Do not build support by default +#endif + +#define EMON_ADS1X15_I2C_ADDRESS 0x48 // I2C address of the ADS1115 +#define EMON_ADS1X15_TYPE ADS1X15_CHIP_ADS1115 +#define EMON_ADS1X15_GAIN ADS1X15_REG_CONFIG_PGA_4_096V +#define EMON_ADS1X15_MASK 0x0F // A0=1 A1=2 A2=4 A4=8 //-------------------------------------------------------------------------------- // Energy Monitor based on interval analog GPIO @@ -222,46 +208,45 @@ #define EMON_ANALOG_SUPPORT 0 // Do not build support by default #endif -#define EMON_ANALOG_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) -#define EMON_ANALOG_ADC_BITS 10 // ADC depth -#define EMON_ANALOG_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC - #if EMON_ANALOG_SUPPORT #undef ADC_VCC_ENABLED #define ADC_VCC_ENABLED 0 #endif //-------------------------------------------------------------------------------- -// Energy Monitor based on ADC121 -// Enable support by passing EMON_ADC121_SUPPORT=1 build flag +// Counter sensor +// Enable support by passing EVENTS_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef EMON_ADC121_SUPPORT -#define EMON_ADC121_SUPPORT 0 // Do not build support by default +#ifndef EVENTS_SUPPORT +#define EVENTS_SUPPORT 0 // Do not build with counter support by default #endif -#define EMON_ADC121_I2C_ADDRESS 0x50 // I2C address of the ADC121 +#ifndef EVENTS_PIN +#define EVENTS_PIN 2 // GPIO to monitor +#endif -#define EMON_ADC121_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) -#define EMON_ADC121_ADC_BITS 12 // ADC depth -#define EMON_ADC121_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC +#ifndef EVENTS_PIN_MODE +#define EVENTS_PIN_MODE INPUT // INPUT, INPUT_PULLUP +#endif + +#ifndef EVENTS_INTERRUPT_MODE +#define EVENTS_INTERRUPT_MODE RISING // RISING, FALLING, BOTH +#endif + +#define EVENTS_DEBOUNCE 50 // Do not register events within less than 10 millis //-------------------------------------------------------------------------------- -// Energy Monitor based on ADS1X15 -// Enable support by passing EMON_ADS1X15_SUPPORT=1 build flag +// MHZ19 CO2 sensor +// Enable support by passing MHZ19_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef EMON_ADS1X15_SUPPORT -#define EMON_ADS1X15_SUPPORT 0 // Do not build support by default +#ifndef MHZ19_SUPPORT +#define MHZ19_SUPPORT 0 #endif -#define EMON_ADS1X15_ADS1115 1 // 0 for ADS10115, 1 for ADS1115 -#define EMON_ADS1X15_PORT_MASK 0x08 // A0=1 A1=2 A2=4 A4=8 -#define EMON_ADS1X15_I2C_ADDRESS 0x48 // I2C address of the ADS1115 - -#define EMON_ADS1X15_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) -#define EMON_ADS1X15_ADC_BITS 16 // ADC depth -#define EMON_ADS1X15_REFERENCE_VOLTAGE 8.192 // Double the gain for peak-to-peak +#define MHZ19_RX_PIN 13 +#define MHZ19_TX_PIN 15 //-------------------------------------------------------------------------------- // Particle Monitor based on Plantower PMSX003 @@ -276,16 +261,17 @@ #define PMS_TX_PIN 15 //-------------------------------------------------------------------------------- -// MHZ19 CO2 sensor -// Enable support by passing MHZ19_SUPPORT=1 build flag +// SI7021 temperature & humidity sensor +// Enable support by passing SI7021_SUPPORT=1 build flag //-------------------------------------------------------------------------------- -#ifndef MHZ19_SUPPORT -#define MHZ19_SUPPORT 0 +#ifndef SI7021_SUPPORT +#define SI7021_SUPPORT 1 #endif -#define MHZ19_RX_PIN 13 -#define MHZ19_TX_PIN 15 +#ifndef SI7021_ADDRESS +#define SI7021_ADDRESS 0x40 +#endif //-------------------------------------------------------------------------------- // Internal power montior diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 15be45e3..525f4c93 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -193,116 +193,183 @@ void _sensorPost() { // ----------------------------------------------------------------------------- // Interrupts // ----------------------------------------------------------------------------- -#if EVENTS_SUPPORT +#if EVENTS_SUPPORT unsigned char _event_sensor_id = 0; -void isrEventSensor() { +void _isrEventSensor() { _sensors[_event_sensor_id]->InterruptHandler(); } - #endif // EVENTS_SUPPORT // ----------------------------------------------------------------------------- -// Values +// Sensor initialization // ----------------------------------------------------------------------------- -void sensorRegister(BaseSensor * sensor) { +void _sensorRegister(BaseSensor * sensor) { + sensor->begin(); _sensors.push_back(sensor); } -unsigned char sensorCount() { - return _sensors.size(); -} +void _sensorInit() { -unsigned char magnitudeCount() { - return _magnitudes.size(); -} - -String magnitudeName(unsigned char index) { - if (index < _magnitudes.size()) { - sensor_magnitude_t magnitude = _magnitudes[index]; - return magnitude.sensor->slot(magnitude.local); + #if ANALOG_SUPPORT + { + #include "sensors/AnalogSensor.h" + AnalogSensor * sensor = new AnalogSensor(); + sensor->setGPIO(ANALOG_PIN, ANALOG_PIN_MODE); + _sensorRegister(sensor); } - return String(); -} + #endif -unsigned char magnitudeType(unsigned char index) { - if (index < _magnitudes.size()) { - return int(_magnitudes[index].type); + #if BMX280_SUPPORT + { + #include "sensors/BMX280Sensor.h" + BMX280Sensor * sensor = new BMX280Sensor(); + sensor->setAddress(BMX280_ADDRESS); + _sensorRegister(sensor); } - return MAGNITUDE_NONE; -} - -void sensorInit() { - - #if DHT_SUPPORT - #include "sensors/DHTSensor.h" - sensorRegister(new DHTSensor(DHT_PIN, DHT_TYPE, DHT_PULLUP)); #endif #if DALLAS_SUPPORT + { #include "sensors/DallasSensor.h" - sensorRegister(new DallasSensor(DALLAS_PIN, SENSOR_READ_INTERVAL, DALLAS_PULLUP)); + DallasSensor * sensor = new DallasSensor(); + sensor->setGPIO(DALLAS_PIN, DALLAS_PULLUP); + _sensorRegister(sensor); + } #endif - #if SI7021_SUPPORT - #include "sensors/SI7021Sensor.h" - sensorRegister(new SI7021Sensor(SI7021_ADDRESS)); + #if DHT_SUPPORT + { + #include "sensors/DHTSensor.h" + DHTSensor * sensor = new DHTSensor(); + sensor->setGPIO(DHT_PIN); + sensor->setType(DHT_TYPE); + _sensorRegister(sensor); + } #endif - #if BMX280_SUPPORT - #include "sensors/BMX280Sensor.h" - sensorRegister(new BMX280Sensor(BMX280_ADDRESS)); + #if DIGITAL_SUPPORT + { + #include "sensors/DigitalSensor.h" + DigitalSensor * sensor = new DigitalSensor(); + sensor->setGPIO(DIGITAL_PIN, DIGITAL_PIN_MODE); + sensor->setDefault(DIGITAL_DEFAULT_STATE); + _sensorRegister(sensor); + } #endif - #if ANALOG_SUPPORT - #include "sensors/AnalogSensor.h" - sensorRegister(new AnalogSensor(ANALOG_PIN, ANALOG_PIN_MODE)); + #if EMON_ADC121_SUPPORT + { + #include "sensors/EmonADC121Sensor.h" + EmonADC121Sensor * sensor = new EmonADC121Sensor(); + sensor->setAddress(EMON_ADC121_I2C_ADDRESS); + sensor->setVoltage(EMON_MAINS_VOLTAGE); + sensor->setReference(EMON_REFERENCE_VOLTAGE); + sensor->setCurrentRatio(EMON_CURRENT_RATIO); + _sensorRegister(sensor); + } #endif - #if DIGITAL_SUPPORT - #include "sensors/DigitalSensor.h" - sensorRegister(new DigitalSensor(DIGITAL_PIN, DIGITAL_PIN_MODE, DIGITAL_DEFAULT_STATE)); + #if EMON_ADS1X15_SUPPORT + { + #include "sensors/EmonADS1X15Sensor.h" + EmonADS1X15Sensor * sensor = new EmonADS1X15Sensor(); + sensor->setAddress(EMON_ADS1X15_I2C_ADDRESS); + sensor->setType(EMON_ADS1X15_TYPE); + sensor->setMask(EMON_ADS1X15_MASK); + sensor->setGain(EMON_ADS1X15_GAIN); + sensor->setVoltage(EMON_MAINS_VOLTAGE); + sensor->setCurrentRatio(EMON_CURRENT_RATIO); + _sensorRegister(sensor); + } #endif #if EMON_ANALOG_SUPPORT + { #include "sensors/EmonAnalogSensor.h" - sensorRegister(new EmonAnalogSensor(A0, EMON_MAINS_VOLTAGE, EMON_ANALOG_ADC_BITS, EMON_ANALOG_REFERENCE_VOLTAGE, EMON_ANALOG_CURRENT_RATIO)); + EmonAnalogSensor * sensor = new EmonAnalogSensor(); + sensor->setVoltage(EMON_MAINS_VOLTAGE); + sensor->setReference(EMON_REFERENCE_VOLTAGE); + sensor->setCurrentRatio(EMON_CURRENT_RATIO); + _sensorRegister(sensor); + } #endif - #if EMON_ADC121_SUPPORT - #include "sensors/EmonADC121Sensor.h" - sensorRegister(new EmonADC121Sensor(EMON_ADC121_I2C_ADDRESS, EMON_MAINS_VOLTAGE, EMON_ADC121_ADC_BITS, EMON_ADC121_REFERENCE_VOLTAGE, EMON_ADC121_CURRENT_RATIO)); + #if EVENTS_SUPPORT + { + #include "sensors/EventSensor.h" + EventSensor * sensor = new EventSensor(); + sensor->setGPIO(EVENTS_PIN, EVENTS_PIN_MODE); + sensor->setDebounceTime(EVENTS_DEBOUNCE); + _sensorRegister(sensor); + _event_sensor_id = sensorCount() - 1; + attachInterrupt(EVENTS_PIN, _isrEventSensor, EVENTS_INTERRUPT_MODE); + } #endif - #if EMON_ADS1X15_SUPPORT - #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)); + #if MHZ19_SUPPORT + { + #include "sensors/MHZ19Sensor.h" + MHZ19Sensor * sensor = new MHZ19Sensor(); + sensor->setGPIO(MHZ19_RX_PIN, MHZ19_TX_PIN); + _sensorRegister(sensor); + } #endif #if PMSX003_SUPPORT + { #include "sensors/PMSX003Sensor.h" - sensorRegister(new PMSX003Sensor(PMS_RX_PIN, PMS_TX_PIN)); + PMSX003Sensor * sensor = new PMSX003Sensor(); + sensor->setGPIO(PMS_RX_PIN, PMS_TX_PIN); + _sensorRegister(sensor); + } #endif - #if MHZ19_SUPPORT - #include "sensors/MHZ19Sensor.h" - sensorRegister(new MHZ19Sensor(MHZ19_RX_PIN, MHZ19_TX_PIN)); + #if SI7021_SUPPORT + { + #include "sensors/SI7021Sensor.h" + SI7021Sensor * sensor = new SI7021Sensor(); + sensor->setAddress(SI7021_ADDRESS); + _sensorRegister(sensor); + } #endif - #if EVENTS_SUPPORT - #include "sensors/EventSensor.h" - sensorRegister(new EventSensor(EVENTS_PIN, EVENTS_PIN_MODE, EVENTS_DEBOUNCE)); - _event_sensor_id = sensorCount() - 1; - attachInterrupt(EVENTS_PIN, isrEventSensor, EVENTS_INTERRUPT_MODE); - #endif +} +// ----------------------------------------------------------------------------- +// Values +// ----------------------------------------------------------------------------- + +unsigned char sensorCount() { + return _sensors.size(); +} + +unsigned char magnitudeCount() { + return _magnitudes.size(); } +String magnitudeName(unsigned char index) { + if (index < _magnitudes.size()) { + sensor_magnitude_t magnitude = _magnitudes[index]; + return magnitude.sensor->slot(magnitude.local); + } + return String(); +} + +unsigned char magnitudeType(unsigned char index) { + if (index < _magnitudes.size()) { + return int(_magnitudes[index].type); + } + return MAGNITUDE_NONE; +} + +// ----------------------------------------------------------------------------- + void sensorSetup() { // Load sensors - sensorInit(); + _sensorInit(); // Load magnitudes for (unsigned char i=0; i<_sensors.size(); i++) { @@ -473,5 +540,4 @@ void sensorLoop() { } - } diff --git a/code/espurna/sensors/AnalogSensor.h b/code/espurna/sensors/AnalogSensor.h index 3d641ce8..cf4b1b6c 100644 --- a/code/espurna/sensors/AnalogSensor.h +++ b/code/espurna/sensors/AnalogSensor.h @@ -12,12 +12,23 @@ class AnalogSensor : public BaseSensor { public: - AnalogSensor(unsigned char gpio, int mode = INPUT): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + AnalogSensor(): BaseSensor() { + _count = 1; + } + + void setGPIO(unsigned char gpio, unsigned char mode = INPUT) { _gpio = gpio; pinMode(_gpio, mode); - _count = 1; } + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + // Descriptive name of the sensor String name() { char buffer[20]; @@ -49,6 +60,10 @@ class AnalogSensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + unsigned char _gpio; }; diff --git a/code/espurna/sensors/BMX280Sensor.h b/code/espurna/sensors/BMX280Sensor.h index 4e2683af..4e6342e3 100644 --- a/code/espurna/sensors/BMX280Sensor.h +++ b/code/espurna/sensors/BMX280Sensor.h @@ -17,45 +17,34 @@ class BMX280Sensor : public BaseSensor { public: - BMX280Sensor(unsigned char address = BMX280_ADDRESS): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Cache + void setAddress(unsigned char address) { _address = address; - _measurement_delay = bmeMeasurementTime(); - - // Init - bme = new BME280(); - bme->settings.commInterface = I2C_MODE; - bme->settings.I2CAddress = _address; - bme->settings.runMode = BMX280_MODE; - bme->settings.tStandby = 0; - bme->settings.filter = 0; - bme->settings.tempOverSample = BMX280_TEMPERATURE; - bme->settings.pressOverSample = BMX280_PRESSURE; - bme->settings.humidOverSample = BMX280_HUMIDITY; + } - // Fix when not measuring temperature, t_fine should have a sensible value - if (BMX280_TEMPERATURE == 0) bme->t_fine = 100000; // aprox 20ºC + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- - // Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up - delay(10); + // Initialization method, must be idempotent + void begin() { - // Check sensor correctly initialized - _chip = bme->begin(); - if ((_chip != BMX280_CHIP_BME280) && (_chip != BMX280_CHIP_BMP280)) { - _chip = 0; + // Discover + if (_address == 0) { + unsigned char addresses[] = {0x76, 0x77}; + _address = i2cFindFirst(2, addresses); + } + if (_address == 0) { _error = SENSOR_ERROR_UNKNOWN_ID; + _chip = 0; + return; } - #if BMX280_TEMPERATURE > 0 - ++_count; - #endif - #if BMX280_PRESSURE > 0 - ++_count; - #endif - #if BMX280_HUMIDITY > 0 - if (_chip == BMX280_CHIP_BME280) ++_count; - #endif + // Init + init(); } @@ -101,7 +90,7 @@ class BMX280Sensor : public BaseSensor { } #if BMX280_MODE == 1 - bmeForceRead(); + forceRead(); #endif } @@ -130,7 +119,49 @@ class BMX280Sensor : public BaseSensor { protected: - unsigned long bmeMeasurementTime() { + void init() { + + // Destroy previous instance if any + if (bme) delete bme; + + bme = new BME280(); + bme->settings.commInterface = I2C_MODE; + bme->settings.I2CAddress = _address; + bme->settings.runMode = BMX280_MODE; + bme->settings.tStandby = 0; + bme->settings.filter = 0; + bme->settings.tempOverSample = BMX280_TEMPERATURE; + bme->settings.pressOverSample = BMX280_PRESSURE; + bme->settings.humidOverSample = BMX280_HUMIDITY; + + // Fix when not measuring temperature, t_fine should have a sensible value + if (BMX280_TEMPERATURE == 0) bme->t_fine = 100000; // aprox 20ºC + + // Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up + delay(10); + + // Check sensor correctly initialized + _chip = bme->begin(); + if ((_chip != BMX280_CHIP_BME280) && (_chip != BMX280_CHIP_BMP280)) { + _chip = 0; + _error = SENSOR_ERROR_UNKNOWN_ID; + } + + #if BMX280_TEMPERATURE > 0 + ++_count; + #endif + #if BMX280_PRESSURE > 0 + ++_count; + #endif + #if BMX280_HUMIDITY > 0 + if (_chip == BMX280_CHIP_BME280) ++_count; + #endif + + _measurement_delay = measurementTime(); + + } + + unsigned long measurementTime() { // Measurement Time (as per BMX280 datasheet section 9.1) // T_max(ms) = 1.25 @@ -156,7 +187,7 @@ class BMX280Sensor : public BaseSensor { } - void bmeForceRead() { + void forceRead() { // We set the sensor in "forced mode" to force a reading. // After the reading the sensor will go back to sleep mode. @@ -172,7 +203,7 @@ class BMX280Sensor : public BaseSensor { BME280 * bme; unsigned char _chip; - unsigned char _address; + unsigned char _address = 0; unsigned long _measurement_delay; }; diff --git a/code/espurna/sensors/BaseSensor.h b/code/espurna/sensors/BaseSensor.h index 5c96f17b..a1ce002a 100644 --- a/code/espurna/sensors/BaseSensor.h +++ b/code/espurna/sensors/BaseSensor.h @@ -58,6 +58,9 @@ class BaseSensor { // General interrupt handler virtual void InterruptHandler() {} + // Initialization method, must be idempotent + virtual void begin() {} + // Loop-like method, call it in your main loop virtual void tick() {} diff --git a/code/espurna/sensors/DHTSensor.h b/code/espurna/sensors/DHTSensor.h index a72c6e57..4b3e9efe 100644 --- a/code/espurna/sensors/DHTSensor.h +++ b/code/espurna/sensors/DHTSensor.h @@ -21,15 +21,68 @@ class DHTSensor : public BaseSensor { public: - DHTSensor(unsigned char gpio, unsigned char type, bool pull_up = false): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + DHTSensor(): BaseSensor() { + _count = 2; + } + + void setGPIO(unsigned char gpio) { _gpio = gpio; + } + + void setType(unsigned char type) { _type = type; - if (pull_up) pinMode(_gpio, INPUT_PULLUP); - _count = 2; } + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + // Pre-read hook (usually to populate registers with up-to-date data) void pre() { + _read(); + } + + // Descriptive name of the sensor + String name() { + char buffer[20]; + snprintf(buffer, sizeof(buffer), "DHT%d @ GPIO%d", _type, _gpio); + 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) { + _error = SENSOR_ERROR_OK; + if (index == 0) return MAGNITUDE_TEMPERATURE; + if (index == 1) return MAGNITUDE_HUMIDITY; + _error = SENSOR_ERROR_OUT_OF_RANGE; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + _error = SENSOR_ERROR_OK; + if (index == 0) return _temperature; + if (index == 1) return _humidity; + _error = SENSOR_ERROR_OUT_OF_RANGE; + return 0; + } + + protected: + + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + + void _read() { if ((_last_ok > 0) && (millis() - _last_ok < DHT_MIN_INTERVAL)) { _error = SENSOR_ERROR_OK; @@ -123,39 +176,6 @@ class DHTSensor : public BaseSensor { } - // Descriptive name of the sensor - String name() { - char buffer[20]; - snprintf(buffer, sizeof(buffer), "DHT%d @ GPIO%d", _type, _gpio); - 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) { - _error = SENSOR_ERROR_OK; - if (index == 0) return MAGNITUDE_TEMPERATURE; - if (index == 1) return MAGNITUDE_HUMIDITY; - _error = SENSOR_ERROR_OUT_OF_RANGE; - return MAGNITUDE_NONE; - } - - // Current value for slot # index - double value(unsigned char index) { - _error = SENSOR_ERROR_OK; - if (index == 0) return _temperature; - if (index == 1) return _humidity; - _error = SENSOR_ERROR_OUT_OF_RANGE; - return 0; - } - - - protected: - unsigned long _signal(int usTimeOut, bool state) { unsigned long uSec = 1; while (digitalRead(_gpio) == state) { diff --git a/code/espurna/sensors/DallasSensor.h b/code/espurna/sensors/DallasSensor.h index 8f46bdc2..6f977512 100644 --- a/code/espurna/sensors/DallasSensor.h +++ b/code/espurna/sensors/DallasSensor.h @@ -29,17 +29,29 @@ class DallasSensor : public BaseSensor { public: - DallasSensor(unsigned char gpio, unsigned long interval, bool pull_up = false): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Cache params + void setGPIO(unsigned char gpio, bool pullup = false) { _gpio = gpio; - _interval = interval / 2; + _interval = SENSOR_READ_INTERVAL / 2; + _pullup = pullup; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { // OneWire + if (_wire) delete _wire; _wire = new OneWire(_gpio); // Must be done after the OneWire initialization - if (pull_up) pinMode(_gpio, INPUT_PULLUP); + if (_pullup) pinMode(_gpio, INPUT_PULLUP); // Search devices loadDevices(); @@ -194,6 +206,10 @@ class DallasSensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + unsigned char chip(unsigned char index) { if (index < _count) return _devices[index].address[0]; return 0; @@ -234,6 +250,7 @@ class DallasSensor : public BaseSensor { unsigned char _gpio; unsigned long _interval; + bool _pullup; OneWire * _wire; }; diff --git a/code/espurna/sensors/DigitalSensor.h b/code/espurna/sensors/DigitalSensor.h index 95e7e35e..0afa463c 100644 --- a/code/espurna/sensors/DigitalSensor.h +++ b/code/espurna/sensors/DigitalSensor.h @@ -12,13 +12,27 @@ class DigitalSensor : public BaseSensor { public: - DigitalSensor(unsigned char gpio, int mode = INPUT, bool default_state = false): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + DigitalSensor(): BaseSensor() { + _count = 1; + } + + void setGPIO(unsigned char gpio, int mode = INPUT) { _gpio = gpio; - _default = default_state; pinMode(_gpio, mode); - _count = 1; } + void setDefault(bool value) { + _default = value; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + // Descriptive name of the sensor String name() { char buffer[20]; @@ -50,7 +64,11 @@ class DigitalSensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + unsigned char _gpio; - bool _default; + bool _default = false; }; diff --git a/code/espurna/sensors/EmonADC121Sensor.h b/code/espurna/sensors/EmonADC121Sensor.h index 2ee410dd..6e622993 100644 --- a/code/espurna/sensors/EmonADC121Sensor.h +++ b/code/espurna/sensors/EmonADC121Sensor.h @@ -8,6 +8,7 @@ #include "Arduino.h" #include "BaseSensor.h" #include "EmonSensor.h" +#include "EmonAnalogSensor.h" #if I2C_USE_BRZO #include @@ -25,15 +26,36 @@ #define ADC121_REG_CONVL 0x06 #define ADC121_REG_CONVH 0x07 -class EmonADC121Sensor : public EmonSensor { +#define ADC121_RESOLUTION 12 + +class EmonADC121Sensor : public EmonAnalogSensor { public: - EmonADC121Sensor(unsigned char address, double voltage, unsigned char bits, double ref, double ratio): EmonSensor(voltage, bits, ref, ratio) { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Cache + void setAddress(unsigned char address) { _address = address; - _count = _magnitudes; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + // Discover + if (_address == 0) { + unsigned char addresses[] = {0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A}; + _address = i2cFindFirst(9, addresses); + } + if (_address == 0) { + _error = SENSOR_ERROR_UNKNOWN_ID; + return; + } // Init sensor #if I2C_USE_BRZO @@ -50,8 +72,18 @@ class EmonADC121Sensor : public EmonSensor { Wire.endTransmission(); #endif - // warmup - read(_address, _pivot); + // Just one channel + _count = _magnitudes; + + // Bit depth + _resolution = ADC121_RESOLUTION; + + // Call the parent class method + EmonSensor::begin(); + + // warmup channel 0 (the only one) + _pivot = _adc_counts >> 1; + read(0, _pivot); } @@ -62,62 +94,24 @@ class EmonADC121Sensor : public EmonSensor { return String(buffer); } - // Descriptive name of the slot # index - String slot(unsigned char index) { - return name(); - } + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() { - // Type for slot # index - magnitude_t type(unsigned char index) { - _error = SENSOR_ERROR_OK; - unsigned char i = 0; - #if EMON_REPORT_CURRENT - if (index == i++) return MAGNITUDE_CURRENT; - #endif - #if EMON_REPORT_POWER - if (index == i++) return MAGNITUDE_POWER_APPARENT; - #endif - #if EMON_REPORT_ENERGY - if (index == i) return MAGNITUDE_ENERGY; - #endif - _error = SENSOR_ERROR_OUT_OF_RANGE; - return MAGNITUDE_NONE; - } - - // Current value for slot # index - double value(unsigned char index) { - - _error = SENSOR_ERROR_OK; - - // Cache the value - static unsigned long last = 0; - if ((last == 0) || (millis() - last > 1000)) { - _current = read(0, _pivot); - #if EMON_REPORT_ENERGY - _energy += (_current * _voltage * (millis() - last) / 1000); - #endif - last = millis(); + if (_address == 0) { + _error = SENSOR_ERROR_UNKNOWN_ID; + return; } - // Report - unsigned char i = 0; - #if EMON_REPORT_CURRENT - if (index == i++) return _current; - #endif - #if EMON_REPORT_POWER - if (index == i++) return _current * _voltage; - #endif - #if EMON_REPORT_ENERGY - if (index == i) return _energy; - #endif - - _error = SENSOR_ERROR_OUT_OF_RANGE; - return 0; + EmonAnalogSensor:pre(); } protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + unsigned int readADC(unsigned char channel) { unsigned int value; @@ -144,11 +138,6 @@ class EmonADC121Sensor : public EmonSensor { } - unsigned char _address; - double _pivot = 0; - double _current = 0; - #if EMON_REPORT_ENERGY - unsigned long _energy = 0; - #endif + unsigned char _address = 0; }; diff --git a/code/espurna/sensors/EmonADS1X15Sensor.h b/code/espurna/sensors/EmonADS1X15Sensor.h index 3a1153f6..8b3baa39 100644 --- a/code/espurna/sensors/EmonADS1X15Sensor.h +++ b/code/espurna/sensors/EmonADS1X15Sensor.h @@ -17,6 +17,11 @@ #define ADS1X15_CHANNELS (4) +#define ADS1X15_CHIP_ADS1015 (0) +#define ADS1X15_CHIP_ADS1115 (1) + +#define ADS1X15_RESOLUTION (16) + #define ADS1015_CONVERSIONDELAY (1) #define ADS1115_CONVERSIONDELAY (8) @@ -96,20 +101,67 @@ class EmonADS1X15Sensor : public EmonSensor { public: - EmonADS1X15Sensor(unsigned char address, bool is_ads1115, unsigned char mask, double voltage, unsigned char bits, double ref, double ratio): EmonSensor(voltage, bits, ref, ratio) { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Cache - _is_ads1115 = is_ads1115; + void setAddress(unsigned char address) { _address = address; + } + + void setType(unsigned char type) { + _type = type; + } + + void setMask(unsigned char mask) { _mask = mask; + } + + void setGain(unsigned int gain) { + _gain = gain; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + // Discover + if (_address == 0) { + unsigned char addresses[] = {0x48, 0x49, 0x4A, 0x4B}; + _address = i2cFindFirst(4, addresses); + } + if (_address == 0) { + _error = SENSOR_ERROR_UNKNOWN_ID; + return; + } + + // Calculate ports _ports = 0; + unsigned char mask = _mask; while (mask) { if (mask & 0x01) ++_ports; mask = mask >> 1; } _count = _ports * _magnitudes; - // warmup + // Bit depth + _resolution = ADS1X15_RESOLUTION; + + // Reference based on gain + if (_gain == ADS1X15_REG_CONFIG_PGA_6_144V) _reference = 12.288; + if (_gain == ADS1X15_REG_CONFIG_PGA_4_096V) _reference = 8.192; + if (_gain == ADS1X15_REG_CONFIG_PGA_2_048V) _reference = 4.096; + if (_gain == ADS1X15_REG_CONFIG_PGA_1_024V) _reference = 2.048; + if (_gain == ADS1X15_REG_CONFIG_PGA_0_512V) _reference = 1.024; + if (_gain == ADS1X15_REG_CONFIG_PGA_0_256V) _reference = 0.512; + + // Call the parent class method + EmonSensor::begin(); + + // warmup all channels warmup(); } @@ -117,7 +169,7 @@ class EmonADS1X15Sensor : public EmonSensor { // Descriptive name of the sensor String name() { char buffer[30]; - snprintf(buffer, sizeof(buffer), "EMON @ ADS1%d15 @ I2C (0x%02X)", _is_ads1115 ? 1 : 0, _address); + snprintf(buffer, sizeof(buffer), "EMON @ ADS1%d15 @ I2C (0x%02X)", _type == ADS1X15_CHIP_ADS1015 ? 0 : 1, _address); return String(buffer); } @@ -125,7 +177,7 @@ class EmonADS1X15Sensor : public EmonSensor { String slot(unsigned char index) { char buffer[35]; unsigned char channel = getChannel(index % _ports); - snprintf(buffer, sizeof(buffer), "EMON @ ADS1%d15 (A%d) @ I2C (0x%02X)", _is_ads1115 ? 1 : 0, channel, _address); + snprintf(buffer, sizeof(buffer), "EMON @ ADS1%d15 (A%d) @ I2C (0x%02X)", _type == ADS1X15_CHIP_ADS1015 ? 0 : 1, channel, _address); return String(buffer); } @@ -190,6 +242,10 @@ class EmonADS1X15Sensor : public EmonSensor { protected: + //---------------------------------------------------------------------- + // Protected + //---------------------------------------------------------------------- + unsigned char getChannel(unsigned char port) { unsigned char count = 0; unsigned char bit = 1; @@ -206,6 +262,7 @@ class EmonADS1X15Sensor : public EmonSensor { void warmup() { for (unsigned char port=0; port<_ports; port++) { unsigned char channel = getChannel(port); + _pivot[channel] = _adc_counts >> 1; getCurrent(channel); } } @@ -218,7 +275,7 @@ class EmonADS1X15Sensor : public EmonSensor { // Start with default values uint16_t config = 0; - config |= ADS1X15_REG_CONFIG_PGA_4_096V; // Set PGA/voltage range (0x0200) + config |= _gain; // Set PGA/voltage range (0x0200) config |= ADS1X15_REG_CONFIG_DR_MASK; // Always at max speed (0x00E0) //config |= ADS1X15_REG_CONFIG_CMODE_TRAD; // Traditional comparator (default val) (0x0000) //config |= ADS1X15_REG_CONFIG_CPOL_ACTVLOW; // Alert/Rdy active low (default val) (0x0000) @@ -298,7 +355,7 @@ class EmonADS1X15Sensor : public EmonSensor { value |= Wire.read(); #endif - if (!_is_ads1115) value >>= ADS1015_BIT_SHIFT; + if (_type = ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT; delayMicroseconds(500); @@ -306,9 +363,10 @@ class EmonADS1X15Sensor : public EmonSensor { } - bool _is_ads1115 = true; unsigned char _address; - unsigned char _mask; + unsigned char _type = ADS1X15_CHIP_ADS1115; + unsigned char _mask = 0x0F; + unsigned int _gain = ADS1X15_REG_CONFIG_PGA_4_096V; unsigned char _ports; double _pivot[ADS1X15_CHANNELS] = {0}; double _current[ADS1X15_CHANNELS] = {0}; diff --git a/code/espurna/sensors/EmonAnalogSensor.h b/code/espurna/sensors/EmonAnalogSensor.h index 4da34426..4c053e6b 100644 --- a/code/espurna/sensors/EmonAnalogSensor.h +++ b/code/espurna/sensors/EmonAnalogSensor.h @@ -9,20 +9,37 @@ #include "BaseSensor.h" #include "EmonSensor.h" +#define INTERNAL_ADC_RESOLUTION 10 + class EmonAnalogSensor : public EmonSensor { public: - EmonAnalogSensor(unsigned char gpio, double voltage, unsigned char bits, double ref, double ratio): EmonSensor(voltage, bits, ref, ratio) { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { - // Cache - _gpio = gpio; + // Just one channel _count = _magnitudes; - // Prepare GPIO - pinMode(gpio, INPUT); + // Bit depth + _resolution = INTERNAL_ADC_RESOLUTION; + + // Init analog PIN + pinMode(_gpio, INPUT); + + // Call the parent class method + EmonSensor::begin(); - // warmup + // warmup channel 0 (the only one) + _pivot = _adc_counts >> 1; read(_gpio, _pivot); } @@ -56,22 +73,26 @@ class EmonAnalogSensor : public EmonSensor { return MAGNITUDE_NONE; } - // Current value for slot # index - double value(unsigned char index) { + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() { - _error = SENSOR_ERROR_OK; + _current = read(0, _pivot); - // Cache the value - static unsigned long last = 0; - if ((last == 0) || (millis() - last > 1000)) { - _current = read(0, _pivot); - #if EMON_REPORT_ENERGY + #if EMON_REPORT_ENERGY + static unsigned long last = 0; + if (last > 0) { _energy += (_current * _voltage * (millis() - last) / 1000); - #endif + } last = millis(); - } + #endif + + } + + // Current value for slot # index + double value(unsigned char index) { + + _error = SENSOR_ERROR_OK; - // Report unsigned char i=0; #if EMON_REPORT_CURRENT if (index == i++) return _current; @@ -94,7 +115,7 @@ class EmonAnalogSensor : public EmonSensor { return analogRead(_gpio); } - unsigned char _gpio; + unsigned char _gpio = 0; double _pivot = 0; double _current; #if EMON_REPORT_ENERGY diff --git a/code/espurna/sensors/EmonSensor.h b/code/espurna/sensors/EmonSensor.h index 2a84f939..3a7caf25 100644 --- a/code/espurna/sensors/EmonSensor.h +++ b/code/espurna/sensors/EmonSensor.h @@ -14,12 +14,11 @@ class EmonSensor : public BaseSensor { public: - EmonSensor(double voltage, unsigned char bits, double ref, double ratio): BaseSensor() { - - // Cache - _voltage = voltage; - _adc_counts = 1 << bits; + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + EmonSensor(): BaseSensor() { #if EMON_REPORT_CURRENT ++_magnitudes; #endif @@ -29,12 +28,42 @@ class EmonSensor : public BaseSensor { #if EMON_REPORT_ENERGY ++_magnitudes; #endif + } + + void setVoltage(double voltage) { + _voltage = voltage; + } + + void setReference(double ref) { + _reference = ref; + } + + void setCurrentRatio(double ratio) { + _current_ratio = ratio; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + void begin() { + + // Resolution + _adc_counts = 1 << _resolution; // Calculate factor - _current_factor = ratio * ref / _adc_counts; + _current_factor = _current_ratio * _reference / _adc_counts; // Calculate multiplier - calculateMultiplier(); + unsigned int s = 1; + unsigned int i = 1; + unsigned int m = s * i; + while (m * _current_factor < 1) { + _multiplier = m; + i = (i == 1) ? 2 : (i == 2) ? 5 : 1; + if (i == 1) s *= 10; + m = s * i; + } #if EMON_DEBUG Serial.print("[EMON] Current ratio: "); Serial.println(ratio); @@ -48,19 +77,11 @@ class EmonSensor : public BaseSensor { protected: - virtual unsigned int readADC(unsigned char channel) {} + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- - void calculateMultiplier() { - unsigned int s = 1; - unsigned int i = 1; - unsigned int m = s * i; - while (m * _current_factor < 1) { - _multiplier = m; - i = (i == 1) ? 2 : (i == 2) ? 5 : 1; - if (i == 1) s *= 10; - m = s * i; - } - } + virtual unsigned int readADC(unsigned char channel) {} double read(unsigned char channel, double &pivot) { @@ -120,13 +141,19 @@ class EmonSensor : public BaseSensor { } - double _voltage; unsigned char _magnitudes = 0; - unsigned long _adc_counts; + unsigned long _samples = EMON_MAX_SAMPLES; + unsigned int _multiplier = 1; + unsigned char _resolution = 10; + + double _voltage = EMON_MAINS_VOLTAGE; + double _reference = EMON_REFERENCE_VOLTAGE; + double _current_ratio = EMON_CURRENT_RATIO; + + unsigned long _adc_counts; double _current_factor; - unsigned long _samples = EMON_MAX_SAMPLES; }; diff --git a/code/espurna/sensors/EventSensor.h b/code/espurna/sensors/EventSensor.h index 9defb28c..61aef1e9 100644 --- a/code/espurna/sensors/EventSensor.h +++ b/code/espurna/sensors/EventSensor.h @@ -12,6 +12,27 @@ class EventSensor : public BaseSensor { public: + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + EventSensor(): BaseSensor() { + _count = 1; + } + + void setGPIO(unsigned char gpio, int mode = INPUT) { + _gpio = gpio; + pinMode(_gpio, mode); + } + + void setDebounceTime(unsigned long debounce) { + _debounce = debounce; + } + + // --------------------------------------------------------------------- + // Sensors API + // --------------------------------------------------------------------- + void InterruptHandler() { static unsigned long last = 0; if (millis() - last > _debounce) { @@ -20,13 +41,6 @@ class EventSensor : public BaseSensor { } } - EventSensor(unsigned char gpio, int pin_mode, unsigned long debounce): BaseSensor() { - _gpio = gpio; - _count = 1; - _debounce = debounce; - pinMode(_gpio, pin_mode); - } - // Descriptive name of the sensor String name() { char buffer[20]; @@ -62,6 +76,10 @@ class EventSensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + volatile unsigned long _events = 0; unsigned long _debounce = 0; unsigned char _gpio; diff --git a/code/espurna/sensors/MHZ19Sensor.h b/code/espurna/sensors/MHZ19Sensor.h index a4fa6cc4..5df94507 100644 --- a/code/espurna/sensors/MHZ19Sensor.h +++ b/code/espurna/sensors/MHZ19Sensor.h @@ -25,15 +25,29 @@ class MHZ19Sensor : public BaseSensor { public: - MHZ19Sensor(int pin_rx = MHZ19_RX_PIN, int pin_tx = MHZ19_TX_PIN): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Cache + MHZ19Sensor(): BaseSensor() { + _count = 1; + } + + void setGPIO(unsigned char pin_rx, unsigned char pin_tx) { _pin_rx = pin_rx; _pin_tx = pin_tx; - _count = 1; + } - // Init - _serial = new SoftwareSerial(pin_rx, pin_tx, false, 256); + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + if (_serial) delete _serial; + + _serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 256); _serial->begin(9600); calibrateAuto(false); @@ -92,6 +106,10 @@ class MHZ19Sensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + void _write(unsigned char * command) { _serial->write(command, MHZ19_REQUEST_LEN); _serial->write(_checksum(command)); diff --git a/code/espurna/sensors/PMSX003Sensor.h b/code/espurna/sensors/PMSX003Sensor.h index ca5a9707..be8ccaac 100644 --- a/code/espurna/sensors/PMSX003Sensor.h +++ b/code/espurna/sensors/PMSX003Sensor.h @@ -16,15 +16,36 @@ class PMSX003Sensor : public BaseSensor { public: - PMSX003Sensor(int pin_rx = PMS_RX_PIN, int pin_tx = PMS_TX_PIN): BaseSensor() { - _pmsSerial = new SoftwareSerial(pin_rx, pin_tx, false, 256); - _pmsSerial->begin(9600); - _pms = new PMS(* _pmsSerial); - _pms->passiveMode(); + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + PMSX003Sensor(): BaseSensor() { + _count = 3; + } + + void setGPIO(unsigned char pin_rx, unsigned char pin_tx) { _pin_rx = pin_rx; _pin_tx = pin_tx; - _count = 3; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + if (_serial) delete _serial; + if (_pms) delete _pms; + + _serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 256); + _serial->begin(9600); + _pms = new PMS(* _serial); + _pms->passiveMode(); + _startTime = millis(); + } // Descriptive name of the sensor @@ -96,7 +117,7 @@ class PMSX003Sensor : public BaseSensor { unsigned int _pin_rx; unsigned int _pin_tx; unsigned long _startTime; - SoftwareSerial * _pmsSerial; + SoftwareSerial * _serial; PMS * _pms; PMS::DATA _data; diff --git a/code/espurna/sensors/SI7021Sensor.h b/code/espurna/sensors/SI7021Sensor.h index 050d1e03..5062fcef 100644 --- a/code/espurna/sensors/SI7021Sensor.h +++ b/code/espurna/sensors/SI7021Sensor.h @@ -27,10 +27,30 @@ class SI7021Sensor : public BaseSensor { public: - SI7021Sensor(unsigned char address = 0x40): BaseSensor() { + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- - // Asume I2C already started + void setAddress(unsigned char address) { _address = address; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + // Discover + if (_address == 0) { + unsigned char addresses[] = {0x40}; + _address = i2cFindFirst(1, addresses); + } + if (_address == 0) { + _error = SENSOR_ERROR_UNKNOWN_ID; + return; + } // Check device #if I2C_USE_BRZO @@ -102,6 +122,10 @@ class SI7021Sensor : public BaseSensor { protected: + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + unsigned int read(uint8_t command) { unsigned char bytes = (command == 0xE0) ? 2 : 3; @@ -139,10 +163,6 @@ class SI7021Sensor : public BaseSensor { } - unsigned char chip() { - return _chip; - } - String chipAsString() { if (_chip == SI7021_CHIP_SI7021) return String("SI7021"); if (_chip == SI7021_CHIP_HTU21D) return String("HTU21D"); @@ -151,6 +171,5 @@ class SI7021Sensor : public BaseSensor { unsigned char _address; unsigned char _chip; - bool _found = false; };