1010 - WiFiManager: https://github.com/tzapu/WiFiManager
1111 - ArduinoMqttClient (if MQTT is defined)
1212*/
13- #define VERSION " v5.4 "
13+ #define VERSION " v5.5 "
1414
1515#define HEIGHT_ABOVE_SEA_LEVEL 50 // Berlin
1616#define TZ_DATA " CET-1CEST,M3.5.0,M10.5.0/3" // Europe/Berlin time zone from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
@@ -42,7 +42,6 @@ WiFiManager wifiManager;
4242#ifdef airgradient
4343/* use https://github.com/geerlingguy/internet-pi to store values */
4444#include < WebServer.h>
45- #include < SPIFFS.h>
4645const int port = 9925 ;
4746WebServer server (port);
4847#endif /* airgradient */
@@ -83,6 +82,8 @@ SensirionI2CScd4x scd4x;
8382#error This sketch should be used when USB is in OTG mode and MSC On Boot enabled
8483#endif
8584#include " USB.h"
85+ #include < USBMSC.h>
86+ USBMSC usbmsc;
8687
8788RTC_DATA_ATTR bool USB_ACTIVE = false , initDone = false , BatteryMode = false , comingFromDeepSleep = false ;
8889RTC_DATA_ATTR bool LEDonBattery, LEDonUSB, useSmoothLEDcolor, invertDisplay, useFahrenheit, useWiFi, english;
@@ -100,7 +101,7 @@ RTC_DATA_ATTR uint16_t currentIndex = 0;
100101RTC_DATA_ATTR bool overflow = false ;
101102#define NUM_MEASUREMENTS (24 *120 )
102103RTC_DATA_ATTR uint16_t co2measurements[NUM_MEASUREMENTS]; // every 30 sec
103- RTC_DATA_ATTR tempHumData tempHumMeasurements[NUM_MEASUREMENTS / 3 ]; // every 1.5 minutes
104+ RTC_DATA_ATTR tempHumData tempHumMeasurements[NUM_MEASUREMENTS / 4 ]; // every 2 minutes
104105
105106/* WIFI */
106107bool shouldSaveConfig = false ;
@@ -175,13 +176,13 @@ void HandleRootClient() {
175176
176177 String message = " <!DOCTYPE html>\n <html>\n " ;
177178 message += " <head>\n <title>OpenCO2 Sensor</title>\n <link rel='icon' href='/favicon.ico' type='image/png' />\n <meta http-equiv='refresh' content='300'>\n " ;
178- message += " <style> .container { display: flex; gap: 15px; } .rounded-box { font-family: Verdana, Geneva, sans-serif; width: 400px; height: 300px; border-radius: 25px; position: relative; display: flex; flex-direction: column; justify-content: center; font-size: 4em; border: 4px solid #ccc ; } .descr-text { position: absolute; top: 10px; left: 10px; font-size: 0.5em; } .center-text { font-size: 1.5em; text-align: center; } .unit-text { font-size: 0.5em; } </style>" ;
179+ message += " <style> .container { display: flex; gap: 15px; } .rounded-box { font-family: Verdana, Geneva, sans-serif; width: 400px; height: 300px; border-radius: 25px; position: relative; display: flex; flex-direction: column; justify-content: center; font-size: 4em; border: 4px solid grey ; } .descr-text { position: absolute; top: 10px; left: 10px; font-size: 0.5em; } .center-text { font-size: 1.5em; text-align: center; } .unit-text { font-size: 0.5em; } </style>" ;
179180 message += " </head>\n " ;
180181
181182 message += " <script src='https://cdn.plot.ly/plotly-latest.min.js'></script>\n " ;
182- message += " <body>\n " ;
183+ message += " <body style='color: grey; background: black;' >\n " ;
183184
184- message += " <div class='container'><div class='rounded-box' style='background-color:#" + getHexColors (co2) + " ; color:#FFFFFF ;'><div class='descr-text'>CO2</div><div class='center-text'><b>" + String (co2) + " </b><div class='unit-text'>ppm</div></div></div>\n " ;
185+ message += " <div class='container'><div class='rounded-box' style='background-color:#" + getHexColors (co2) + " ; color:'grey' ;'><div class='descr-text'>CO2</div><div class='center-text'><b>" + String (co2) + " </b><div class='unit-text'>ppm</div></div></div>\n " ;
185186 char tempString[6 ];
186187 if (useFahrenheit) sprintf (tempString, " %.1f" ,(temperature * 1 .8f ) + 32 .0f ); // convert to °F
187188 else sprintf (tempString, " %.1f" , temperature);
@@ -228,12 +229,12 @@ void HandleRootClient() {
228229
229230 message = " ];\n " ;
230231 message += " const data = [{x:times, y:yValues, mode:'lines'}];\n " ;
231- message += " const layout = {yaxis: { title: 'CO2 (ppm)'}, title: 'History'};\n " ;
232+ message += " const layout = {yaxis: { title: 'CO2 (ppm)'}, title: 'History', plot_bgcolor:'black', paper_bgcolor:'black' };\n " ;
232233 message += " Plotly.newPlot('CO2Plot', data, layout);\n " ;
233234 server.sendContent (message);
234235
235236 Buffer = " const y1Values = [" ;
236- index = index / 3 .0 ;
237+ index = index / 4 .0 ;
237238 for (int i = 0 ; i < index; i++) {
238239 if (useFahrenheit) sprintf (tempString, " %.1f" ,(getTempMeasurement (i)/10.0 * 1 .8f ) + 32 .0f ); // convert to °F
239240 else sprintf (tempString, " %.1f" , getTempMeasurement (i)/10.0 );
@@ -262,12 +263,12 @@ void HandleRootClient() {
262263 message += " const data2 = [{x: times2, y: y1Values, name: 'Temperature', mode:'lines'}, " ;
263264 message += " {x: times2, y: y2Values, name: 'Humidity', yaxis: 'y2', mode:'lines'}];\n " ;
264265 message += " const layout2 = { showlegend: false, yaxis: {title: 'Temperature (" + String (useFahrenheit? " *F" : " *C" ) ;
265- message += " )'}, yaxis2: { title: 'Humidity (%)', overlaying: 'y', side: 'right'}};\n " ;
266+ message += " )'}, yaxis2: { title: 'Humidity (%)', overlaying: 'y', side: 'right'}, plot_bgcolor:'black', paper_bgcolor:'black' };\n " ;
266267 message += " Plotly.newPlot('TempHumPlot', data2, layout2);\n " ;
267268
268269 message += " </script>\n </body>\n </html>\n " ;
269270 server.sendContent (message);
270- server.client (). stop ();
271+ server.sendContent ( " " ); // Send finish
271272}
272273
273274void HandleRoot () {
@@ -353,6 +354,7 @@ void initOnce() {
353354 LEDonUSB = preferences.getBool (" LEDonUSB" , true );
354355 ledbrightness = preferences.getInt (" ledbrightness" , 5 );
355356 font = preferences.getInt (" font" , 0 );
357+ if (font == 2 ) font = 1 ; // remove gotham font
356358 changeFont (font);
357359 useSmoothLEDcolor = preferences.getBool (" useSmoothLEDcolor" , true );
358360 invertDisplay = preferences.getBool (" invertDisplay" , false );
@@ -436,13 +438,6 @@ void lowBatteryMode() {
436438 rtc_gpio_pullup_dis (USB_PRESENT);
437439 rtc_gpio_pulldown_dis (USB_PRESENT);
438440 esp_sleep_enable_ext0_wakeup (USB_PRESENT, 1 );
439-
440- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); // RTC IO, sensors and ULP co-processor
441- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_AUTO); // RTC slow memory: auto
442- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); // RTC fast memory
443- esp_sleep_pd_config (ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); // XTAL oscillator
444- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_OFF); // CPU core
445- esp_sleep_pd_config (ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF);
446441 esp_deep_sleep_start ();
447442}
448443
@@ -455,12 +450,6 @@ void goto_deep_sleep(int ms) {
455450 }
456451
457452 esp_sleep_enable_timer_wakeup (ms * 1000 ); // periodic measurement every 30 sec - 0.83 sec awake
458- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); // RTC IO, sensors and ULP co-processor
459- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_AUTO); // RTC slow memory: auto
460- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); // RTC fast memory
461- esp_sleep_pd_config (ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); // XTAL oscillator
462- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_OFF); // CPU core
463- esp_sleep_pd_config (ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF);
464453
465454 /* Wakeup by usb power */
466455 rtc_gpio_pullup_dis (USB_PRESENT);
@@ -470,12 +459,16 @@ void goto_deep_sleep(int ms) {
470459 /* Wakeup by IO0 button */
471460 rtc_gpio_pullup_en (BUTTON);
472461 rtc_gpio_pulldown_dis (BUTTON);
473- esp_sleep_enable_ext1_wakeup ( 0x1 , ESP_EXT1_WAKEUP_ALL_LOW); // 2^0 = GPIO_NUM_0 = BUTTON
462+ esp_sleep_enable_ext1_wakeup_io (( 1ULL << BUTTON), ESP_EXT1_WAKEUP_ANY_LOW);
474463
475464 /* Keep LED enabled */
476465 if (LEDonBattery) gpio_hold_en (LED_POWER);
477466 else gpio_hold_dis (LED_POWER);
478467
468+ /* Keep Display power enabled
469+ gpio_hold_en(DISPLAY_POWER);
470+ gpio_deep_sleep_hold_en();*/
471+
479472 comingFromDeepSleep = true ;
480473 esp_deep_sleep_start ();
481474}
@@ -518,12 +511,6 @@ void goto_light_sleep(int ms) {
518511 esp_sleep_enable_gpio_wakeup ();
519512
520513 esp_sleep_enable_timer_wakeup (ms * 1000 ); // periodic measurement every 5 sec -1.1 sec awake
521- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); // RTC IO, sensors and ULP co-processor
522- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_AUTO); // RTC slow memory: auto
523- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); // RTC fast memory
524- esp_sleep_pd_config (ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); // XTAL oscillator
525- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_OFF); // CPU core
526- esp_sleep_pd_config (ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF);
527514 esp_light_sleep_start ();
528515 }
529516}
@@ -628,9 +615,9 @@ void rainbowMode() {
628615
629616void saveMeasurement (uint16_t co2, float temperature, float humidity) {
630617 co2measurements[currentIndex] = co2;
631- if (!(currentIndex % 3 )) { // every 1.5 minutes
632- tempHumMeasurements[currentIndex / 3 ].temperature = (uint16_t )(temperature * 10 );
633- tempHumMeasurements[currentIndex / 3 ].humidity = (uint8_t ) humidity;
618+ if (!(currentIndex % 4 )) { // every 2 minutes
619+ tempHumMeasurements[currentIndex / 4 ].temperature = (uint16_t )(temperature * 10 );
620+ tempHumMeasurements[currentIndex / 4 ].humidity = (uint8_t ) humidity;
634621 }
635622
636623 currentIndex++;
@@ -646,11 +633,11 @@ uint16_t getCO2Measurement(uint16_t index) {
646633}
647634uint16_t getTempMeasurement (uint16_t index) {
648635 if (!overflow) return tempHumMeasurements[index].temperature ;
649- else return tempHumMeasurements[(int )(ceil (currentIndex/3 .0 ) + index) % (NUM_MEASUREMENTS/3 )].temperature ;
636+ else return tempHumMeasurements[(int )(ceil (currentIndex/4 .0 ) + index) % (NUM_MEASUREMENTS/4 )].temperature ;
650637}
651638uint8_t getHumMeasurement (uint16_t index) {
652639 if (!overflow) return tempHumMeasurements[index].humidity ;
653- else return tempHumMeasurements[(int )(ceil (currentIndex/3 .0 ) + index) % (NUM_MEASUREMENTS/3 )].humidity ;
640+ else return tempHumMeasurements[(int )(ceil (currentIndex/4 .0 ) + index) % (NUM_MEASUREMENTS/4 )].humidity ;
654641}
655642
656643void handleWiFiChange () {
@@ -716,6 +703,7 @@ void startWiFi() {
716703
717704 WiFi.setHostname (" OpenCO2" ); // hostname when connected to home network
718705 wifiManager.setConfigPortalBlocking (false );
706+ wifiManager.setClass (" invert" ); // dark theme
719707 wifiManager.setWiFiAutoReconnect (true );
720708 wifiManager.autoConnect (" OpenCO2 Sensor" ); // name of broadcasted SSID
721709
@@ -764,6 +752,7 @@ void setup() {
764752 scd4x.begin (Wire);
765753
766754 USB.onEvent (usbEventCallback);
755+ usbmsc.isWritable (true );
767756 if (!initDone) initOnce ();
768757
769758#if ARDUINO_USB_CDC_ON_BOOT && !ARDUINO_USB_MODE
0 commit comments