ESPHome: CO2 Sensors
I am using an SCD30 connected to a Raspberry PI Zero W to send CO2 measurements every 2 seconds to my Homeassistant. The current value of the SCD30 together with the difference of the last minute is shown in my statusbar, see a previous blog post about this.
But before I migrate the SCD30 to ESPHome I want to try a MH-Z19B I have bought a while ago and never used.
First I soldered pins on the sensor and connected them to a Raspberry PI Pico W.
For this I used Pins GP0
and GP1
to connect to RX/TX of the sensor.
There are a lot of alternative UART pins on the Pico.
A common alternative here would be GP21/GP22.
The sensor needs 4.5~5.5 V DC
so connect to 5V and of course connect GND.
The wiring setup looks like this:
My ESPHome config (ESPHome reference for MHZ19):
uart: tx_pin: 0 rx_pin: 1 baud_rate: 9600 sensor: - platform: mhz19 co2: name: MH-Z19 CO2 Value temperature: name: MH-Z19 Temperature
When booting the sensor is warming up and after this we get CO2 values and temperature:
[20:02:29][W][mhz19:035]: MHZ19 warming up, 30s left [20:03:29][W][component:170]: Component mhz19.sensor cleared Warning flag [20:03:29][D][mhz19:065]: MHZ19 Received CO₂=756ppm Temperature=23°C Status=0x00 [20:03:29][D][sensor:093]: 'MH-Z19 CO2 Value': Sending state 756.00000 ppm with 0 decimals of accuracy [20:03:29][D][sensor:093]: 'MH-Z19 Temperature': Sending state 23.00000 °C with 0 decimals of accuracy
On the Homeassistant dashboard the sensor works as expected:
Next the SCD30, which has a lot better accuracy, but costs more than twice as much. The sensor uses I2C which we used before for a BME280. We connect the SCD30 to GP0/GP1 (the same pins as for UART for the MHZ19). Important here is to connect SDA to GP0 and SCL to GP1 and not crosswise as for RX/TX.
Addionally I added a BME280 the same way my Raspberry PI Zero had used before. Because we have two devices that use I2C but can only specify one pin pair per bus we use the second bus for the BME280. We connected the BME280 to GP26 and GP27 for SDA and SCL and for power to the 3.3V pin.
My ESPHome config for the SCD30 (ESPHome reference) and a BME280:
i2c: - id: bus0 sda: 0 scl: 1 - id: bus1 sda: 26 scl: 27 sensor: - platform: scd30 i2c_id: bus0 co2: name: "Desk CO2" accuracy_decimals: 1 temperature: name: "Desk Temperature" accuracy_decimals: 2 humidity: name: "Desk Humidity" accuracy_decimals: 1 address: 0x61 update_interval: 2s - platform: bme280_i2c i2c_id: bus1 temperature: name: "Desk BME280 Temperature" pressure: name: "Desk BME280 Pressure" humidity: name: "Desk BME280 Humidity" address: 0x76 update_interval: 60s
Bootup is a lot faster and there is no initialization wait for the CO2 sensor:
[20:53:29][D][scd30:186]: Got CO2=962.24ppm temperature=25.13°C humidity=50.12% [20:53:29][D][sensor:093]: 'Desk CO2': Sending state 962.23608 ppm with 1 decimals of accuracy [20:53:29][D][sensor:093]: 'Desk Temperature': Sending state 25.13084 °C with 2 decimals of accuracy [20:53:29][D][sensor:093]: 'Desk Humidity': Sending state 50.12207 % with 1 decimals of accuracy [20:53:34][D][sensor:093]: 'Desk BME280 Temperature': Sending state 22.73586 °C with 1 decimals of accuracy [20:53:34][D][sensor:093]: 'Desk BME280 Pressure': Sending state 959.16943 hPa with 1 decimals of accuracy [20:53:34][D][sensor:093]: 'Desk BME280 Humidity': Sending state 53.44043 % with 1 decimals of accuracy
In Homeassistant the card looks like this:
The temperature of the SCD30 is a bit off.
This can be corrected with the temperature_offset
parameter in the sensor config.
But because I have an additional BME280, I don't care about the offset.
Positives of migrating the SCD30 to ESPHome: one Raspberry Pi Zero shut off (no OS updates anymore, less power consumption for a Pico than for a Zero). Addionally I can update the Pico via OTA every few months with probably less issues.