diff --git a/ampel-firmware/co2_sensor.cpp b/ampel-firmware/co2_sensor.cpp index a41162aff8c255ff501c6ba7d0bc018d0b885a48..946e09b8c2fc621b9a027a96ca44985b0720d4e0 100644 --- a/ampel-firmware/co2_sensor.cpp +++ b/ampel-firmware/co2_sensor.cpp @@ -24,7 +24,6 @@ namespace sensor { float humidity = 0; char timestamp[23]; int16_t stable_measurements = 0; - uint32_t waiting_color = color::blue; /** * Define sensor states @@ -36,13 +35,21 @@ namespace sensor { * PREPARECALIBRATION -> forced calibration was initiated, waiting for stable measurements * CALIBRATION -> the sensor does calibrate itself */ - enum state {INITIAL, BOOTUP, READY, NEEDSCALIBRATION, PREPARECALIBRATION, CALIBRATION}; + enum state { + INITIAL, + BOOTUP, + READY, + NEEDSCALIBRATION, + PREPARECALIBRATION_INSTABLE, + PREPARECALIBRATION_STABLE, + CALIBRATION}; const char *state_names[] = { "INITIAL", "BOOTUP", "READY", "NEEDSCALIBRATION", - "PREPARECALIBRATION", + "PREPARECALIBRATION_INSTABLE", + "PREPARECALIBRATION_STABLE", "CALIBRATION" }; state current_state = INITIAL; @@ -114,19 +121,21 @@ namespace sensor { previous_measurement_at = now; } - void countStableMeasurements() { + bool countStableMeasurements() { + // Returns true, if a sufficient number of stable measurements has been observed. static int16_t previous_co2 = 0; if (co2 > (previous_co2 - config::max_deviation_during_calibration) && co2 < (previous_co2 + config::max_deviation_during_calibration)) { stable_measurements++; Serial.print(F("Number of stable measurements : ")); Serial.println(stable_measurements); - waiting_color = color::green; + switchState(PREPARECALIBRATION_STABLE); } else { stable_measurements = 0; - waiting_color = color::red; + switchState(PREPARECALIBRATION_INSTABLE); } previous_co2 = co2; + return (stable_measurements == config::enough_stable_measurements); } void startCalibrationProcess() { @@ -138,7 +147,7 @@ namespace sensor { scd30.setMeasurementInterval(2); // [s] The change will only take effect after next measurement. Serial.println(F("Waiting until the measurements are stable for at least 2 minutes.")); Serial.println(F("It could take a very long time.")); - switchState(PREPARECALIBRATION); + switchState(PREPARECALIBRATION_INSTABLE); } void calibrateAndRestart() { @@ -191,7 +200,8 @@ namespace sensor { // No special signaling, we want to show the CO2 value case READY: break; case NEEDSCALIBRATION: led_effects::showWaitingLED(color::magenta); break; - case PREPARECALIBRATION: led_effects::showWaitingLED(waiting_color); break; + case PREPARECALIBRATION_INSTABLE: led_effects::showWaitingLED(color::red); break; + case PREPARECALIBRATION_STABLE: led_effects::showWaitingLED(color::green); break; // No special signaling here, too. case CALIBRATION: break; // This should not happen. @@ -218,14 +228,17 @@ namespace sensor { // zero ppm but non-zero temperature and non-zero humidity. Serial.println(F("Invalid sensor data - CO2 concentration <= 0 ppm")); switchState(BOOTUP); + } else if ((current_state == PREPARECALIBRATION_INSTABLE) || + (current_state == PREPARECALIBRATION_STABLE)) { + // Check for pre-calibration states first, because we do not want to + // leave them before calibration is done. + bool ready_for_calibration = countStableMeasurements(); + if (ready_for_calibration) { + calibrateAndRestart(); + } } else if (co2 < 250) { // Sensor should be calibrated. switchState(NEEDSCALIBRATION); - } else if (current_state == PREPARECALIBRATION) { - countStableMeasurements(); - if (stable_measurements == config::enough_stable_measurements) { - calibrateAndRestart(); - } } else { switchState(READY); }