Skip to content

Instantly share code, notes, and snippets.

@gretel
Last active June 8, 2024 18:35
Show Gist options
  • Save gretel/3add6f08774f930ef0eaff03b847db64 to your computer and use it in GitHub Desktop.
Save gretel/3add6f08774f930ef0eaff03b847db64 to your computer and use it in GitHub Desktop.
esphome (wemos d1 mini) sensor phalanx (temperature, humidity, iaq, particles) including a custom component for the waveshare dust sensor (GP2Y1010AU0F)
# https://gist.github.com/gretel/3add6f08774f930ef0eaff03b847db64
substitutions:
devicename: 'dusty'
upper_devicename: 'Dusty'
logger_level: INFO
esphome:
name: ${devicename}
platform: ESP8266
#arduino_version: dev
board: d1_mini
on_shutdown:
then:
- logger.log: shutting down!
includes:
- GP2Y1010AU0F.h
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
domain: '.jitter.local'
fast_connect: on
ap:
ssid: "Node${upper_devicename}"
password: !secret ap_pass
# over-the-air updates
ota:
logger:
level: ${logger_level}
#esp8266_store_log_strings_in_flash: False
status_led:
pin:
number: D4
inverted: true
# homeassistant
api:
web_server:
port: 80
text_sensor:
- platform: version
name: "${upper_devicename} Version"
icon: "mdi:exponent-box"
- platform: wifi_info
ip_address:
name: "${upper_devicename} IP Address"
icon: "mdi:counter"
- platform: bme680_bsec
iaq_accuracy:
name: "${upper_devicename} IAQ Accuracy"
icon: "mdi:gradient"
i2c:
sda: D1
scl: D2
scan: False
output:
- platform: gpio
pin: D6
id: gpio_fan
switch:
- platform: restart
name: "${upper_devicename} Restart"
icon: "mdi:restart"
- platform: output
id: sensor_fan
name: "${upper_devicename} Fan"
output: gpio_fan
# script:
# - id: fan_interval_script
# mode: restart
# then:
# - fan.turn_on: sensor_fan
# - delay: 5s
# - fan.turn_off: sensor_fan
interval:
- interval: 1min
then:
- logger.log: "Interval"
- switch.toggle: sensor_fan
- delay: 5s
- switch.turn_off: sensor_fan
binary_sensor:
- platform: status
name: "${upper_devicename} Status"
time:
- platform: homeassistant
id: homeassistant_time
# https://github.com/trvrnrth/esphome-bsec-bme680
# https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/Explanation-on-static-IAQ-breath-VOC-and-CO2-equivalent/td-p/7413
bme680_bsec:
address: 0x77
#temperature_offset: 0.5
#iaq_mode: mobile
state_save_interval: 4h
sensor:
- platform: uptime
name: "${upper_devicename} Uptime"
update_interval: 5s
icon: "mdi:clock-start"
- platform: wifi_signal
name: "${upper_devicename} WiFi Signal"
update_interval: 30s
icon: "mdi:wifi"
# filters:
# - median:
- platform: bme680_bsec
temperature:
id: bme_tmp
name: "${upper_devicename} Temperature"
icon: "mdi:temperature-celsius"
# filters:
# - median:
humidity:
id: bme_hum
name: "${upper_devicename} Humidity"
icon: "mdi:water-percent"
# filters:
# - median:
pressure:
id: bme_prs
name: "${upper_devicename} Pressure"
icon: "mdi:arrow-collapse-all"
internal: True
# filters:
# - median:
gas_resistance:
id: bme_gas
name: "${upper_devicename} Gas Resistance"
icon: "mdi:gas-cylinder"
# filters:
# - median:
co2_equivalent:
id: bme_co2_equiv
name: "${upper_devicename} CO2 Equivalent"
icon: "mdi:home-outline"
# filters:
# - median:
breath_voc_equivalent:
id: bme_voc_equiv
name: "${upper_devicename} Breath VOC Equivalent"
icon: "mdi:human"
# filters:
# - median:
iaq:
id: bme_iaq
name: "${upper_devicename} IAQ"
icon: "mdi:biohazard"
# filters:
# - median:
iaq_accuracy:
id: bme_iaq_accuracy
# IAQ accuracy as a numeric value of 0, 1, 2, 3
name: "${upper_devicename} IAQ Numeric Accuracy"
icon: "mdi:gradient"
# - platform: template
# name: "${upper_devicename} Altitude"
# lambda: |-
# const float STANDARD_SEA_LEVEL_PRESSURE = 1013.25; // hPa
# return ((id(bme_tmp).state + 273.15) / 0.0065) *
# (powf((STANDARD_SEA_LEVEL_PRESSURE / id(bme_prs).state), 0.190234) - 1); // meter
# update_interval: 60s
# icon: 'mdi:signal'
# unit_of_measurement: 'm'
- platform: template
id: "iaq_percentual"
name: "${upper_devicename} IAQ Percentual"
lambda: |-
float x = (id(bme_iaq).state / 500) * 100;
auto call = id(led).turn_on();
call.set_transition_length(2000); // ms
if (x < 25) {
call.set_brightness(0.2);
call.set_rgb(0.0, 1.0, 0.0);
} else if (x < 50) {
call.set_rgb(0.6, 0.4, 0.0);
call.set_brightness(0.4);
} else {
call.set_rgb(1.0, 0.0, 0.0);
call.set_brightness(0.6);
}
call.perform();
return x;
update_interval: 10s
unit_of_measurement: '%'
- platform: template
name: "${upper_devicename} Pressure Equivalent Sea Level"
lambda: |-
const float STANDARD_ALTITUDE = 20.0; // in meters, see note
return id(bme_prs).state / powf(1 - ((0.0065 * STANDARD_ALTITUDE) /
(id(bme_tmp).state + (0.0065 * STANDARD_ALTITUDE) + 273.15)), 5.257); // in hPa
update_interval: 60s
unit_of_measurement: 'hPa'
icon: 'mdi:waves'
- platform: template
name: "${upper_devicename} Absolute Humidity"
lambda: |-
const float mw = 18.01534; // molar mass of water g/mol
const float r = 8.31447215; // universal gas constant J/mol/K
return (6.112 * powf(2.718281828, (17.67 * id(bme_tmp).state) /
(id(bme_tmp).state + 243.5)) * id(bme_hum).state * mw) /
((273.15 + id(bme_tmp).state) * r); // in grams/m^3
accuracy_decimals: 2
update_interval: 15s
unit_of_measurement: 'g/m³'
icon: 'mdi:water'
- platform: template
name: "${upper_devicename} Dew Point"
lambda: return (243.5*(log(id(bme_hum).state/100)+((17.67*id(bme_tmp).state)/(243.5+id(bme_tmp).state)))/(17.67-log(id(bme_hum).state/100)-((17.67*id(bme_tmp).state)/(243.5+id(bme_tmp).state))));
unit_of_measurement: °C
update_interval: 15s
icon: 'mdi:thermometer-alert'
- platform: custom
lambda: |-
auto dust_sensor = new GP2Y1010AU0FCustomSensor();
App.register_component(dust_sensor);
return {dust_sensor};
sensors:
- name: "${upper_devicename} Dust Sensor"
id: smog
accuracy_decimals: 2
unit_of_measurement: "µg/m³"
icon: "mdi:smog"
filters:
- median:
light:
- platform: fastled_clockless
name: "${upper_devicename} LED"
id: led
chipset: WS2811
pin: D7
num_leds: 1
rgb_order: GRB
restore_mode: ALWAYS_OFF
max_refresh_rate: 16ms
internal: True
// https://gist.github.com/gretel/3add6f08774f930ef0eaff03b847db64
#include "esphome.h"
static const char *const TAG = "GP2Y1010AU0F.sensor";
// measure while the sensor is running
#define VOLTAGE_VREF 4.62
#define PIN_ADC 5
#define PIN_EMT 6
class GP2Y1010AU0FCustomSensor : public PollingComponent, public Sensor
{
public:
GP2Y1010AU0FCustomSensor() : PollingComponent(15000) {}
float get_setup_priority() const override { return esphome::setup_priority::DATA; }
void setup() override
{
ESP_LOGCONFIG(TAG, "Setting up sensor");
pinMode(PIN_EMT, OUTPUT); // emitter
pinMode(PIN_ADC, INPUT); // sensor
}
void update() override
{
float value = 0;
float voltage = 0;
float density = 0;
// enable led in sensor
// !! the waveshare board does invert logic
digitalWrite(PIN_EMT, HIGH);
delayMicroseconds(280);
// measure voltage
value = analogRead(PIN_ADC);
delayMicroseconds(40);
// led off
// !! the waveshare board does invert logic
digitalWrite(PIN_EMT, LOW);
// caluclate voltage
voltage = value * (VOLTAGE_VREF / 1024.0);
// datashet specifies voltage range of 3.4V so anything above is faulty
if(voltage < 3.5)
{
// for calibration
ESP_LOGCONFIG(TAG, "Measurement done, VRef: %f, ADC Value: %f, Calculated Voltage: %f", VOLTAGE_VREF, value, voltage);
// taken from https://www.howmuchsnow.com/arduino/airquality/
publish_state(170 * voltage); // publish
} else {
ESP_LOGCONFIG(TAG, "Measurement out of bound, Calculated Voltage: %f", voltage);
}
}
};
wifi_ssid: 'T-Mobile'
wifi_pass: 'Lenis4223Penlarge?99ment'
ap_pass: 'WatchaWannaDo256Times'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment