From ffa9f3f90a8a9524c320355df04da996c7b9dba7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20K=C3=A4ppler?= <michael_kaeppler@web.de>
Date: Sat, 17 Apr 2021 22:46:05 +0200
Subject: [PATCH] co2_sensor: introduce states

* define sensor states
* log every change of state to serial

There is no new functionality added yet.
---
 ampel-firmware/co2_sensor.cpp | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/ampel-firmware/co2_sensor.cpp b/ampel-firmware/co2_sensor.cpp
index 5dff676..50930c6 100644
--- a/ampel-firmware/co2_sensor.cpp
+++ b/ampel-firmware/co2_sensor.cpp
@@ -25,6 +25,29 @@ namespace sensor {
   char timestamp[23];
   int16_t stable_measurements = 0;
   uint32_t waiting_color = color::blue;
+
+  /**
+   * Define sensor states
+   * INITIAL -> initial state
+   * BOOTUP -> state after initializing the sensor, i.e. after scd.begin()
+   * READY -> sensor does output valid information (> 0 ppm) and no other condition takes place
+   * (NOTE: This state is currently unused)
+   * NEEDSCALIBRATION -> sensor measurements are too low (< 250 ppm)
+   * PREPARECALIBRATION -> forced calibration was initiated, waiting for stable measurements
+   * CALIBRATION -> the sensor does calibrate itself
+   */
+  enum state {INITIAL, BOOTUP, READY, NEEDSCALIBRATION, PREPARECALIBRATION, CALIBRATION};
+  const char *state_names[] = {
+    "INITIAL",
+    "BOOTUP",
+    "READY",
+    "NEEDSCALIBRATION",
+    "PREPARECALIBRATION",
+    "CALIBRATION"
+  };
+  state current_state = INITIAL;
+  void switchState(state);
+
   bool should_calibrate = false;
 
   void initialize() {
@@ -49,6 +72,8 @@ namespace sensor {
       ESP.restart();
     }
 
+    switchState(BOOTUP);
+
     // SCD30 has its own timer.
     //NOTE: The timer seems to be inaccurate, though, possibly depending on voltage. Should it be offset?
     Serial.println();
@@ -116,9 +141,11 @@ namespace sensor {
     Serial.println(F("Waiting until the measurements are stable for at least 2 minutes."));
     Serial.println(F("It could take a very long time."));
     should_calibrate = true;
+    switchState(PREPARECALIBRATION);
   }
 
   void calibrateAndRestart() {
+    switchState(CALIBRATION);
     Serial.print(F("Calibrating SCD30 now..."));
     scd30.setAltitudeCompensation(config::altitude_above_sea_level);
     scd30.setForcedRecalibrationFactor(config::co2_calibration_level);
@@ -137,10 +164,20 @@ namespace sensor {
     Serial.println(humidity, 1);
   }
 
+  void switchState(state new_state) {
+    if (new_state == current_state) return;
+    Serial.print(F("Changing sensor state: "));
+    Serial.print(state_names[current_state]);
+    Serial.print(" -> ");
+    Serial.println(state_names[new_state]);
+    current_state = new_state;
+  }
+
   void displayCO2OnLedRing() {
     if (co2 < 250) {
       // Sensor should be calibrated.
       led_effects::showWaitingLED(color::magenta);
+      switchState(NEEDSCALIBRATION);
       return;
     }
     /**
@@ -174,8 +211,11 @@ namespace sensor {
     //NOTE: Data is available, but it's sometimes erroneous: the sensor outputs zero ppm but non-zero temperature and non-zero humidity.
     if (co2 <= 0) {
       // No measurement yet. Waiting.
+      switchState(BOOTUP);
       led_effects::showWaitingLED(color::blue);
       return false;
+    } else if (current_state != PREPARECALIBRATION) {
+      switchState(READY);
     }
 
     /**
-- 
GitLab