diff --git a/code/espurna/sensor.cpp b/code/espurna/sensor.cpp index 01ff8135..da4df2d6 100644 --- a/code/espurna/sensor.cpp +++ b/code/espurna/sensor.cpp @@ -2935,7 +2935,8 @@ void _sensorLoad() { PulseMeterSensor * sensor = new PulseMeterSensor(); sensor->setGPIO(PULSEMETER_PIN); sensor->setInterruptMode(PULSEMETER_INTERRUPT_ON); - sensor->setDebounceTime(PULSEMETER_DEBOUNCE); + sensor->setDebounceTime( + PulseMeterSensor::TimeSource::duration{PULSEMETER_DEBOUNCE}); _sensors.push_back(sensor); } #endif diff --git a/code/espurna/sensors/PulseMeterSensor.h b/code/espurna/sensors/PulseMeterSensor.h index 1431662b..d5e32c22 100644 --- a/code/espurna/sensors/PulseMeterSensor.h +++ b/code/espurna/sensors/PulseMeterSensor.h @@ -14,6 +14,8 @@ class PulseMeterSensor : public BaseEmonSensor { public: + using TimeSource = espurna::time::CpuClock; + // --------------------------------------------------------------------- // Public // --------------------------------------------------------------------- @@ -23,11 +25,9 @@ class PulseMeterSensor : public BaseEmonSensor { MAGNITUDE_ENERGY }; - PulseMeterSensor() { - _sensor_id = SENSOR_PULSEMETER_ID; - _count = std::size(Magnitudes); - findAndAddEnergy(Magnitudes); - } + PulseMeterSensor() : + BaseEmonSensor(Magnitudes) + {} // --------------------------------------------------------------------- @@ -41,21 +41,22 @@ class PulseMeterSensor : public BaseEmonSensor { _interrupt_mode = interrupt_mode; } - void setDebounceTime(unsigned long debounce) { - _interrupt_debounce = debounce; + template + void setDebounceTime(T debounce) { + _interrupt_debounce = std::chrono::duration_cast(debounce); } // --------------------------------------------------------------------- - unsigned char getGPIO() { + unsigned char getGPIO() const { return _pin.pin(); } - unsigned char getInterruptMode() { + unsigned char getInterruptMode() const { return _interrupt_mode; } - unsigned long getDebounceTime() { + TimeSource::duration getDebounceTime() const { return _interrupt_debounce; } @@ -63,45 +64,50 @@ class PulseMeterSensor : public BaseEmonSensor { // Sensors API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_PULSEMETER_ID; + } + + unsigned char count() const override { + return std::size(Magnitudes); + } + // Initialization method, must be idempotent - // Defined outside the class body - void begin() { + void begin() override { + _previous_time = TimeSource::now(); _enableInterrupts(); _ready = true; } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[24]; snprintf_P(buffer, sizeof(buffer), PSTR("PulseMeter @ GPIO(%hhu)"), _pin.pin()); return String(buffer); } - // Descriptive name of the slot # index - String description(unsigned char index) { - return description(); - }; - // Address of the sensor (it could be the GPIO or I2C address) - String address(unsigned char index) { + String address(unsigned char) const override { return String(_pin); } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { - unsigned long lapse = millis() - _previous_time; - _previous_time = millis(); + void pre() override { + const auto now = TimeSource::now(); + const auto elapsed = now - _previous_time; + _previous_time = now; - auto reading = *(reinterpret_cast(&_pulses)); + const auto reading = *(reinterpret_cast(&_pulses)); unsigned long pulses = reading - _previous_pulses; _previous_pulses = reading; sensor::Ws delta = 1000.0 * 3600.0 * static_cast(pulses) / _energy_ratio; _energy[0] += delta; - if (lapse > 0) { - _active = 1000.0 * delta.value / lapse; + if (elapsed.count()) { + const auto milliseconds = std::chrono::duration_cast(elapsed).count(); + _active = 1000.0 * delta.value / milliseconds; } } @@ -129,7 +135,7 @@ class PulseMeterSensor : public BaseEmonSensor { } // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index < std::size(Magnitudes)) { return Magnitudes[index].type; } @@ -138,7 +144,7 @@ class PulseMeterSensor : public BaseEmonSensor { } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _active; if (index == 1) return _energy[0].asDouble(); return 0; @@ -146,8 +152,9 @@ class PulseMeterSensor : public BaseEmonSensor { // Handle interrupt calls void IRAM_ATTR interrupt() { - if (millis() - _interrupt_last > _interrupt_debounce) { - _interrupt_last = millis(); + const auto now = TimeSource::now(); + if (now - _interrupt_last > _interrupt_debounce) { + _interrupt_last = now; ++_pulses; } } @@ -156,13 +163,14 @@ class PulseMeterSensor : public BaseEmonSensor { instance->interrupt(); } - protected: + private: // --------------------------------------------------------------------- // Interrupt management // --------------------------------------------------------------------- void _enableInterrupts() { + _interrupt_last = TimeSource::now(); _pin.attach(this, handleInterrupt, _interrupt_mode); } @@ -176,12 +184,14 @@ class PulseMeterSensor : public BaseEmonSensor { unsigned long _pulses = 0; unsigned long _previous_pulses = 0; - unsigned long _previous_time = 0; + + TimeSource::time_point _interrupt_last; + TimeSource::duration _interrupt_debounce; + + TimeSource::time_point _previous_time; InterruptablePin _pin; int _interrupt_mode = FALLING; - unsigned long _interrupt_last = 0; - unsigned long _interrupt_debounce = PULSEMETER_DEBOUNCE; }; #if __cplusplus < 201703L