Commit a5e847e9 authored by Käppler's avatar Käppler
Browse files

co2_sensor: Handle pre-calibration by states

* split state PREPARECALIBRATION into
PREPARECALIBRATION_INSTABLE (co2 measurements are changing
too much to start calibration) and

PREPARECALIBRATION_STABLE (co2 measurements are stable,
now waiting for 60 stable measurements)

* Handle all possible LED signal states in showState()
* drop now unused `waiting_color`
parent 0604a79c
...@@ -24,7 +24,6 @@ namespace sensor { ...@@ -24,7 +24,6 @@ namespace sensor {
float humidity = 0; float humidity = 0;
char timestamp[23]; char timestamp[23];
int16_t stable_measurements = 0; int16_t stable_measurements = 0;
uint32_t waiting_color = color::blue;
/** /**
* Define sensor states * Define sensor states
...@@ -36,13 +35,21 @@ namespace sensor { ...@@ -36,13 +35,21 @@ namespace sensor {
* PREPARECALIBRATION -> forced calibration was initiated, waiting for stable measurements * PREPARECALIBRATION -> forced calibration was initiated, waiting for stable measurements
* CALIBRATION -> the sensor does calibrate itself * 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[] = { const char *state_names[] = {
"INITIAL", "INITIAL",
"BOOTUP", "BOOTUP",
"READY", "READY",
"NEEDSCALIBRATION", "NEEDSCALIBRATION",
"PREPARECALIBRATION", "PREPARECALIBRATION_INSTABLE",
"PREPARECALIBRATION_STABLE",
"CALIBRATION" "CALIBRATION"
}; };
state current_state = INITIAL; state current_state = INITIAL;
...@@ -114,19 +121,21 @@ namespace sensor { ...@@ -114,19 +121,21 @@ namespace sensor {
previous_measurement_at = now; 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; static int16_t previous_co2 = 0;
if (co2 > (previous_co2 - config::max_deviation_during_calibration) if (co2 > (previous_co2 - config::max_deviation_during_calibration)
&& co2 < (previous_co2 + config::max_deviation_during_calibration)) { && co2 < (previous_co2 + config::max_deviation_during_calibration)) {
stable_measurements++; stable_measurements++;
Serial.print(F("Number of stable measurements : ")); Serial.print(F("Number of stable measurements : "));
Serial.println(stable_measurements); Serial.println(stable_measurements);
waiting_color = color::green; switchState(PREPARECALIBRATION_STABLE);
} else { } else {
stable_measurements = 0; stable_measurements = 0;
waiting_color = color::red; switchState(PREPARECALIBRATION_INSTABLE);
} }
previous_co2 = co2; previous_co2 = co2;
return (stable_measurements == config::enough_stable_measurements);
} }
void startCalibrationProcess() { void startCalibrationProcess() {
...@@ -138,7 +147,7 @@ namespace sensor { ...@@ -138,7 +147,7 @@ namespace sensor {
scd30.setMeasurementInterval(2); // [s] The change will only take effect after next measurement. 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("Waiting until the measurements are stable for at least 2 minutes."));
Serial.println(F("It could take a very long time.")); Serial.println(F("It could take a very long time."));
switchState(PREPARECALIBRATION); switchState(PREPARECALIBRATION_INSTABLE);
} }
void calibrateAndRestart() { void calibrateAndRestart() {
...@@ -191,7 +200,8 @@ namespace sensor { ...@@ -191,7 +200,8 @@ namespace sensor {
// No special signaling, we want to show the CO2 value // No special signaling, we want to show the CO2 value
case READY: break; case READY: break;
case NEEDSCALIBRATION: led_effects::showWaitingLED(color::magenta); 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. // No special signaling here, too.
case CALIBRATION: break; case CALIBRATION: break;
// This should not happen. // This should not happen.
...@@ -218,14 +228,17 @@ namespace sensor { ...@@ -218,14 +228,17 @@ namespace sensor {
// zero ppm but non-zero temperature and non-zero humidity. // zero ppm but non-zero temperature and non-zero humidity.
Serial.println(F("Invalid sensor data - CO2 concentration <= 0 ppm")); Serial.println(F("Invalid sensor data - CO2 concentration <= 0 ppm"));
switchState(BOOTUP); 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) { } else if (co2 < 250) {
// Sensor should be calibrated. // Sensor should be calibrated.
switchState(NEEDSCALIBRATION); switchState(NEEDSCALIBRATION);
} else if (current_state == PREPARECALIBRATION) {
countStableMeasurements();
if (stable_measurements == config::enough_stable_measurements) {
calibrateAndRestart();
}
} else { } else {
switchState(READY); switchState(READY);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment