vd Brink Home Automations

Home automations: Home Assistant, ESPHome, Node-RED and more.

Follow me on GitHub

ESPHome CO2 sensor

Based on the SCD40 sensor

Introduction

SCD40

There are CO2 sensors available, most of them are expensive, but you can also create one yourself with just a single sensor and an ESP board. It’s easy (and fun) to create one yourself.
You can even create this one WITHOUT SOLDERING!!

CO2 stands for Carbon dioxide and is measured in Parts per million (ppm).

If your in a space with a too high ppm level, you can feel tired, your start yawning and can give you a headache. For your, and your family health, it’s important to act when these values are too high.
The value rice gradual, so you don’t notice it directly. That’s why it’s important to get notified about it.

The base value is what you measure outside and is around 400 ppm.

This table shows for which value, which action is required.

ppm condition action
400 - 800 good no action is required
800 - 1200 medium open a window
1200+ bad limit has reached, open all windows

In Home Assistant, you can visualize how the CO2 value changed over time. And with an automation, you can get notified when the value is too high. Use a notification to get a message on your phone or a smart speaker.

SCD40

Read along how you create this graph yourself…


My solution

This sensor is the easiest way to start with ESPHome.
No soldering is required here.
You only need to connect the wires to the ESP and flash the correct configuration.

hardware connected

Click on the photo to open it fullscreen.


Table of Contents


Required hardware

These hardware components do I use for this project.

Affiliate links are used here. Same price, and you sponsor this blog.

SCD40 CO2 sensor

This small gas sensor measures CO2 (in a range 400-2000 ppm) and also temperature (-10-60 degrees) and humidity (0-100 percent).
The SCD40 datasheet for all the details specs from this sensor.

This sensor is useful if you don't want to solder (AliExpress)
GY-SCD40 CO2 sensor without soldering

ESP board

You can use any ESP board: ESP32, ESP D1 mini, but on this page I use an ESP8266.

ESP8266 NodeMCU v3 (Ch340) with pre soldered pins (AliExpress)
ESP8266 Node MCU
Alternative link (AliExpress)

Case

You can use any object with holes in it, which has a minimum length of 7 cm, width of 3 cm, and a height of 3 cm.
The only requirement is that there could be enough air reach the sensor to measure the values in the air.\

It can also be a plastic box from a local shop and drill some holes in it.

Also, a decorative small statuette can be used as long as it is porous or with holes.

On AliExpress they also sell Plastic DIY Cases (AliExpress)
DIY cases

USB power cable

A cable to power the ESP.

Micro USB cable to USB A to power the ESP (AliExpress)
Micro USB cable

5V USB power adapter

A power adapter to power the ESP.

5V USB power adapter (AliExpress)
5V USB power adapter


Found a dead link? Please inform me or look at ESPHome DIY sensors - Best Buy Tips for alternative links.


Connect the hardware

I’ve made a scheme how to connect the GY SCD40 to the ESP.
This sensor uses an i2c bus interface to connect to the ESP. This makes it possible to connect multiple sensors to this bus.
The ESP has predefined pins for SDA (data) and SDL (clock).

ESP pin GPIO esp8266 pin SCD40 pin color
D2 GPIO4 SDA (data) white
D1 GPIO5 SDL (clock) yellow
G GND GND black
3V 3 V VCC red

Connect the SCD40 to the ESP

Connect the four wires direct to the ESP8266 NodeMCU like this.

hardware connected hardware connected cables

Click on the photos to open them in fullscreen.


Required software

ESPHome

ESPHome

The only software you need is ESPHome.

This software is used to flash the config file to the ESP board.

Their website contains a lot of information about how-to config and calibrate all kinds of sensors.
Also, the one we used here:

Flash the script

There are a lot of ways to flash the config file with ESPHome to the board.
Read here how to upload it.

Connect the ESP via USB to the computer.

One possible way is to run Python in command line:

esphome “co2_scd40.yaml” run

Python Flash output

The co2_scd40.yaml YAML script:

# Sourcecode by vdbrink.github.io
esphome:
  name: espscd40
  comment: Room CO2 sensor
  platform: ESP8266
  board: nodemcuv2

wifi:
  ssid: "XXX"
  password: "XXX"
  fast_connect: true # only needed for hidden SSID

# Push the data also to MQTT topics: 
# * CO2 espscd40/sensor/scd40_co2/state
# * Temperature espscd40/sensor/co2_temperature/state  
# * Humidity espscd40/sensor/co2_humidity/state
mqtt:
  broker: 192.168.XXX.XXX
  port: 1883
  username: "XXXX"
  password: "XXXX"

# Enable logging to the console
logger:

# Home Assistant integration
api:

# Pins on an esp8266
i2c:
  sda: 4 # pin 21 for an ESP32
  scl: 5 # pin 22 for an ESP32

# Sensors definitions
sensor:
  - platform: scd4x
    co2:
      name: "SCD40 CO2"
    temperature:
      name: "CO2 temperature"
    humidity:
      name: "CO2 humidity"

Test if it works

Now the data is flashed, check if the sensor pushes the data correctly.

Via console

If you flash the ESP via the console and enabled logging, you see the readings in the console direct after the ESP is flashed.

Logging cmd output

Via Home Assistant

Ones the ESP is online it automatically registers itself by Home Assistant if you installed ESPHome.

You will see a new device with three entities, CO2 , temperature and humidity.

New ESPHome device ESPHome device sensors

Via MQTT

One way is to test, if the ESP works now, check for incoming MQTT messages (if you enabled it in the config).
On Windows you can use the application MQTT Explorer. The sensor sends it data to the topics /homeassistant/sensor/espscd40 and /espscd40

MQTT data

Home Assistant Dashboards

Now the data is available in Home Assistant we can create dashboard elements to visual it.

Dashboard Gauge

In a Gauge, you can directly see if the current CO2 value is correct. I used different colors to indicate how bad the condition is. I used the values from the table mentioned in the Introduction.

Home Assistant Gauge
# Sourcecode by vdbrink.github.io
# Dashboard card code
type: gauge
severity:
  green: 400
  yellow: 800
  red: 1200
entity: sensor.scd40_co2_value
min: 350
max: 1500
name: Room CO2 sensor

Dashboard Graphic

To show the history of the last 6 hours, you can use the history-graph-card (or a line-card for a rawer version).

CO2 value for the last 6 hours

The corresponding dashboard yaml code.

# Sourcecode by vdbrink.github.io
# Dashboard card code
type: history-graph
entities:
  - entity: sensor.scd40_co2_value
hours_to_show: 6

Dashboard Graphic with levels

Home Assistant History Graph

You can also show baseline values in the graph by creating some extra custom sensors with a fixed value.
This shows direct if the value is still correct.

# Sourcecode by vdbrink.github.io
# Dashboard card code
type: history-graph
entities:
  - entity: sensor.scd40_co2_value
  - entity: sensor.co2_value_800
  - entity: sensor.co2_value_1200
  - entity: sensor.co2_value_1500
hours_to_show: 24

This is how you create three custom lines in the graph to see the threshold values. Add this section to your configuration.yaml to create the three static helper sensors.


# Sourcecode by vdbrink.github.io
# configuration.yaml
sensor:
  - platform: template
    sensors:
      co2_value_800:
        friendly_name: "good"
        value_template: 800
        unit_of_measurement: 'ppm'
      co2_value_1200:
        friendly_name: "medium"
        value_template: 1200
        unit_of_measurement: 'ppm'
      co2_value_1500:
        friendly_name: "bad"
        value_template: 1500
        unit_of_measurement: 'ppm'

Dashboard condition text

Home Assistant conditional CO2 text

This creates a new sensor that shows a textual presentation of the current condition.


# Sourcecode by vdbrink.github.io
# configuration.yaml
- platform: template
  sensors:
    scd40_co2_value_text:
        icon_template: "mdi:molecule-co2"
        friendly_name: "roomname CO2"
        value_template: >-
          {% set state = states('sensor.scd40_co2_value') | int %}
          {% if state < 800 %}good
          {% elif state > 800 and state <= 1200 %}medium
          {% elif state > 1200 and state <= 1500 %}bad
          {% elif state > 1500%}very bad
          {% else %}unknown{% endif %}

Dashboard bad condition text

In my dashboard, I have a section with important messages. Only when there is an action required, you see that here. There is also a message when the CO2 value is not good. This section can be achieved by using conditional entities.


# Sourcecode by vdbrink.github.io
# Dashboard card code
type: entities
entities:
- type: conditional
  conditions:
    - entity: sensor.scd40_co2_value_text
      state_not: good
      row:
        entity: sensor.scd40_co2_value_text

Dashboard Mushroom entity

mushroom chips Show a green icon, without any text, if the level is less the 800 ppm, less than 1200 ppm yellow, less than 1500 ppm red.

# Sourcecode by vdbrink.github.io
# Dashboard card code
type: custom:mushroom-chips-card
chips:
  - chip: null
    type: template
    icon: mdi:molecule-co2
    entity: sensor.senseair_co2_value
    content: ''
    icon_color: |-
      {% if is_state('sensor.scd40_co2_value', 'unavailable') %}
         blue
      {% elif states('sensor.scd40_co2_value')|int > 1500 %}
         red
      {% elif states('sensor.scd40_co2_value')|int > 1200 %}
         orange
      {% elif states('sensor.scd40_co2_value')|int > 800 %}
         yellow
      {% else %}
         green
      {% endif %}


Automations

When the CO2 value is too high, you can send a notification to your phone or smart speaker.
Or use a colored light or LED-strip to indicate the condition.



That’s it!


Top | Homepage | Best Buy Tips