From 2807ee2647a61522df8d06faa7c4188b98de6880 Mon Sep 17 00:00:00 2001 From: Juerd Waalboer Date: Thu, 11 Mar 2021 03:54:36 +0100 Subject: [PATCH] Implement manual calibration (command 0x87) --- operame.ino | 62 ++++++++++++++++++++++++++++++++++++++++++++--- operame_strings.h | 25 +++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/operame.ino b/operame.ino index d9c564a..975df83 100644 --- a/operame.ino +++ b/operame.ino @@ -113,11 +113,31 @@ void display_ppm(int ppm) { display_big(String(ppm), fg, bg); } +void calibrate() { + auto lines = T.calibration; + for (int count = 60; count >= 0; count--) { + lines.back() = String(count); + display_lines(lines, TFT_RED); + unsigned long start = millis(); + while (millis() - start < 1000) { + if (button(pin_demobutton) || button(pin_portalbutton)) return; + } + } + + lines = T.calibrating; + if (driver == AQC) for (auto& line : lines) line.replace("400", "425"); + display_lines(lines, TFT_MAGENTA); + + set_zero(); // actually instantaneous + delay(15000); // give time to read long message +} + void ppm_demo() { display_big("demo!"); delay(3000); display_logo(); delay(1000); + int buttoncounter = 0; for (int p = 400; p < 1200; p++) { display_ppm(p); if (button(pin_demobutton)) { @@ -125,6 +145,18 @@ void ppm_demo() { delay(500); return; } + + // Hold portal button from 700 to 800 for manual calibration + if (p >= 700 && p < 800 && !digitalRead(pin_portalbutton)) { + buttoncounter++; + } + if (p == 800 && buttoncounter >= 85) { + while (!digitalRead(pin_portalbutton)) delay(100); + calibrate(); + display_logo(); + delay(500); + return; + } delay(30); } display_logo(); @@ -184,6 +216,13 @@ void connect_mqtt() { } } +void flush(Stream& s, int limit = 20) { + // .available() sometimes stays true (why?), hence the limit + + s.flush(); // flush output + while(s.available() && --limit) s.read(); // flush input +} + int aqc_get_co2() { static bool initialized = false; @@ -192,12 +231,10 @@ int aqc_get_co2() { int co2 = -1; for (int attempt = 0; attempt < 3; attempt++) { - hwserial1.flush(); - int limit = 20; // .available() sometimes stays true - while(hwserial1.available() && --limit) hwserial1.read(); - + flush(hwserial1); hwserial1.write(command, sizeof(command)); delay(50); + size_t c = hwserial1.readBytes(response, sizeof(response)); if (c != sizeof(response) || response[0] != 0xff || response[1] != 0x86) { continue; @@ -223,6 +260,11 @@ int aqc_get_co2() { return co2; } +void aqc_set_zero() { + const uint8_t command[9] = { 0xff, 0x01, 0x87, 0, 0, 0, 0, 0, 0x78 }; + hwserial1.write(command, sizeof(command)); +} + void mhz_setup() { mhz.begin(hwserial1); // mhz.setFilter(true, true); Library filter doesn't handle 0436 @@ -253,6 +295,10 @@ int mhz_get_co2() { return co2; } +void mhz_set_zero() { + mhz.calibrate(); +} + int get_co2() { // <0 means read error, 0 means still initializing, >0 is PPM value @@ -264,6 +310,14 @@ int get_co2() { return -1; // suppress warning } +void set_zero() { + if (driver == AQC) { aqc_set_zero(); return; } + if (driver == MHZ) { mhz_set_zero(); return; } + + // Should be unreachable + panic(T.error_driver); +} + void setup() { Serial.begin(115200); Serial.println("Operame start"); diff --git a/operame_strings.h b/operame_strings.h index cdae1d9..1370aea 100644 --- a/operame_strings.h +++ b/operame_strings.h @@ -31,6 +31,8 @@ struct Texts { ; std::vector> portal_instructions; std::list first_run; + std::list calibration; + std::list calibrating; }; std::map languages { @@ -101,6 +103,17 @@ bool select(Texts& T, String language) { "Initializing", "flash memory.", }; + T.calibration = { + "Manual calibration!", + "Press button", + "to cancel.", + "" + }; + T.calibrating = { + "Assuming current", + "CO2 level to be", + "400 PPM." + }; return true; } @@ -157,6 +170,18 @@ bool select(Texts& T, String language) { "Flashgeheugen", "wordt voorbereid." }; + T.calibration = { + "Handmatige", + "calibratie!", + "knop = stop", + "" + }; + T.calibrating = { + "Het huidige CO2-", + "niveau wordt", + "aangenomen", + "400 PPM te zijn." + }; return true; }