Hi.
I have a small home assistant setup with one esp8266 and a pms5003 sensor so i can monitor small particules because i have two kids and my wife that suffers from asthma.
Initially i only had the esp8266 with pms5003 connected, but everytime i wanted to see how the particules are i had to reach the smartphone, so i bought 4 ws2812 and tryed to output on each led the particules acording to AQI (air quality index) schema in Europe. So the first led is for PM1 (particules below 1µm) the second PM2,5, the third PM10 and the fourth the AQI itself.
The problem i have is when the data is colected, all the leds light white. They seem to flash (i notice other colors) for a brief moment once data is provided by the pms5003, but stay white the rest of the time.
The yaml i use follows:
substitutions:
name: esphome-web-0524a0
friendly_name: Sensor Partículas
esphome:
name: ${name}
friendly_name: ${friendly_name}
name_add_mac_suffix: false
project:
name: esphome.web
version: '4.0'
on_boot:
priority: 600 # garantir que executa antes de qualquer leitura
then:
- light.turn_off: Particle_Matter_Indicator
#then:
#- delay: 1s
#- script.execute: BootFlash
esp8266:
board: nodemcu
framework:
version: recommended
# Enable logging
logger:
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: !secret sensorParticulas
services:
- service: dummy_block_led
variables: {}
then:
- logger.log: "API de luz bloqueada"
ota:
- platform: esphome
password: !secret ota_pass
wifi:
networks:
- ssid: !secret wifi_ssid2
password: !secret wifi_password2
- ssid: !secret wifi_ssid3
password: !secret wifi_password3
power_save_mode: NONE
manual_ip:
static_ip: 192.168.1.xx
gateway: 192.168.1.xx
subnet: 255.255.255.0
dns1: 192.168.1.xx
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esphomexxxxxxxxxx"
password: !secret ap_pass
captive_portal:
globals:
- id: aqi
type: int
restore_value: False
initial_value: '0'
# Light component
light:
- platform: neopixelbus
type: GRB
variant: WS2812
pin: GPIO12
method: BIT_BANG
num_leds: 4
name: "Indicador de Particulas"
id: Particle_Matter_Indicator
internal: true
default_transition_length: 0.1s
initial_state:
state: True
restore_mode: ALWAYS_OFF
effects: []
# Define onboard LED
output:
- platform: gpio
pin: GPIO2
id: OnboardLED
inverted: true
button:
- platform: restart
name: "Reiniciar"
# Particle sensor PMS5003
uart:
rx_pin: GPIO13
tx_pin: GPIO15
baud_rate: 9600
sensor:
- platform: pmsx003
type: PMSX003
id: part_sensor_hall
pm_1_0:
name: "Particulate Matter <1.0µm Concentration"
id: pmsx003_pm_1_0
pm_2_5:
name: "Particulate Matter <2.5µm Concentration"
id: pmsx003_pm_2_5
pm_10_0:
name: "Particulate Matter <10.0µm Concentration"
id: pmsx003_pm_10_0
update_interval: 100s
# Adicionar um sensor para exibir o AQI
- platform: template
name: "Air Quality Index"
id: aqi_display
unit_of_measurement: "AQI"
lambda: |-
// Obter as concentrações de partículas
float pm1_0 = id(pmsx003_pm_1_0).state;
float pm2_5 = id(pmsx003_pm_2_5).state;
float pm10_0 = id(pmsx003_pm_10_0).state;
int aqi = 0;
// Calcular o AQI com base nas três partículas
// Podemos usar a média ou a maior concentração
// Aqui estamos pegando o maior valor entre PM 1.0, PM 2.5 e PM 10.0 para determinar o AQI
float max_pm = std::max(std::max(pm1_0, pm2_5), pm10_0);
// https://qualar.apambiente.pt/node/metodo-calculo-indices & https://atmotube.com/blog/particulate-matter-pm-levels-and-aqi
// Classificação PM1 PM2.5 PM10 Cor Indice
// Muito Bom 0-10 0-10 0 - 20 Verde 0 - 50
// Bom 11-20 11-20 21 - 40 Amarelo 51 - 100
// Médio 21-25 21-25 41 - 50 Laranja 101 - 150
// Fraco 26-50 26-50 51 - 100 Vermelho 150 - 300
// Mau 51-800 51-800 101 - 150 Roxo 301 - 2800
// PM 1µ partículas caem na categoria das PM 2,5µ e os efeitos no corpo humano são semelhantes:
// https://www.iqair.com/us/newsroom/pm1
if (max_pm <= 12) {
aqi = (max_pm / 12) * 50;
} else if (max_pm <= 35.4) {
aqi = 51 + ((max_pm - 12) / 23.4) * 49;
} else if (max_pm <= 55.4) {
aqi = 101 + ((max_pm - 35.4) / 20) * 49;
} else if (max_pm <= 150.4) {
aqi = 151 + ((max_pm - 55.4) / 95) * 149;
} else if (max_pm <= 250.4) {
aqi = 301 + ((max_pm - 150.4) / 100) * 199;
} else if (max_pm <= 350.4) {
aqi = 501 + ((max_pm - 250.4) / 100) * 249;
} else {
aqi = 3000;
}
// Exibir o AQI no log
ESP_LOGI("AQI", "AQI Calculado: %d", aqi);
return aqi;
on_value:
then:
- lambda: |-
id(aqi) = (int)x;
- script.execute: LED_control
- platform: wifi_signal
name: ${friendly_name} WiFi Signal Strength
update_interval: 60s
- platform: uptime
name: ${friendly_name} Uptime
binary_sensor:
- platform: status
name: ${friendly_name}
# Scripts
# source: community.home-assistant.io/t/air-quality-measurement-sensor-with-esphome/276445/31
# https://community.home-assistant.io/t/how-to-change-ws2812b-led-colour-based-on-sensor-values/699219/14
script:
- id: LED_control
mode: single
then:
- logger.log: "Script LED_control executado"
- logger.log:
format: "pm1=%.1f pm2.5=%.1f pm10=%.1f AQI=%d"
args: [id(pmsx003_pm_1_0).state, id(pmsx003_pm_2_5).state, id(pmsx003_pm_10_0).state, id(aqi)]
- if: # Condição para pm1
condition:
- lambda: return id(pmsx003_pm_1_0).state < 10;
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 0
range_to: 1
red: 0%
green: 100% #verde
blue: 0%
- logger.log: "pm1 < 10µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_1_0).state >= 11.0) & (id(pmsx003_pm_1_0).state <20.));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 0
range_to: 1
red: 100%
green: 100% #amarelo
blue: 0%
- logger.log: "pm1 > 11 < 20µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_1_0).state >= 21) & (id(pmsx003_pm_1_0).state < 25));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 0
range_to: 1
red: 100%
green: 60% # laranja
blue: 0%
- logger.log: "pm1 > 21 < 25µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_1_0).state >= 26) & (id(pmsx003_pm_1_0).state < 50));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 0
range_to: 1
red: 100%
green: 0% #vermelho
blue: 0%
- logger.log: "pm1 > 26 < 50µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_1_0).state >= 51) & (id(pmsx003_pm_1_0).state < 800));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 0
range_to: 1
red: 25%
green: 0% #roxo
blue: 25%
- logger.log: "pm1 > 51 < 800µg/m3"
- if: # condição para pm2,5
condition:
- lambda: return id(pmsx003_pm_2_5).state < 10;
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 1
range_to: 2
red: 0%
green: 100% #verde
blue: 0%
- logger.log: "pm2.5 < 10µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_2_5).state >= 11) & (id(pmsx003_pm_2_5).state < 20));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 1
range_to: 2
red: 100%
green: 100% #amarelo
blue: 0%
- logger.log: "pm2.5 > 11 < 20µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_2_5).state >= 21) & (id(pmsx003_pm_2_5).state < 25));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 1
range_to: 2
red: 100%
green: 60% # laranja
blue: 0%
- logger.log: "pm2.5 > 21 < 25µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_2_5).state >= 26) & (id(pmsx003_pm_2_5).state < 50));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 1
range_to: 2
red: 100%
green: 0% #vermelho
blue: 0%
- logger.log: "pm2.5 > 26 < 50µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_2_5).state >= 51) & (id(pmsx003_pm_2_5).state < 800));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 1
range_to: 2
red: 25%
green: 0% #roxo
blue: 25%
- logger.log: "pm2.5 > 51 < 800µg/m3"
- if: # condição para pm10
condition:
- lambda: return id(pmsx003_pm_10_0).state < 20;
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 2
range_to: 3
red: 0%
green: 100% #verde
blue: 0%
- logger.log: "pm10 < 20µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_10_0).state >= 21) & (id(pmsx003_pm_10_0).state < 40));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 2
range_to: 3
red: 100%
green: 100% #amarelo
blue: 0%
- logger.log: "pm10 > 21 < 40µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_10_0).state >= 41) & (id(pmsx003_pm_10_0).state < 50));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 2
range_to: 3
red: 100%
green: 60% # laranja
blue: 0%
- logger.log: "pm10 > 41 < 50µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_10_0).state >= 51) & (id(pmsx003_pm_10_0).state < 100));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 2
range_to: 3
red: 100%
green: 0% #vermelho
blue: 0%
- logger.log: "pm10 > 51 < 100µg/m3"
- if:
condition:
- lambda: return ((id(pmsx003_pm_10_0).state >= 101) & (id(pmsx003_pm_10_0).state < 150));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 2
range_to: 3
red: 25%
green: 0% #roxo
blue: 25%
- logger.log: "pm10 > 101 < 150µg/m3"
- if: # condição para Indice AQI
condition:
- lambda: return id(aqi) < 50;
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 3
range_to: 4
red: 0%
green: 100% #verde
blue: 0%
- logger.log: "AQI - Muito Bom"
- if:
condition:
- lambda: return ((id(aqi) >= 51) & (id(aqi) < 100));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 3
range_to: 4
red: 100%
green: 100% #amarelo
blue: 0%
- logger.log: "AQI - Bom"
- if:
condition:
- lambda: return ((id(aqi) >= 101) & (id(aqi) < 150));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 3
range_to: 4
red: 100%
green: 60% # laranja
blue: 0%
- logger.log: "AQI - Médio"
- if:
condition:
- lambda: return ((id(aqi) >= 151) & (id(aqi) < 300));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 3
range_to: 4
red: 100%
green: 0% #vermelho
blue: 0%
- logger.log: "AQI - Fraco"
- if:
condition:
- lambda: return ((id(aqi) >= 301) & (id(aqi) < 2800));
then:
- light.turn_on:
id: Particle_Matter_Indicator
brightness: 20%
- light.addressable_set:
id: Particle_Matter_Indicator
range_from: 3
range_to: 4
red: 25%
green: 0% #roxo
blue: 25%
- logger.log: "AQI - Mau"
English’s not my native language, so sorry for the erratas!
Thanks