Browse Source

Check init status of sensors and re-init if they fail on boot (#353)

rfm69
Xose Pérez 6 years ago
parent
commit
26a087dd7c
20 changed files with 117 additions and 78 deletions
  1. +1
    -0
      code/espurna/config/sensors.h
  2. +66
    -51
      code/espurna/sensor.ino
  3. +1
    -0
      code/espurna/sensors/AnalogSensor.h
  4. +2
    -1
      code/espurna/sensors/BH1750Sensor.h
  5. +5
    -6
      code/espurna/sensors/BMX280Sensor.h
  6. +6
    -2
      code/espurna/sensors/BaseSensor.h
  7. +1
    -0
      code/espurna/sensors/DHTSensor.h
  8. +2
    -1
      code/espurna/sensors/DallasSensor.h
  9. +1
    -0
      code/espurna/sensors/DigitalSensor.h
  10. +3
    -1
      code/espurna/sensors/ECH1560Sensor.h
  11. +0
    -1
      code/espurna/sensors/EmonADS1X15Sensor.h
  12. +4
    -0
      code/espurna/sensors/EmonSensor.h
  13. +1
    -0
      code/espurna/sensors/EventSensor.h
  14. +2
    -0
      code/espurna/sensors/HLW8012Sensor.h
  15. +3
    -1
      code/espurna/sensors/MHZ19Sensor.h
  16. +2
    -1
      code/espurna/sensors/PMSX003Sensor.h
  17. +3
    -1
      code/espurna/sensors/PZEM004TSensor.h
  18. +3
    -1
      code/espurna/sensors/SHT3XI2CSensor.h
  19. +8
    -10
      code/espurna/sensors/SI7021Sensor.h
  20. +3
    -1
      code/espurna/sensors/V9261FSensor.h

+ 1
- 0
code/espurna/config/sensors.h View File

@ -7,6 +7,7 @@
#define SENSOR_READ_INTERVAL 6 // Read data from sensors every 6 seconds #define SENSOR_READ_INTERVAL 6 // Read data from sensors every 6 seconds
#define SENSOR_READ_MIN_INTERVAL 6 // Minimum read interval #define SENSOR_READ_MIN_INTERVAL 6 // Minimum read interval
#define SENSOR_READ_MAX_INTERVAL 3600 // Maximum 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_EVERY 10 // Report every this many readings
#define SENSOR_REPORT_MIN_EVERY 1 // Minimum every value #define SENSOR_REPORT_MIN_EVERY 1 // Minimum every value


+ 66
- 51
code/espurna/sensor.ino View File

@ -28,6 +28,7 @@ typedef struct {
std::vector<BaseSensor *> _sensors; std::vector<BaseSensor *> _sensors;
std::vector<sensor_magnitude_t> _magnitudes; std::vector<sensor_magnitude_t> _magnitudes;
bool _sensors_ready = false;
unsigned char _counts[MAGNITUDE_MAX]; unsigned char _counts[MAGNITUDE_MAX];
bool _sensor_realtime = API_REAL_TIME_VALUES; bool _sensor_realtime = API_REAL_TIME_VALUES;
@ -254,7 +255,7 @@ void _sensorPost() {
// Sensor initialization // Sensor initialization
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void _sensorInit() {
void _sensorLoad() {
/* /*
@ -461,15 +462,19 @@ void _sensorInit() {
} }
void _sensorCallback(unsigned char i, unsigned char type, const char * payload) { 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); 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++) { 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 EMON_ANALOG_SUPPORT
if (_sensors[i]->getID() == SENSOR_EMON_ANALOG_ID) { if (_sensors[i]->getID() == SENSOR_EMON_ANALOG_ID) {
@ -499,6 +504,14 @@ void _sensorConfigure() {
// Force sensor to reload config // Force sensor to reload config
_sensors[i]->begin(); _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 // Hook callback
_sensors[i]->onEvent([i](unsigned char type, const char * payload) { _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; k<sensor->count(); 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 // General sensor settings
_sensor_read_interval = 1000 * constrain(getSetting("snsRead", SENSOR_READ_INTERVAL).toInt(), SENSOR_READ_MIN_INTERVAL, SENSOR_READ_MAX_INTERVAL); _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); _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; k<sensor->count(); 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 // Public
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -694,14 +703,12 @@ String magnitudeUnits(unsigned char type) {
void sensorSetup() { void sensorSetup() {
// Load sensors // Load sensors
_sensorLoad();
_sensorInit(); _sensorInit();
// Configure stored values // Configure stored values
_sensorConfigure(); _sensorConfigure();
// Load magnitudes
_magnitudesInit();
#if WEB_SUPPORT #if WEB_SUPPORT
// Websockets // Websockets
@ -725,8 +732,14 @@ void sensorSetup() {
void sensorLoop() { 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; if (_magnitudes.size() == 0) return;
@ -734,6 +747,8 @@ void sensorLoop() {
_sensorTick(); _sensorTick();
// Check if we should read new data // 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) { if (millis() - last_update > _sensor_read_interval) {
last_update = millis(); last_update = millis();


+ 1
- 0
code/espurna/sensors/AnalogSensor.h View File

@ -30,6 +30,7 @@ class AnalogSensor : public BaseSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
void begin() { void begin() {
pinMode(0, INPUT); pinMode(0, INPUT);
_ready = true;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 2
- 1
code/espurna/sensors/BH1750Sensor.h View File

@ -55,7 +55,6 @@ class BH1750Sensor : public I2CSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
// I2C auto-discover // I2C auto-discover
unsigned char addresses[] = {0x23, 0x5C}; unsigned char addresses[] = {0x23, 0x5C};
@ -64,6 +63,8 @@ class BH1750Sensor : public I2CSensor {
// Run configuration on next update // Run configuration on next update
_run_configure = true; _run_configure = true;
_ready = true;
_dirty = false;
} }


+ 5
- 6
code/espurna/sensors/BMX280Sensor.h View File

@ -67,14 +67,9 @@ class BMX280Sensor : public I2CSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
_chip = 0;
// Init
_init(); _init();
_dirty = !_ready;
} }
// Descriptive name of the sensor // 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 // Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up
delay(10); delay(10);
// No chip ID by default
_chip = 0;
// I2C auto-discover // I2C auto-discover
_address = _begin_i2c(_address, sizeof(BMX280Sensor::addresses), BMX280Sensor::addresses); _address = _begin_i2c(_address, sizeof(BMX280Sensor::addresses), BMX280Sensor::addresses);
if (_address == 0) return; if (_address == 0) return;
@ -242,6 +240,7 @@ class BMX280Sensor : public I2CSensor {
_measurement_delay = _measurementTime(); _measurement_delay = _measurementTime();
_run_init = false; _run_init = false;
_ready = true;
} }


+ 6
- 2
code/espurna/sensors/BaseSensor.h View File

@ -70,8 +70,11 @@ class BaseSensor {
// Sensor ID // Sensor ID
unsigned char getID() { return _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 // Return sensor last internal error
int error() { return _error; } int error() { return _error; }
@ -89,6 +92,7 @@ class BaseSensor {
int _error = 0; int _error = 0;
bool _dirty = true; bool _dirty = true;
unsigned char _count = 0; unsigned char _count = 0;
bool _ready = false;
}; };


+ 1
- 0
code/espurna/sensors/DHTSensor.h View File

@ -75,6 +75,7 @@ class DHTSensor : public BaseSensor {
_previous = _gpio; _previous = _gpio;
_count = 2; _count = 2;
_ready = true;
} }


+ 2
- 1
code/espurna/sensors/DallasSensor.h View File

@ -64,7 +64,6 @@ class DallasSensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
// Manage GPIO lock // Manage GPIO lock
if (_previous != GPIO_NONE) gpioReleaseLock(_previous); if (_previous != GPIO_NONE) gpioReleaseLock(_previous);
@ -93,6 +92,8 @@ class DallasSensor : public BaseSensor {
} else { } else {
_previous = _gpio; _previous = _gpio;
} }
_ready = true;
_dirty = false;
} }


+ 1
- 0
code/espurna/sensors/DigitalSensor.h View File

@ -58,6 +58,7 @@ class DigitalSensor : public BaseSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
void begin() { void begin() {
pinMode(_gpio, _mode); pinMode(_gpio, _mode);
_ready = true;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 3
- 1
code/espurna/sensors/ECH1560Sensor.h View File

@ -67,12 +67,14 @@ class ECH1560Sensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
pinMode(_clk, INPUT); pinMode(_clk, INPUT);
pinMode(_miso, INPUT); pinMode(_miso, INPUT);
_enableInterrupts(true); _enableInterrupts(true);
_dirty = false;
_ready = true;
} }
// Loop-like method, call it in your main loop // Loop-like method, call it in your main loop


+ 0
- 1
code/espurna/sensors/EmonADS1X15Sensor.h View File

@ -147,7 +147,6 @@ class EmonADS1X15Sensor : public EmonSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
// Discover // Discover
unsigned char addresses[] = {0x48, 0x49, 0x4A, 0x4B}; unsigned char addresses[] = {0x48, 0x49, 0x4A, 0x4B};


+ 4
- 0
code/espurna/sensors/EmonSensor.h View File

@ -109,6 +109,10 @@ class EmonSensor : public I2CSensor {
} }
#endif #endif
_ready = true;
_dirty = false;
} }
protected: protected:


+ 1
- 0
code/espurna/sensors/EventSensor.h View File

@ -72,6 +72,7 @@ class EventSensor : public BaseSensor {
void begin() { void begin() {
pinMode(_gpio, _mode); pinMode(_gpio, _mode);
_enableInterrupts(true); _enableInterrupts(true);
_ready = true;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 2
- 0
code/espurna/sensors/HLW8012Sensor.h View File

@ -153,6 +153,8 @@ class HLW8012Sensor : public BaseSensor {
}); });
#endif #endif
_ready = true;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 3
- 1
code/espurna/sensors/MHZ19Sensor.h View File

@ -72,7 +72,6 @@ class MHZ19Sensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
if (_serial) delete _serial; if (_serial) delete _serial;
@ -81,6 +80,9 @@ class MHZ19Sensor : public BaseSensor {
_serial->begin(9600); _serial->begin(9600);
calibrateAuto(false); calibrateAuto(false);
_ready = true;
_dirty = false;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 2
- 1
code/espurna/sensors/PMSX003Sensor.h View File

@ -62,7 +62,6 @@ class PMSX003Sensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
if (_serial) delete _serial; if (_serial) delete _serial;
if (_pms) delete _pms; if (_pms) delete _pms;
@ -74,6 +73,8 @@ class PMSX003Sensor : public BaseSensor {
_pms->passiveMode(); _pms->passiveMode();
_startTime = millis(); _startTime = millis();
_ready = true;
_dirty = false;
} }


+ 3
- 1
code/espurna/sensors/PZEM004TSensor.h View File

@ -70,7 +70,6 @@ class PZEM004TSensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
if (_pzem) delete _pzem; if (_pzem) delete _pzem;
if (_serial == NULL) { if (_serial == NULL) {
@ -80,6 +79,9 @@ class PZEM004TSensor : public BaseSensor {
} }
_pzem->setAddress(_ip); _pzem->setAddress(_ip);
_ready = true;
_dirty = false;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 3
- 1
code/espurna/sensors/SHT3XI2CSensor.h View File

@ -31,13 +31,15 @@ class SHT3XI2CSensor : public I2CSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
// I2C auto-discover // I2C auto-discover
unsigned char addresses[] = {0x45}; unsigned char addresses[] = {0x45};
_address = _begin_i2c(_address, sizeof(addresses), addresses); _address = _begin_i2c(_address, sizeof(addresses), addresses);
if (_address == 0) return; if (_address == 0) return;
_ready = true;
_dirty = false;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


+ 8
- 10
code/espurna/sensors/SI7021Sensor.h View File

@ -41,18 +41,9 @@ class SI7021Sensor : public I2CSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
void begin() { void begin() {
if (!_dirty) return; 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(); _init();
_dirty = !_ready;
} }
// Descriptive name of the sensor // Descriptive name of the sensor
@ -116,6 +107,11 @@ class SI7021Sensor : public I2CSensor {
void _init() { void _init() {
// I2C auto-discover
unsigned char addresses[] = {0x40};
_address = _begin_i2c(_address, sizeof(addresses), addresses);
if (_address == 0) return;
// Check device // Check device
i2c_write_uint8(_address, 0xFC, 0xC9); i2c_write_uint8(_address, 0xFC, 0xC9);
_chip = i2c_read_uint8(_address); _chip = i2c_read_uint8(_address);
@ -136,6 +132,8 @@ class SI7021Sensor : public I2CSensor {
_count = 2; _count = 2;
} }
_ready = true;
} }
unsigned int _read(uint8_t command) { unsigned int _read(uint8_t command) {


+ 3
- 1
code/espurna/sensors/V9261FSensor.h View File

@ -61,7 +61,6 @@ class V9261FSensor : public BaseSensor {
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
_dirty = false;
if (_serial) delete _serial; if (_serial) delete _serial;
@ -69,6 +68,9 @@ class V9261FSensor : public BaseSensor {
_serial->enableIntTx(false); _serial->enableIntTx(false);
_serial->begin(V9261F_BAUDRATE); _serial->begin(V9261F_BAUDRATE);
_ready = true;
_dirty = false;
} }
// Descriptive name of the sensor // Descriptive name of the sensor


Loading…
Cancel
Save