CO2 monitoring with SCD30 sensor and HA integration

Tags: #<Tag:0x00007f7398e4bdb8> #<Tag:0x00007f7398e4bbb0>

These day I tested a nice sensor, the SCD30 from Sensirion.


https://www.sensirion.com/en/environmental-sensors/carbon-dioxide-sensors/carbon-dioxide-sensors-co2/
It’s a nice small unit capable of sense very well carbon dioxide levels in the air, as well as temperature and humidity.
The average cost per unit is around 60 Euro, but I managed to find it for less than half price on an online chinese supplier, have a look on aliexpress/taobao/bangood.
I choose this sensor compared to other mainly for these characteristics:

  • I2C/UART interface
  • calibrated output in ppm
  • high precision of +/- 30ppm
  • operating voltage between 3.3v and 5.5v (therefore good with Arduino and ESP8266 board which only provides 3.3v like ESP01/ESP12).
    The sensor reading seems very accurate. In the following example I closed door and windows of my bedroom before going to sleep, and then opened again once awake:

    Slowly the concentration of CO2 coming from breathing saturates the room, a nice idea could be to trigger a sound or notification to ventilate the room, or starting an air extractor.

Here’s a detail of the sensor in operation, the glowing light is the infrared source necessary to analyze the air samples:


I tested the unit with my beloved NodeMCU wiring it this way:

ESP SCD30
gnd gnd
3v3 +3v
D1 SCL/tx
D2 SDA/rx
Next step is to realize some coding to read the CO2 data, and publish it as MQTT topic.
I made this little code which you can upload on any ESP/Arduino board:

// * * * * * * * * * * * * * * * * * * * * * * *
// SDC30 carbon dioxide sensor to MQTT
// by Ombra for Home Assistant Community - 2020
// * * * * * * * * * * * * * * * * * * * * * * *

#include <ESP8266WiFi.h>
#include <Wire.h>
#include <PubSubClient.h>

#define scd_debug 0
#include “paulvha_SCD30.h”
SCD30 airSensor;

// Network and MQTT broker parameters
#define wifi_ssid “YOUR SSID”
#define wifi_password “YOUR PASSWD”
#define mqtt_server “YOUR MQTT BROKER”
#define mqtt_user “YOUR MQTT USERNAME”
#define mqtt_password “YOUR MQTT PASSWD”

#define co2_topic “chemical_SCD30/CO2”
#define temp_topic “chemical_SCD30/TEMP”
#define humi_topic “chemical_SCD30/HUMI”

int co2, temp, humi;

// --------------------------------
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {

Wire.begin();
Serial.begin(9600);
Serial.println(“SCD30 values:”);

airSensor.setDebug(scd_debug);
airSensor.begin(Wire);

// ------------------------------------
setup_wifi();
client.setServer(mqtt_server, 1883);
}

void setup_wifi() {
delay(10);
// Connect to WiFi network
Serial.println();
Serial.print(“Connecting to network: “);
Serial.println(wifi_ssid);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(”.”);
}
Serial.println("");
Serial.println(“WiFi connected”);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
while (!client.connected()) {
Serial.print(“Connecting to MQTT broker…”);

// no user and pass use this:
// if (client.connect("ESP8266Client")) {
//
if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
  Serial.println("Connected!");
} else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" retry 5 in seconds");
 // set a different delay if having fast connection
  delay(5000);
}

}
}

void loop() {

co2 = airSensor.getCO2();
temp = airSensor.getTemperature(), 1;
humi = airSensor.getHumidity(), 1;

if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();

delay(2000);

// Publish MQTT topic
Serial.print(“CO2(ppm):”);
Serial.println(String(co2).c_str());
client.publish(co2_topic, String(co2).c_str(), true);

  Serial.print("Temperature:");
  Serial.println(String(temp).c_str());
  client.publish(temp_topic, String(temp).c_str(), true);


  Serial.print("humidity:");
  Serial.println(String(humi).c_str());
  client.publish(humi_topic, String(humi).c_str(), true);

}

The script provides 3 topics with the values of CO2, temperature and humidity.
To integrate it in HA make this entry inside the configuration.yaml

sensor 3:
  platform: mqtt
  name: "SDC30 CO2"
  state_topic: "chemical_SCD30/CO2"
  qos: 0
  unit_of_measurement: "PPM"
sensor 4:
  platform: mqtt
  name: "SDC30 temperature"
  state_topic: "chemical_SCD30/TEMP"
  qos: 0
  unit_of_measurement: "C"
sensor 5:
  platform: mqtt
  name: "SDC30 humidity"
  state_topic: "chemical_SCD30/HUMI"
  qos: 0
  unit_of_measurement: "%"

And here is the final result:

2.200ppm in your bedroom :scream: that sure is a very high level which is not so healthy to sleep in…

Great tutorial by the way!

Indeed it’s a high level, I made it intentionally closing the bedroom door and sealing any ventilation (for the love of science!).
Bear in mind that any room is generally not 100% sealed, therefore consider some miniman air exchange from below doors.

“Parameters” used for this sampling:

  • Bedroom size approx. 4m x 4m x 3m
  • Occupants: two
  • Sampling period: 9 hours
  • Internal values: 28c temp - 57% humi - 1007Hpa press
    Once windows opened for recirculation the values dropped to approx 500ppm

Case suggestion for the sensor. After several tries the most reliable way is to provide a double grid to create a sort of small airflow, yet avoiding large readings if accidentally breathing on it.


(the mesh comes from a frying strainer).