Skip to content

Commit ac07b2c

Browse files
committed
v4.6 history graph and README update
Go to Menu -> History to see up to 18h of CO2 or Temperature/Humidity measurements in a graph. Min/max/avg values will also be displayed. QR code order is inverted now for easier export.
1 parent fecd940 commit ac07b2c

File tree

4 files changed

+216
-72
lines changed

4 files changed

+216
-72
lines changed

OpenCO2_Sensor.ino

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- WiFiManager: https://github.com/tzapu/WiFiManager
1111
- ArduinoMqttClient (if MQTT is defined)
1212
*/
13-
#define VERSION "v4.5"
13+
#define VERSION "v4.6"
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
@@ -84,7 +84,7 @@ SensirionI2CScd4x scd4x;
8484

8585
RTC_DATA_ATTR bool USB_ACTIVE = false, initDone = false, BatteryMode = false, comingFromDeepSleep = false;
8686
RTC_DATA_ATTR bool LEDonBattery, LEDonUSB, useSmoothLEDcolor, invertDisplay, useFahrenheit, useWiFi, english;
87-
RTC_DATA_ATTR int ledbrightness, HWSubRev, font;
87+
RTC_DATA_ATTR uint8_t ledbrightness, HWSubRev, font;
8888
RTC_DATA_ATTR float maxBatteryVoltage;
8989

9090
/* TEST_MODE */
@@ -484,51 +484,24 @@ void rainbowMode() {
484484

485485
RTC_DATA_ATTR uint8_t hour = 0;
486486
RTC_DATA_ATTR uint8_t halfminute = 0;
487-
RTC_DATA_ATTR uint16_t measurements[24][120];
488-
void saveMeasurement(uint16_t co2) {
487+
#define NUM_HOURS 16 // ESP32-S2 slow RTC memory limitation
488+
RTC_DATA_ATTR SensorData measurements[NUM_HOURS][120];
489+
void saveMeasurement(uint16_t co2, float temperature, float humidity) {
489490
if (halfminute == 120) {
490491
halfminute=0;
491492
hour++;
492493
}
493-
if (hour == 24) {
494-
for (int i=0; i<23; ++i) memcpy(measurements[i], measurements[i + 1], sizeof(uint16_t) * 120);
495-
hour = 23;
494+
if (hour == NUM_HOURS) {
495+
for (int i=0; i<NUM_HOURS-1; ++i) memcpy(measurements[i], measurements[i + 1], sizeof(SensorData) * 120); // destination, source
496+
hour = NUM_HOURS-1;
496497
}
497498

498-
measurements[hour][halfminute] = co2;
499+
measurements[hour][halfminute].co2 = co2;
500+
measurements[hour][halfminute].temperature = (uint16_t)temperature*10;
501+
measurements[hour][halfminute].humidity = (uint8_t)humidity;
499502
halfminute++;
500503
}
501504

502-
uint8_t qrcodeNumber = 0;
503-
void history() {
504-
// DEMO DATA:
505-
/*hour = 2;
506-
for (int i=0; i<120; i++) {
507-
measurements[0][i] = 400+i;
508-
measurements[1][i] = 520+i;
509-
measurements[2][i] = 1000+i;
510-
}
511-
halfminute = 120;*/
512-
513-
if (halfminute == 0 && hour == 0) { // no history data
514-
displayNoHistory();
515-
unsigned long StartTime = millis();
516-
for (;;) if ((millis() - StartTime) > 20000 || digitalRead(BUTTON) == 0) return; // wait for button press OR up to 20 sec
517-
}
518-
519-
qrcodeNumber = hour; // start at current hour
520-
for (int i=0; i<200; i++) {
521-
if (digitalRead(BUTTON) == 0) { // goto next qr code
522-
displayHistory(measurements);
523-
delay(500);
524-
if (qrcodeNumber == hour) qrcodeNumber = 0;
525-
else qrcodeNumber++;
526-
i = 0; // display qrcode again for 20 sec
527-
}
528-
delay(100);
529-
}
530-
}
531-
532505
void handleWiFiChange() {
533506
scd4x.stopPeriodicMeasurement();
534507
scd4x.setTemperatureOffset(getTempOffset());
@@ -612,7 +585,7 @@ void startWiFi() {
612585
float currentTemp = temperatureRead();
613586
RTC_DATA_ATTR float ESP32temps[10] = {currentTemp,currentTemp,currentTemp,currentTemp,currentTemp,currentTemp,currentTemp,currentTemp,currentTemp,currentTemp};
614587
RTC_DATA_ATTR float sumTemp = currentTemp * 10;
615-
RTC_DATA_ATTR int indexTemp = 0;
588+
RTC_DATA_ATTR uint8_t indexTemp = 0;
616589
void measureESP32temperature() {
617590
currentTemp = temperatureRead();
618591
sumTemp -= ESP32temps[indexTemp];
@@ -694,7 +667,8 @@ void loop() {
694667
errorToString(error, errorMessage, 256);
695668
displayWriteError(errorMessage);
696669
} else {
697-
if (BatteryMode) saveMeasurement(new_co2);
670+
extern int refreshes;
671+
if (BatteryMode || (refreshes%6 == 1)) saveMeasurement(new_co2, new_temperature, humidity);
698672
/* don't update in Battery mode, unless CO2 has changed by 3% or temperature by 0.5°C */
699673
if (!TEST_MODE && BatteryMode && comingFromDeepSleep) {
700674
if ((abs(new_co2 - co2) < (0.03*co2)) && (fabs(new_temperature - temperature) < 0.5)) {

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
![alt text](https://github.com/davidkreidler/OpenCO2_Sensor/raw/main/pictures/Header.png)
66

7-
OpenCO2 Sensor is an Arduino IDE compatible Repository for an E-Ink Indoor air quality Sensor using the ESP32, SCD4X and an RBG LED.
7+
OpenCO2 Sensor is an Arduino IDE compatible Repository for an E-Ink Indoor air quality Sensor using the ESP32, SCD4X and an RGB LED.
88

99
## Buy it [here on Tindie](https://www.tindie.com/products/davidkreidler/open-co2-sensor/)
1010

@@ -41,30 +41,37 @@ Size: 4.7 x 4.1 x 2.4 cm
4141
# Menu
4242

4343
Press the Menu button on the backside of the OpenCO2 Sensor. Select an option via long press (1+ sec) or move to next menu point via a short press. Choose between:
44-
* `LED toggle` enable or disable the LED in battery mode
45-
* `Rainbow` fun little easter egg (press ↪️ to exit)
44+
* `LED` control color, brightness and when the LED should be enabled
45+
* `Display` can be inverted. Also change the Temperature unit, language and font
4646
* `Calibrate` put the sensor outside for 3+ minutes (only run this, if calibration is needed)
47-
* `History` display up to 24 QR codes containing 1h of measurements each (only stored in battery mode)
47+
* `History` display up to 18h of CO2, temperature and humidity as a graph. Values can also be exported via QR codes containing 1h of CO2 measurements each.
4848
* `Wi-Fi` enable or disable wireless connections
49-
* `Exit` quit Menu (automatically after 20 sec)
49+
* `Info` shows MAC Address, serial numbers, uptime, version and battery details
50+
* `Rainbow` fun little easter egg
5051

5152
# Wi-Fi
5253

53-
Enable Wi-Fi via the Menu button. When power is connected, an access point `OpenCO2 Sensor` is enabled. Connect to it and navigate to http://192.168.4.1 (it will open automatically on modern Smartphones). Insert your home Wi-Fi credentials under `Configure WiFi`. Choose your network name from the list in the top and insert the password. Click `Save`. The sensor will now be automatically connected. Navigate to ip:9925 to see current co2/temperature/humidity measurements.
54+
Enable Wi-Fi via the Menu button. When power is connected, an access point `OpenCO2 Sensor` is enabled. Connect to it and navigate to http://192.168.4.1 (it will open automatically on modern Smartphones). Insert your home Wi-Fi credentials under `Configure WiFi`. Choose your network name from the list in the top and insert the password. Click `Save`. The sensor will now be automatically connected. Navigate to IP:9925 to see current co2/temperature/humidity measurements.
5455
![alt text](https://github.com/davidkreidler/OpenCO2_Sensor/raw/main/pictures/setup.jpg)
5556

5657
# AirGradient / Grafana
5758

5859
Use [internet-pi](https://github.com/geerlingguy/internet-pi) to store the CO2 / Temperature / Humidity data on your Pi. First connect the OpenCO2 Sensor to your Wi-Fi network and follow the instructions https://www.youtube.com/watch?v=Cmr5VNALRAg Then download the https://raw.githubusercontent.com/davidkreidler/OpenCO2_Sensor/main/grafana_OpenCO2_Sensor.json and import it into Grafana.
5960
![alt text](https://github.com/davidkreidler/OpenCO2_Sensor/raw/main/pictures/grafana.png)
6061

62+
# Update via USB
63+
64+
1. Download `FIRMWARE.BIN` from the latest [release](https://github.com/davidkreidler/OpenCO2_Sensor/releases)
65+
2. Plug a data USB-C cable into your PC and the Sensor
66+
3. copy `FIRMWARE.BIN` to the USB device
67+
6168
# OTA Update
6269

63-
Download `OpenCO2_Sensor.ino.bin` from the latest [release](https://github.com/davidkreidler/OpenCO2_Sensor/releases).
70+
Download `FIRMWARE.BIN` from the latest [release](https://github.com/davidkreidler/OpenCO2_Sensor/releases).
6471
Enable Wi-Fi via the Menu button, in an area where no previously known network is active. Connect power. Then connect to `OpenCO2 Sensor` and navigate to http://192.168.4.1 . Under `Update` select the `OpenCO2_Sensor.ino.bin` file and click `Update`. The Sensor will restart.
6572
![alt text](https://github.com/davidkreidler/OpenCO2_Sensor/raw/main/pictures/OTA.jpg)
6673

67-
# Update via USB
74+
# Update via USB (from an old release)
6875

6976
1. Download all files from the latest [release](https://github.com/davidkreidler/OpenCO2_Sensor/releases)
7077
2. Make sure, that the power switch is in the `ON` position (down)

epd_abstraction.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ const char* GermanOptionsMenuItems[NUM_DISPLAY_OPTIONS] = {
8080
"Beenden"
8181
};
8282

83+
typedef struct {
84+
uint8_t humidity : 7; // 7 bits (range 0 to 100)
85+
uint16_t temperature : 9; // 9 bits (/10= range 0 to 51.1°C )
86+
uint16_t co2;
87+
} SensorData;
88+
8389
void handleButtonPress();
8490
void changeFont(int font);
8591
void displayWelcome();
@@ -93,8 +99,6 @@ void displayWriteTestResults(float voltage, uint16_t sensorStatus);
9399
void displayBattery(uint8_t percentage);
94100
void updateDisplay();
95101
void displayImage(const unsigned char* image_buffer);
96-
void displayHistory(uint16_t measurements[24][120]);
97-
void displayNoHistory();
98102
void displayCalibrationWarning();
99103
void displayWiFi(bool useWiFi);
100104
void displayWiFiStrengh();

0 commit comments

Comments
 (0)