diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 9a925998..28824ee8 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -7,6 +7,7 @@ #define SENSOR_READ_INTERVAL 6 // Read data from sensors every 6 seconds #define SENSOR_READ_MIN_INTERVAL 6 // Minimum read interval #define SENSOR_READ_MAX_INTERVAL 3600 // Maximum read interval +#define SENSOR_INIT_INTERVAL 10000 // Try to re-init non-ready sensors every 10s #define SENSOR_REPORT_EVERY 10 // Report every this many readings #define SENSOR_REPORT_MIN_EVERY 1 // Minimum every value diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 38d17995..0da53af3 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -28,6 +28,7 @@ typedef struct { std::vector _sensors; std::vector _magnitudes; +bool _sensors_ready = false; unsigned char _counts[MAGNITUDE_MAX]; bool _sensor_realtime = API_REAL_TIME_VALUES; @@ -254,7 +255,7 @@ void _sensorPost() { // Sensor initialization // ----------------------------------------------------------------------------- -void _sensorInit() { +void _sensorLoad() { /* @@ -461,15 +462,19 @@ void _sensorInit() { } void _sensorCallback(unsigned char i, unsigned char type, const char * payload) { - DEBUG_MSG_P(PSTR("[SENSOR] Sensor #%u callback, type %u, payload: '%s'\n"), i, type, payload); - } -void _sensorConfigure() { +void _sensorInit() { + + _sensors_ready = true; for (unsigned char i=0; i<_sensors.size(); i++) { + // Do not process and already initialized sensor + if (_sensors[i]->ready()) continue; + DEBUG_MSG_P(PSTR("[SENSOR] Initializing %s\n"), _sensors[i]->description().c_str()); + #if EMON_ANALOG_SUPPORT if (_sensors[i]->getID() == SENSOR_EMON_ANALOG_ID) { @@ -499,6 +504,14 @@ void _sensorConfigure() { // Force sensor to reload config _sensors[i]->begin(); + if (!_sensors[i]->ready()) { + if (_sensors[i]->error() != 0) DEBUG_MSG_P(PSTR("[SENSOR] -> ERROR %d\n"), _sensors[i]->error()); + _sensors_ready = false; + continue; + } + + // Initialize magnitudes + _magnitudesInit(_sensors[i]); // Hook callback _sensors[i]->onEvent([i](unsigned char type, const char * payload) { @@ -550,6 +563,44 @@ void _sensorConfigure() { } +} + +void _magnitudesInit(BaseSensor * sensor) { + + + for (unsigned char k=0; kcount(); k++) { + + unsigned char type = sensor->type(k); + + sensor_magnitude_t new_magnitude; + new_magnitude.sensor = sensor; + new_magnitude.local = k; + new_magnitude.type = type; + new_magnitude.global = _counts[type]; + new_magnitude.current = 0; + new_magnitude.filtered = 0; + new_magnitude.reported = 0; + new_magnitude.min_change = 0; + if (type == MAGNITUDE_DIGITAL) { + new_magnitude.filter = new MaxFilter(); + } else if (type == MAGNITUDE_EVENTS) { + new_magnitude.filter = new MovingAverageFilter(); + } else { + new_magnitude.filter = new MedianFilter(); + } + new_magnitude.filter->resize(_sensor_report_every); + _magnitudes.push_back(new_magnitude); + + DEBUG_MSG_P(PSTR("[SENSOR] -> %s:%d\n"), magnitudeTopic(type).c_str(), _counts[type]); + + _counts[type] = _counts[type] + 1; + + } + +} + +void _sensorConfigure() { + // General sensor settings _sensor_read_interval = 1000 * constrain(getSetting("snsRead", SENSOR_READ_INTERVAL).toInt(), SENSOR_READ_MIN_INTERVAL, SENSOR_READ_MAX_INTERVAL); _sensor_report_every = constrain(getSetting("snsReport", SENSOR_REPORT_EVERY).toInt(), SENSOR_REPORT_MIN_EVERY, SENSOR_REPORT_MAX_EVERY); @@ -573,48 +624,6 @@ void _sensorConfigure() { } -void _magnitudesInit() { - - for (unsigned char i=0; i<_sensors.size(); i++) { - - BaseSensor * sensor = _sensors[i]; - - DEBUG_MSG_P(PSTR("[SENSOR] %s\n"), sensor->description().c_str()); - if (sensor->error() != 0) DEBUG_MSG_P(PSTR("[SENSOR] -> ERROR %d\n"), sensor->error()); - - for (unsigned char k=0; kcount(); k++) { - - unsigned char type = sensor->type(k); - - sensor_magnitude_t new_magnitude; - new_magnitude.sensor = sensor; - new_magnitude.local = k; - new_magnitude.type = type; - new_magnitude.global = _counts[type]; - new_magnitude.current = 0; - new_magnitude.filtered = 0; - new_magnitude.reported = 0; - new_magnitude.min_change = 0; - if (type == MAGNITUDE_DIGITAL) { - new_magnitude.filter = new MaxFilter(); - } else if (type == MAGNITUDE_EVENTS) { - new_magnitude.filter = new MovingAverageFilter(); - } else { - new_magnitude.filter = new MedianFilter(); - } - new_magnitude.filter->resize(_sensor_report_every); - _magnitudes.push_back(new_magnitude); - - DEBUG_MSG_P(PSTR("[SENSOR] -> %s:%d\n"), magnitudeTopic(type).c_str(), _counts[type]); - - _counts[type] = _counts[type] + 1; - - } - - } - -} - // ----------------------------------------------------------------------------- // Public // ----------------------------------------------------------------------------- @@ -694,14 +703,12 @@ String magnitudeUnits(unsigned char type) { void sensorSetup() { // Load sensors + _sensorLoad(); _sensorInit(); // Configure stored values _sensorConfigure(); - // Load magnitudes - _magnitudesInit(); - #if WEB_SUPPORT // Websockets @@ -725,8 +732,14 @@ void sensorSetup() { void sensorLoop() { - static unsigned long last_update = 0; - static unsigned long report_count = 0; + // Check if we still have uninitialized sensors + static unsigned long last_init = 0; + if (!_sensors_ready) { + if (millis() - last_init > SENSOR_INIT_INTERVAL) { + last_init = millis(); + _sensorInit(); + } + } if (_magnitudes.size() == 0) return; @@ -734,6 +747,8 @@ void sensorLoop() { _sensorTick(); // Check if we should read new data + static unsigned long last_update = 0; + static unsigned long report_count = 0; if (millis() - last_update > _sensor_read_interval) { last_update = millis(); diff --git a/code/espurna/sensors/AnalogSensor.h b/code/espurna/sensors/AnalogSensor.h index 1502a09c..920538c9 100644 --- a/code/espurna/sensors/AnalogSensor.h +++ b/code/espurna/sensors/AnalogSensor.h @@ -30,6 +30,7 @@ class AnalogSensor : public BaseSensor { // Initialization method, must be idempotent void begin() { pinMode(0, INPUT); + _ready = true; } // Descriptive name of the sensor diff --git a/code/espurna/sensors/BH1750Sensor.h b/code/espurna/sensors/BH1750Sensor.h index c29ab2de..9cc2b87d 100644 --- a/code/espurna/sensors/BH1750Sensor.h +++ b/code/espurna/sensors/BH1750Sensor.h @@ -55,7 +55,6 @@ class BH1750Sensor : public I2CSensor { void begin() { if (!_dirty) return; - _dirty = false; // I2C auto-discover unsigned char addresses[] = {0x23, 0x5C}; @@ -64,6 +63,8 @@ class BH1750Sensor : public I2CSensor { // Run configuration on next update _run_configure = true; + _ready = true; + _dirty = false; } diff --git a/code/espurna/sensors/BMX280Sensor.h b/code/espurna/sensors/BMX280Sensor.h index 26fe4cac..9782c95e 100644 --- a/code/espurna/sensors/BMX280Sensor.h +++ b/code/espurna/sensors/BMX280Sensor.h @@ -67,14 +67,9 @@ class BMX280Sensor : public I2CSensor { // Initialization method, must be idempotent void begin() { - if (!_dirty) return; - _dirty = false; - _chip = 0; - - // Init _init(); - + _dirty = !_ready; } // Descriptive name of the sensor @@ -190,6 +185,9 @@ class BMX280Sensor : public I2CSensor { // Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up delay(10); + // No chip ID by default + _chip = 0; + // I2C auto-discover _address = _begin_i2c(_address, sizeof(BMX280Sensor::addresses), BMX280Sensor::addresses); if (_address == 0) return; @@ -242,6 +240,7 @@ class BMX280Sensor : public I2CSensor { _measurement_delay = _measurementTime(); _run_init = false; + _ready = true; } diff --git a/code/espurna/sensors/BaseSensor.h b/code/espurna/sensors/BaseSensor.h index fdcbe528..12ab5d09 100644 --- a/code/espurna/sensors/BaseSensor.h +++ b/code/espurna/sensors/BaseSensor.h @@ -70,8 +70,11 @@ class BaseSensor { // Sensor ID unsigned char getID() { return _sensor_id; }; - // Return sensor status (true for ready) - bool status() { return _error == 0; } + // Return status (true if no errors) + bool status() { return 0 == _error; } + + // Return ready status (true for ready) + bool ready() { return _ready; } // Return sensor last internal error int error() { return _error; } @@ -89,6 +92,7 @@ class BaseSensor { int _error = 0; bool _dirty = true; unsigned char _count = 0; + bool _ready = false; }; diff --git a/code/espurna/sensors/DHTSensor.h b/code/espurna/sensors/DHTSensor.h index 1cb3f3e1..fe590b84 100644 --- a/code/espurna/sensors/DHTSensor.h +++ b/code/espurna/sensors/DHTSensor.h @@ -75,6 +75,7 @@ class DHTSensor : public BaseSensor { _previous = _gpio; _count = 2; + _ready = true; } diff --git a/code/espurna/sensors/DallasSensor.h b/code/espurna/sensors/DallasSensor.h index 03bf8c8b..e5dbba11 100644 --- a/code/espurna/sensors/DallasSensor.h +++ b/code/espurna/sensors/DallasSensor.h @@ -64,7 +64,6 @@ class DallasSensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; // Manage GPIO lock if (_previous != GPIO_NONE) gpioReleaseLock(_previous); @@ -93,6 +92,8 @@ class DallasSensor : public BaseSensor { } else { _previous = _gpio; } + _ready = true; + _dirty = false; } diff --git a/code/espurna/sensors/DigitalSensor.h b/code/espurna/sensors/DigitalSensor.h index a0e725ae..fc1ca796 100644 --- a/code/espurna/sensors/DigitalSensor.h +++ b/code/espurna/sensors/DigitalSensor.h @@ -58,6 +58,7 @@ class DigitalSensor : public BaseSensor { // Initialization method, must be idempotent void begin() { pinMode(_gpio, _mode); + _ready = true; } // Descriptive name of the sensor diff --git a/code/espurna/sensors/ECH1560Sensor.h b/code/espurna/sensors/ECH1560Sensor.h index 8ffc07a4..0fc9dc54 100644 --- a/code/espurna/sensors/ECH1560Sensor.h +++ b/code/espurna/sensors/ECH1560Sensor.h @@ -67,12 +67,14 @@ class ECH1560Sensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; pinMode(_clk, INPUT); pinMode(_miso, INPUT); _enableInterrupts(true); + _dirty = false; + _ready = true; + } // Loop-like method, call it in your main loop diff --git a/code/espurna/sensors/EmonADS1X15Sensor.h b/code/espurna/sensors/EmonADS1X15Sensor.h index 36c9b045..26f18c40 100644 --- a/code/espurna/sensors/EmonADS1X15Sensor.h +++ b/code/espurna/sensors/EmonADS1X15Sensor.h @@ -147,7 +147,6 @@ class EmonADS1X15Sensor : public EmonSensor { void begin() { if (!_dirty) return; - _dirty = false; // Discover unsigned char addresses[] = {0x48, 0x49, 0x4A, 0x4B}; diff --git a/code/espurna/sensors/EmonSensor.h b/code/espurna/sensors/EmonSensor.h index e82e7b05..dc2ea7a2 100644 --- a/code/espurna/sensors/EmonSensor.h +++ b/code/espurna/sensors/EmonSensor.h @@ -109,6 +109,10 @@ class EmonSensor : public I2CSensor { } #endif + _ready = true; + _dirty = false; + + } protected: diff --git a/code/espurna/sensors/EventSensor.h b/code/espurna/sensors/EventSensor.h index 70288a1f..d46fc063 100644 --- a/code/espurna/sensors/EventSensor.h +++ b/code/espurna/sensors/EventSensor.h @@ -72,6 +72,7 @@ class EventSensor : public BaseSensor { void begin() { pinMode(_gpio, _mode); _enableInterrupts(true); + _ready = true; } // Descriptive name of the sensor diff --git a/code/espurna/sensors/HLW8012Sensor.h b/code/espurna/sensors/HLW8012Sensor.h index 9a43c938..2e030ed1 100644 --- a/code/espurna/sensors/HLW8012Sensor.h +++ b/code/espurna/sensors/HLW8012Sensor.h @@ -153,6 +153,8 @@ class HLW8012Sensor : public BaseSensor { }); #endif + _ready = true; + } // Descriptive name of the sensor diff --git a/code/espurna/sensors/MHZ19Sensor.h b/code/espurna/sensors/MHZ19Sensor.h index 4826069a..105adf22 100644 --- a/code/espurna/sensors/MHZ19Sensor.h +++ b/code/espurna/sensors/MHZ19Sensor.h @@ -72,7 +72,6 @@ class MHZ19Sensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; if (_serial) delete _serial; @@ -81,6 +80,9 @@ class MHZ19Sensor : public BaseSensor { _serial->begin(9600); calibrateAuto(false); + _ready = true; + _dirty = false; + } // Descriptive name of the sensor diff --git a/code/espurna/sensors/PMSX003Sensor.h b/code/espurna/sensors/PMSX003Sensor.h index 788a2b06..95e5933a 100644 --- a/code/espurna/sensors/PMSX003Sensor.h +++ b/code/espurna/sensors/PMSX003Sensor.h @@ -62,7 +62,6 @@ class PMSX003Sensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; if (_serial) delete _serial; if (_pms) delete _pms; @@ -74,6 +73,8 @@ class PMSX003Sensor : public BaseSensor { _pms->passiveMode(); _startTime = millis(); + _ready = true; + _dirty = false; } diff --git a/code/espurna/sensors/PZEM004TSensor.h b/code/espurna/sensors/PZEM004TSensor.h index 9e2cea38..2adc71e9 100644 --- a/code/espurna/sensors/PZEM004TSensor.h +++ b/code/espurna/sensors/PZEM004TSensor.h @@ -70,7 +70,6 @@ class PZEM004TSensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; if (_pzem) delete _pzem; if (_serial == NULL) { @@ -80,6 +79,9 @@ class PZEM004TSensor : public BaseSensor { } _pzem->setAddress(_ip); + _ready = true; + _dirty = false; + } // Descriptive name of the sensor diff --git a/code/espurna/sensors/SHT3XI2CSensor.h b/code/espurna/sensors/SHT3XI2CSensor.h index ded19529..b3f9e8ca 100644 --- a/code/espurna/sensors/SHT3XI2CSensor.h +++ b/code/espurna/sensors/SHT3XI2CSensor.h @@ -31,13 +31,15 @@ class SHT3XI2CSensor : public I2CSensor { void begin() { if (!_dirty) return; - _dirty = false; // I2C auto-discover unsigned char addresses[] = {0x45}; _address = _begin_i2c(_address, sizeof(addresses), addresses); if (_address == 0) return; + _ready = true; + _dirty = false; + } // Descriptive name of the sensor diff --git a/code/espurna/sensors/SI7021Sensor.h b/code/espurna/sensors/SI7021Sensor.h index 86192b01..677d8b2d 100644 --- a/code/espurna/sensors/SI7021Sensor.h +++ b/code/espurna/sensors/SI7021Sensor.h @@ -41,18 +41,9 @@ class SI7021Sensor : public I2CSensor { // Initialization method, must be idempotent void begin() { - if (!_dirty) return; - _dirty = false; - - // I2C auto-discover - unsigned char addresses[] = {0x40}; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; - - // Initialize sensor _init(); - + _dirty = !_ready; } // Descriptive name of the sensor @@ -116,6 +107,11 @@ class SI7021Sensor : public I2CSensor { void _init() { + // I2C auto-discover + unsigned char addresses[] = {0x40}; + _address = _begin_i2c(_address, sizeof(addresses), addresses); + if (_address == 0) return; + // Check device i2c_write_uint8(_address, 0xFC, 0xC9); _chip = i2c_read_uint8(_address); @@ -136,6 +132,8 @@ class SI7021Sensor : public I2CSensor { _count = 2; } + _ready = true; + } unsigned int _read(uint8_t command) { diff --git a/code/espurna/sensors/V9261FSensor.h b/code/espurna/sensors/V9261FSensor.h index 31b57b62..c80ab44b 100644 --- a/code/espurna/sensors/V9261FSensor.h +++ b/code/espurna/sensors/V9261FSensor.h @@ -61,7 +61,6 @@ class V9261FSensor : public BaseSensor { void begin() { if (!_dirty) return; - _dirty = false; if (_serial) delete _serial; @@ -69,6 +68,9 @@ class V9261FSensor : public BaseSensor { _serial->enableIntTx(false); _serial->begin(V9261F_BAUDRATE); + _ready = true; + _dirty = false; + } // Descriptive name of the sensor