diff --git a/ampel-firmware/co2_sensor.cpp b/ampel-firmware/co2_sensor.cpp index e532065bbb517f9b12ac3a1a9fc5ca603b7519fd..414b45de090fd32c82fd5ee3c92cc47fb90a2e56 100644 --- a/ampel-firmware/co2_sensor.cpp +++ b/ampel-firmware/co2_sensor.cpp @@ -3,10 +3,12 @@ namespace config { // Values should be defined in config.h uint16_t measurement_timestep = MEASUREMENT_TIMESTEP; // [s] Value between 2 and 1800 (range for SCD30 sensor) + const uint16_t measurement_timestep_bootup = 2; // [s] Measurement timestep during acclimatization const uint16_t altitude_above_sea_level = ALTITUDE_ABOVE_SEA_LEVEL; // [m] uint16_t co2_calibration_level = ATMOSPHERIC_CO2_CONCENTRATION; // [ppm] int8_t max_deviation_during_calibration = 30; // [ppm] int8_t enough_stable_measurements = 60; + const uint8_t max_deviation_during_bootup = 20; // [%] #ifdef TEMPERATURE_OFFSET // Residual heat from CO2 sensor seems to be high enough to change the temperature reading. How much should it be offset? // NOTE: Sign isn't relevant. The returned temperature will always be shifted down. @@ -97,9 +99,9 @@ namespace sensor { //NOTE: The timer seems to be inaccurate, though, possibly depending on voltage. Should it be offset? Serial.println(); Serial.print(F("Setting SCD30 timestep to ")); - Serial.print(config::measurement_timestep); - Serial.println(" s."); - scd30.setMeasurementInterval(config::measurement_timestep); // [s] + Serial.print(config::measurement_timestep_bootup); + Serial.println(" s during acclimatization."); + scd30.setMeasurementInterval(config::measurement_timestep_bootup); // [s] sensor_console::defineIntCommand("co2", setCO2forDebugging, F(" 1500 (Sets co2 level, for debugging purposes)")); sensor_console::defineIntCommand("timer", setTimer, F(" 30 (Sets measurement interval, in s)")); @@ -122,6 +124,16 @@ namespace sensor { previous_measurement_at = now; } + bool hasSensorSettled() { + static uint16_t last_co2 = 0; + uint16_t delta; + delta = abs(co2 - last_co2); + last_co2 = co2; + // We assume the sensor has acclimated to the environment if measurements + // change less than a specified percentage of the current value. + return (co2 > 0 && delta < ((uint32_t)co2 * config::max_deviation_during_bootup / 100)); + } + bool countStableMeasurements() { // Returns true, if a sufficient number of stable measurements has been observed. static int16_t previous_co2 = 0; @@ -185,6 +197,15 @@ namespace sensor { } void switchStateForCurrentPPM() { + if (current_state == BOOTUP) { + if (!hasSensorSettled()) return; + switchState(READY); + Serial.println(F("Sensor acclimatization finished.")); + Serial.print(F("Setting SCD30 timestep to ")); + Serial.print(config::measurement_timestep); + Serial.println(" s."); + scd30.setMeasurementInterval(config::measurement_timestep); // [s] + } if (co2 == 0) { // NOTE: Data is available, but it's sometimes erroneous: the sensor outputs // zero ppm but non-zero temperature and non-zero humidity.