Introduction
The SEN55 and SCD40 Breakout Board is a compact PCB kit featuring the SEN55 sensor and an optional SCD40, making it easy to add high-quality air monitoring to any new or existing project.
Please go to this website and copy the randomly generated API key inside the code block as shown below then paste it in the code below where you see "use-a-randomly-generated-key-here".
GPIO Pins Listed:
#These are the i2c pins
i2c:
sda: GPIO1
scl: GPIO0
#This is the onboard LED pin
GPIO3
The Apollo DEV-2 is an ideal starter board for tinkerers, available on its own or bundled with a breadboard and Dupont (jumper) wires. The example YAML below uses the DEV-2 (ESP32 C6 Mini 4MB flash or 8MB flash if newest revision).
Example ESPHome yaml:
#Define Project
substitutions:
name: sen55-scd40-breakout-board
version: "1"
device_description: ${name} made by Apollo Automation - version ${version}.
esphome:
name: "${name}"
friendly_name: SEN55 SCD40 Breakout Board
comment: SEN55-SCD40-Breakout-Board With Apollo DEV-2
# platformio_options:
# board_build.flash_mode: dio
project:
name: "ApolloAutomation.DEV-2"
version: "${version}"
# Define Board
esp32:
board: esp32-c6-devkitc-1
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "use-a-randomly-generated-key-here"
actions:
#Co2 Calibration Action
- action: calibrate_co2_value
variables:
co2_ppm: float
then:
- scd4x.perform_forced_calibration:
value: !lambda "return co2_ppm;"
id: scd40
- action: sen55_clean
then:
- sen5x.start_fan_autoclean: sen55
reboot_timeout: 0s
ota:
- platform: esphome
password: "a53d93acd493275512730c776f88722a"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Apollo-Dev-2 Fallback Hotspot"
password: !secret wifi_password
captive_portal:
web_server:
port: 80
version: 3
i2c:
sda: GPIO1
scl: GPIO0
id: bus_a
number:
- platform: template
name: SEN55 Temperature Offset
id: sen55_temperature_offset
restore_value: true
initial_value: 6.0
min_value: -70.0
max_value: 70.0
entity_category: "CONFIG"
unit_of_measurement: "°C"
optimistic: true
update_interval: never
step: 0.1
mode: box
- platform: template
name: SEN55 Humidity Offset
id: sen55_humidity_offset
restore_value: true
initial_value: 0
min_value: -70.0
max_value: 70.0
entity_category: "CONFIG"
unit_of_measurement: "%"
optimistic: true
update_interval: never
step: 0.1
mode: box
#onboard LED using pin GPIO3 as shown below
light:
- platform: esp32_rmt_led_strip
id: rgb_onboard_light
name: "RGB Onboard Light"
pin: GPIO3
default_transition_length: 0s
chipset: WS2812
num_leds: 1
rgb_order: grb
effects:
- pulse:
name: "Slow Pulse"
transition_length: 1000ms
update_interval: 1000ms
min_brightness: 50%
max_brightness: 100%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 50%
max_brightness: 100%
button:
- platform: restart
icon: mdi:power-cycle
name: "ESP Reboot"
- platform: factory_reset
disabled_by_default: True
name: "Factory Reset ESP"
id: factory_reset_all
- platform: template
name: "Calibrate SCD40 To 420ppm"
id: set_SCD40_calibrate
on_press:
- scd4x.perform_forced_calibration:
value: 420
id: scd40
- platform: template
name: "Clean SEN55"
id: clean_sen55
on_press:
- sen5x.start_fan_autoclean: sen55
sensor:
- platform: internal_temperature
name: "ESP Temperature"
id: sys_esp_temperature
- platform: uptime
name: Uptime
id: sys_uptime
update_interval: 60s
- platform: wifi_signal
name: RSSI
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: scd4x
id: scd40
co2:
name: "CO2"
id: "co2"
automatic_self_calibration: false
update_interval: 60s
measurement_mode: "periodic"
i2c_id: bus_a
- platform: sen5x
id: sen55
pm_1_0:
name: "PM <1µm Weight concentration"
id: pm_1_0
accuracy_decimals: 1
pm_2_5:
name: "PM <2.5µm Weight concentration"
id: pm_2_5
accuracy_decimals: 1
pm_4_0:
name: "PM <4µm Weight concentration"
id: pm_4_0
accuracy_decimals: 1
pm_10_0:
name: "PM <10µm Weight concentration"
id: pm_10_0
accuracy_decimals: 1
temperature:
name: "SEN55 Temperature"
accuracy_decimals: 1
filters:
- lambda: return x - id(sen55_temperature_offset).state;
humidity:
name: "SEN55 Humidity"
filters:
- lambda: return x - id(sen55_humidity_offset).state;
accuracy_decimals: 1
voc:
name: "SEN55 VOC"
id: sen55_voc
algorithm_tuning:
#https://sensirion.com/media/documents/25AB572C/62B463AA/Sensirion_Engineering_Guidelines_SEN5x.pdf
index_offset: 100
learning_time_offset_hours: 72
learning_time_gain_hours: 72
gating_max_duration_minutes: 180
std_initial: 50
gain_factor: 230
nox:
name: "SEN55 NOX"
id: sen55_nox
acceleration_mode: low
store_baseline: true
address: 0x69
update_interval: 10s
- platform: template
name: "PM 0.3 To 1 µm"
id: pm0_3_to_1
disabled_by_default: true
lambda: return id(pm_1_0).state;
unit_of_measurement: "µg/m³"
state_class: measurement
icon: mdi:air-filter
update_interval: 10s
- platform: template
name: "PM 1 To 2.5 µm"
id: pm1_to_2_5
disabled_by_default: true
lambda: return std::max(0.0f, id(pm_2_5).state - id(pm_1_0).state);
unit_of_measurement: "µg/m³"
state_class: measurement
icon: mdi:air-filter
update_interval: 10s
- platform: template
name: "PM 2.5 To 4 µm"
id: pm2_5_to_4
disabled_by_default: true
lambda: return std::max(0.0f, id(pm_4_0).state - id(pm_2_5).state);
unit_of_measurement: "µg/m³"
state_class: measurement
icon: mdi:air-filter
update_interval: 10s
- platform: template
name: "PM 4 To 10 µm"
id: pm4_to_10
disabled_by_default: true
lambda: return std::max(0.0f, id(pm_10_0).state - id(pm_4_0).state);
unit_of_measurement: "µg/m³"
state_class: measurement
icon: mdi:air-filter
update_interval: 10s
text_sensor:
# Convert VOC Index To Text:
# https://sensirion.com/media/documents/02232963/6294E043/Info_Note_VOC_Index.pdf
# https://sensirion.com/media/documents/ACD82D45/6294DFC0/Info_Note_Integration_VOC_NOx_Sensor.pdf
- platform: template
name: "VOC Quality"
id: voc_quality
icon: mdi:air-filter
lambda: |-
if (id(sen55_voc).state < 80) {
return std::string("Improved");}
else if (id(sen55_voc).state < 150) {
return std::string("Normal");}
else if (id(sen55_voc).state < 250) {
return std::string("Abnormal");}
else if (id(sen55_voc).state < 400) {
return std::string("Very abnormal");}
else if (id(sen55_voc).state >= 400) {
return std::string("Extremely abnormal");}
else {
return std::string("Unknown");}
- platform: wifi_info
ip_address:
name: "${name} IP"
icon: "mdi:ip-outline"