Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4629a64
Modifications for different hardware platforms
Nov 1, 2020
8ce4f24
Moved configuration to separate file
Nov 1, 2020
7e0d9c9
Allow enabling/disabling of serial
Nov 1, 2020
1019906
Dynamic WiFi names with MAC suffix, GPIO config twiddling
Nov 5, 2020
f229cdc
Added calibration via button press feature
Nov 5, 2020
cbcfcc2
Dump WiFi hotspot name regularly
Nov 14, 2020
9fd5689
Changed LED and buzzer GPIO config
Nov 14, 2020
62abe5f
Removed support for WiFi client mode (hotspot mode only)
Nov 14, 2020
93d4c5f
Removed support for BME280 pressure sensor
Nov 14, 2020
b81e90f
Fixed recalibration with fresh air
Nov 14, 2020
0ae5f65
Changed minimum concentration as well as calibration reference
Nov 14, 2020
5cf2fa1
Changed buzzer alarms with max beep count, changed sanity check of CO…
Nov 28, 2020
87ca55b
Updated README.md
Nov 28, 2020
e7d5016
Removed obsolete image
Nov 28, 2020
804a1d3
Switched off serial console by default
Dec 3, 2020
4767cc2
Moved comment about CO2 to header, changed log duration (2h) and labe…
Dec 3, 2020
0d6beca
Optimized setting of NeoPixel ring colors (for speed)
Dec 3, 2020
54a896f
Clear NeoPixel ring at startup
Dec 3, 2020
8fb75b6
Use std::max() instead of solely max()
Feb 5, 2021
99f132a
Updated instructions in README.md
Feb 5, 2021
1ee059e
Remove platformio.ini file due to missing test/support from my side
maehw Jan 24, 2023
6dce841
Hide things only MacOS needs
maehw Jan 30, 2023
ab18561
Support for settings in non-volatile memory that can be accessed via …
maehw Jan 30, 2023
c3476d6
Update README.md (the lazy way)
maehw Jan 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.pio
.DS_Store
CMakeLists.txt
CMakeListsPrivate.txt
cmake-build-*/
Expand Down
115 changes: 51 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
# CorO₂Sens

Disclaimer and credits: this repository is a fork from https://github.com/kmetz/coro2sens.

Several changes have been made in this fork. Please also consult the README file of the original version.

The following sections have been updated for this repository:



Build a simple device that warns if CO₂ concentration in a room becomes a risk for COVID-19 aerosol infections.

- Measures CO₂ concentration in room air.
- Controls an RGB LED (green, yellow, red, like a traffic light).
- A buzzer can be connected that alarms if levels are critical.
- Also opens a WiFi portal which shows current readings and a graph (not connected to the internet).
- Controls two LEDs (green + orange/red) for indication of warning/critical CO2 level.
- Controls a NeoPixel ring for indication of CO2 level and its criticality (optional).
- A buzzer can be connected that alarms if levels are critical (optional).
- Also opens a WiFi portal which shows current readings and a graph (not connected to the internet; optional).
- Can be built for ~ $60 / 50€ (parts cost).

This project was heavily inspired by [ideas from Umwelt-Campus Birkenfeld](https://www.umwelt-campus.de/forschung/projekte/iot-werkstatt/ideen-zur-corona-krise).

You can also find a good overview of the topic by Rainer Winkler here: [Recommendations for use of CO2 sensors to control room air quality during the COVID-19 pandemic](https://medium.com/@rainer.winkler.poaceae/recommendations-for-use-of-co2-sensors-to-control-room-air-quality-during-the-covid-19-pandemic-c04cac6644d0).

![coro2sens overview](coro2sens.jpeg)



## Sensors
- The sensor used here is the Sensirion SCD30 (around $50 / 40€) which is optionally augmented by a BME280 pressure sensor to improve accuracy.
- [Look here](https://github.com/RainerWinkler/CO2-Measurement-simple) if you want to use MH-Z19B sensors.

The sensor used here is the Sensirion SCD30 (around 70 USD / 60 €).

The pressure compensation by an additional sensor BME280 is currently no longer supported in this forked repo.




## Threshold values
| LED color |CO₂ concentration |
Expand All @@ -29,73 +41,48 @@ You can also find a good overview of the topic by Rainer Winkler here: [Recommen

Based on a [Recommendation from the REHVA](https://www.rehva.eu/fileadmin/user_upload/REHVA_COVID-19_guidance_document_V3_03082020.pdf)
(Federation of European Heating, Ventilation and Air Conditioning associations, [rehva.eu](https://www.rehva.eu/))
for preventing COVID-19 aerosol spread, especially in schools.
for preventing COVID-19 aerosol spread, especially in schools.


## Web server
You can read current levels and a simple graph for the last hour by connecting to the WiFi `coro2sens` that is created.
Most devices will open a captive portal, immediately showing the data. You can also open `http://10.0.0.1/` in a browser.


## You need
1. Any ESP32 or ESP8266 board (like a [WEMOS D32](https://docs.wemos.cc/en/latest/d32/d32.html) (about $18 / 15€) or [WEMOS LOLIN D1 Mini](https://docs.wemos.cc/en/latest/d1/d1_mini.html) (about $7 / 6€)).
ESP32 has bluetooth, for future expansion.
1. [Sensirion SCD30](https://www.sensirion.com/en/environmental-sensors/carbon-dioxide-sensors/carbon-dioxide-sensors-co2/) I<sup>2</sup>C carbon dioxide sensor module ([mouser](https://mouser.com/ProductDetail/Sensirion/SCD30?qs=rrS6PyfT74fdywu4FxpYjQ==), [digikey](https://www.digikey.com/product-detail/en/sensirion-ag/SCD30/1649-1098-ND/8445334)) (around $50 / 40€).
1. 1 [NeoPixel](https://www.adafruit.com/category/168) compatible RGB LED (WS2812B, like the V2 Flora RGB Smart NeoPixel LED, you can also remove one from a larger strip which might be cheaper).
1. A 3V piezo buzzer or a small speaker.
1. Optional: [Bosch BME280](https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/) I<sup>2</sup>C sensor module (like the GY-BME280 board), for air pressure compensation, improves accuracy (less than $5 / 4€).
1. A nice case :) Make shure the sensor has enough air flow.
## Web server
You can read current levels and a simple graph for the last hour by connecting to the WiFi `coro2sens_<serialno>` that is created.
Most devices will open a captive portal, immediately showing the data. You can also open `http://10.0.0.1/` in a browser.
You can also control most of the settings via the web interface. Visit `http://10.0.0.1/config` in a browser.


### Wiring

| ESP8266 pin | ESP32 pin | goes to |
|:-------------|:--------------|:-------------------------------------------|
| 3V3 | 3V3 | SCD30 VIN, BME280 VIN |
| 5V | 5V | LED +5V |
| GND | GND | SCD30 GND, BME280 GND, LED GND, Buzzer (-) |
| SCL / D1 | SCL / GPIO 22 | SCD30 SCL, BME280 SCL |
| SDA / D2 | SDA / GPIO 21 | SCD30 SDA, BME280 SDA |
| GPIO 0 / D3 | GPIO 16 | LED DIN |
| GPIO 14 / D5 | GPIO 19 | Buzzer (+) |


### Flashing the ESP using [PlatfomIO](https://platformio.org/)
- Simply open the project, select your env (`esp12e` for ESP8266 / `esp32dev` for ESP32) and run / upload.
- Or via command line:
- `pio run -t -e esp12e upload` for ESP8266.
- `pio run -t -e esp32dev upload` for ESP32.
- Libraries will be installed automatically.

### Flash using the Arduino IDE
- Install [the latest Arduino IDE](https://www.arduino.cc/en/main/software).
- [Download the latest code](https://github.com/kmetz/coro2sens/archive/master.zip) and unzip it somewhere.
- Open `coro2sense.ino` in the `coro2sens` sub folder in your Arduino IDE.
- Install (or update) your board platform:
(*Tools –> Board –> Board Manager...*)
- Install `esp8266` or `esp32`.
- Install (or update) the following libraries using the built-in library manager:
(*Tools –> Library Manager...*)
- For ESP8266:
- `SparkFun BME280`
- `FastLED`
- For ESP32:
- `SparkFun SCD30 Arduino Library`
- `SparkFun BME280`
- `FastLED`
- Install the following external libraries:
(download .zip file, then import it via *Sketch –> Include Library –> Add .ZIP Library...*)
- For ESP8266:
## You need
- A NodeMCU board (any other ESP8266 based board might also work).
- [Sensirion SCD30](https://www.sensirion.com/en/environmental-sensors/carbon-dioxide-sensors/carbon-dioxide-sensors-co2/) I<sup>2</sup>C carbon dioxide sensor module ([mouser](https://mouser.com/ProductDetail/Sensirion/SCD30?qs=rrS6PyfT74fdywu4FxpYjQ==), [digikey](https://www.digikey.com/product-detail/en/sensirion-ag/SCD30/1649-1098-ND/8445334)).
- *(optional)* NeoPixel ring
- *(optional)* 2 LEDs (green + yellow/red); the green one indicates "all good" (< 800 ppm) the other one that this limit has been exceeded
- *(optional)* A 3V piezo buzzer or a small speaker.
- *(optional)* You may want to work with Guido Burger's IoT Octopus PCB. This helps fixing the sensor and the NodeMCU, as well as the LEDs.
- *(optional)* A nice case :) Make sure the sensor has enough air flow.
- An Arduino IDE (select the board "NodeMCU 1.0 (ESP-12E Module)", v2.7.1 and v2.7.4 have been tested and should work; you may need to install the board support for the "esp8266")
- Arduino libraries:
- FastLED (via the library manager)
- zip file libraries
(download .zip file, then import it via *Sketch –> Include Library –> Add .ZIP Library...*)
- [paulvha/scd30](https://github.com/paulvha/scd30) ([.zip](https://github.com/paulvha/scd30/archive/master.zip))
- [me-no-dev/ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) ([.zip](https://github.com/me-no-dev/ESPAsyncTCP/archive/master.zip))
- [me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) ([.zip](https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip))
- For ESP32:
- [lbernstone/Tone32](https://github.com/lbernstone/Tone32) ([.zip](https://github.com/lbernstone/Tone32/archive/master.zip))
- [me-no-dev/AsyncTCP](https://github.com/me-no-dev/AsyncTCP) ([.zip](https://github.com/me-no-dev/AsyncTCP/archive/master.zip))
- [me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) ([.zip](https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip))
- Run & upload :)


Please let me know of any issues you might encounter ([open a GitHub issue](https://github.com/kmetz/coro2sens/issues/new/choose) or write me on [twitter.com/kmetz](https://twitter.com/kmetz) or k@kjpm.de).
Also, I'd be for hire for customizations.


### Wiring

| ESP8266 pin | goes to |
| :---------- | :----------------------------------------- |
| 3V3 | SCD30 VIN |
| GND | SCD30 GND, Buzzer (-) |
| SCL / D1 | SCD30 SCL |
| SDA / D2 | SCD30 SDA |
| D3 | LED DIN |
| D5 | Green LED |
| D6 | Buzzer (+) |
| D7 | Warning LED (yellow or red is a good idea) |
| D8 | NeoPixel ring |
Binary file removed coro2sens.jpeg
Binary file not shown.
126 changes: 126 additions & 0 deletions coro2sens/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Define if the Octopus PCB layout is used or not
// ----------------------------------------------------------------------------
#define OCTOPUS 1

// Logging to serial console
// ----------------------------------------------------------------------------
#define SERIAL_BAUDRATE 115200
#define USE_SERIAL_CONSOLE 0
//#undef USE_SERIAL_CONSOLE // Uncomment this line to disable logging to serial console (e.g. "deactivates" bright blue LED on NodeMCU)
#if defined(USE_SERIAL_CONSOLE)
#define serial_begin Serial.begin
#define serial_printf Serial.printf
#define serial_println Serial.println
#else
#define serial_begin
#define serial_printf
#define serial_println
#endif

// LED and NeoPixel ring
// ----------------------------------------------------------------------------
// Activity indicator LED (use the built-in LED if your board has one).
// Which pin on the Arduino is connected to the NeoPixels?

#if defined(OCTOPUS)
#define LED_GREEN_PIN D5
//#define LED_YELLOW_PIN D7
//#define LED_RED_PIN D6
#define LED_WARN_PIN D7 /* combined warning LED to replace separate yellow+red LEDs */
#define NEOPIXEL_PIN D8
#else
#define LED_GREEN_PIN D8
#define LED_YELLOW_PIN D7
#define LED_RED_PIN D6
#define NEOPIXEL_PIN D4
#endif

//#undef NEOPIXEL_PIN

// How many NeoPixels are attached to the Arduino?
#if defined(NEOPIXEL_PIN)
#define LED_INTENSITY_MIN 5
#define LED_INTENSITY_MAX 100
#define LED_INTENSITY 50
#define NUMPIXELS 16
#define COLOR_BLACK 0, 0, 0
#define COLOR_GREEN 0, 3*settings.neopixel_brightness/10, 0
#define COLOR_YELLOW 2*settings.neopixel_brightness/10, settings.neopixel_brightness/10, 0
#define COLOR_RED 3*settings.neopixel_brightness/10, 0, 0
#endif /* defined(NEOPIXEL_PIN) */

// Buzzer, activated continuously when CO2 level is critical.
// ----------------------------------------------------------------------------
#if defined(OCTOPUS)
#define BUZZER_PIN D6
#endif
//#undef BUZZER_PIN // Uncomment if buzzer shall not be used

#ifdef BUZZER_PIN
#define BEEP_DURATION_MS 200 /* Beep duration in milliseconds */
#define BEEP_DURATION_MS_MIN 20
#define BEEP_DURATION_MS_MAX 3000
#define BEEP_TONE_FREQ 1047 /* Note C6 (see also: pitches.h on toneMelody example) */
#define BEEP_TONE_FREQ_MIN 261
#define BEEP_TONE_FREQ_MAX 2093

#define BUZZER_MAX_BEEPS 7 /* Maximum number of beeps for an active alarm */
#define BUZZER_MAX_BEEPS_MIN 0
#define BUZZER_MAX_BEEPS_MAX 99
#endif


// CO2 thresholds for warning and critical warning
// ----------------------------------------------------------------------------
// CO2 Thresholds (ppm).
//
// Recommendation from REHVA (Federation of European Heating, Ventilation and Air Conditioning associations, rehva.eu)
// for preventing COVID-19 aerosol spread especially in schools:
// - warn: 800, critical: 1000
// (https://www.rehva.eu/fileadmin/user_upload/REHVA_COVID-19_guidance_document_V3_03082020.pdf)
//
// General air quality recommendation by the German Federal Environmental Agency (2008):
// - warn: 1000, critical: 2000
// (https://www.umweltbundesamt.de/sites/default/files/medien/pdfs/kohlendioxid_2008.pdf)
//
#define CO2_WARN_PPM 800
#define CO2_WARN_PPM_MIN 500
#define CO2_WARN_PPM_MAX 2000
#define CO2_CRITICAL_PPM 1000
#define CO2_CRITICAL_PPM_MIN 600
#define CO2_CRITICAL_PPM_MAX 3000
#define CO2_PLASABILIT_PPM_MIN 300

// CO2 measurement
// ----------------------------------------------------------------------------
// Update CO2 level every MEASURE_INTERVAL_S seconds.
// Should be kept at 2 unless you want to save power.
#define MEASURE_INTERVAL_S 2

// WiFi hotspot configuration (including IP + DNS)
// ----------------------------------------------------------------------------
// Set to 0 to disable altogether.
#define WIFI_ENABLED 1
#define WIFI_HOTSPOT_PREFIX "coro2sens"
#define WIFI_HOTSPOT_SIZE 64
#define WIFI_AP_IP 10, 0, 0, 1
#define WIFI_AP_NETMASK 255, 255, 255, 0
#define WIFI_DNS_PORTNO 53

// How long the graph/log in the WiFi portal should go back, in minutes.
#define LOG_MINUTES 120
// Label describing the time axis.
#define TIME_LABEL "2 Stunden"

#define GRAPH_W 600
#define GRAPH_H 260
#define LOG_SIZE GRAPH_W

// Button
// ----------------------------------------------------------------------------
#define BUTTON_PIN D3 // "GPIO0/FLASH" button on NodeMCU

// Storage for settings (non-volatile memory)
// ----------------------------------------------------------------------------
#define SETTINGS_STORAGE
#define SETTINGS_EEPROM_MAGIC 0x6D616568
Loading