Files
Bathroom_Fan.ESPHome/bathroom-fan.yaml
nc 593b6dee25 Update bathroom-fan.yaml
Update: 
 - Faster response to changes from HASS
 - Faster response to PIR detection
 - Few temperature updates sent to HASS
 - Better clamping and control of fan-speed
2025-10-28 19:35:56 +01:00

249 lines
7.6 KiB
YAML

substitutions:
deviceName: "Bathroom Fan"
deviceLowerCaseName: "bathroom-fan"
deviceComment: "ElectroDragon Extractor Fan"
# Onboard status LED
pinStatusLED: "10"
# The pins controlling the RGBW terminals
pinWhite: "04"
pinBlue: "05"
pinGreen: "06"
pinRed: "07"
# One pin can be switched to 5v out signalling, which we use for the Fan PWM signalling
pinWS28xx: "09"
# We need pins for: IR sensor, Fan RPM sensor, and i2c (SDA+SCL)
pinPIR: "01"
pinRPM: "03"
pinSDA: "02"
pinSCL: "08"
########################################################
## General setup of device, network etc ##
########################################################
esphome:
name: "${deviceLowerCaseName}"
friendly_name: "${deviceName}"
comment: "${deviceComment}"
esp32:
board: esp32-c3-devkitm-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret api_enckey
ota:
password: !secret ota_password
platform: esphome
wifi:
ssid: !secret wifi_ssid # Set your SSID in ESPHome's Secret file
password: !secret wifi_password # Set your WiFi password in ESPHome's Secret file
# Enable fallback hotspot (captive portal) in case wifi connection fails
# Note: ESP32-C3s can get stuck in boot-loop if this or captive_portal is removed (known issue)
ap:
ssid: "AP-${deviceName}"
password: "ESPHOME" # Consider changing this
captive_portal:
#####################################################
## Setup of Status Light ##
## Off when running, blinks in case or error ##
#####################################################
light:
- platform: status_led # Oboard status_led indicates errors/warnings during boot + operation
id: statusled
name: "Status LED"
pin: ${pinStatusLED}
disabled_by_default: True # No need to reflect in Home Assistant
#####################################################
## Setup of Fan ##
## ##
#####################################################
power_supply: # Optional control of fan to switch off power completely
- id: fanPower
pin: ${pinBlue}
output: # PMW control of fan using the LEDC platform
- platform: ledc
pin: ${pinWS28xx}
id: fanPin
power_supply: fanPower # Which pin to use to turn off Fan completely
frequency: 19531Hz # Higher frequency, but "only" 12-bit resolution (4096 gradiant steps)
fan: # Very basic fan with no oscilation etc control
- platform: speed
output: fanPin
#oscillation:
#direction_output:
speed_count: 100
name: "Extractor Fan"
id: Extractor
restore_mode: ALWAYS_ON # Default to turning on, to help with installation
icon: mdi:fan
#####################################################
## Setup of Sensors: ##
## Motion (IR), Humidity, Temperatur ##
#####################################################
# Need i2c bus to control the humidity+temperature sensor
i2c:
sda: ${pinSDA}
scl: ${pinSCL}
scan: true
id: bus_a
## PIR Sensor AM312
binary_sensor:
- platform: gpio
name: "Motion" # IR Presense detection, halves fan speed
id: pirSensor
pin:
number: ${pinPIR}
mode:
input: True
pulldown: True
device_class: motion
filters:
- delayed_off: 180s
on_state: # Update fan if Presence changes
then:
- script.execute: update_fan
sensor:
- platform: pulse_meter # Warning: Not been tested, TACHO impulses fried ESP32 somehow
name: "RPM"
id: rpmSensor
unit_of_measurement: 'RPM'
state_class: measurement
accuracy_decimals: 0
pin:
number: ${pinRPM}
inverted: true
mode:
input: true
pullup: true
filters:
- multiply: 0.5 # 2 impulses per rotation, /2 to get RPM
- throttle_average: 10s # Only update every 10 seconds
- filter_out: nan
- delta: 10% # And further reduce updates if change is small
- platform: sht3xd # Temp + Humidity sensor
address: 0x44
update_interval: 60s # Faster interval gives smoother fan speed changes, but also spams logs
temperature:
name: "Temperature" # We only use Temp for information. SHT3x uses it for Relative Humidity
id: temp
filters:
- delta: 0.6 # Don't react to every small change
humidity:
name: "Humidity"
id: humid
filters:
- clamp: # Clamp to get rid of bad readings
min_value: 0.1
max_value: 99.9
ignore_out_of_range: true
- delta: 1.0 # Don't react to every small change
on_value:
then:
- script.execute: update_fan
#####################################################
## Setup of Scripts ##
## "update_fan" - set fan speeds ##
#####################################################
script:
- id: update_fan
mode: single
then:
- lambda: |- # Lets call this every time we need to update
float cutoff = id(lowHumCutoff).state;
int humidity = id(humid).state;
// Doing linear transform here because we need the id(lowHumCutoff) variable
// Max is 100 at 80%
// Min is 25 at cutoff%
// linear equation y = mx + c
// = ((100-25) / (80 - $C$5)) * B8 + (100 - (((100-25) / (80 - $C$5))*80))
float speed = (75/(80-cutoff)) * humidity + (100-((75/ (80-cutoff))*80));
// Clamp between 20% and 100% duty-cycle
if( humidity <= cutoff )
speed = 20;
if( humidity >= 80)
speed = 100;
// Test if we need to go slow
if( id(quietModeSwitch).state || id(pirSensor).state )
speed = speed / 2;
// Turn the fan on and set the speed, or turn off
// Test for both cutoff, and minimum speed.
if( humidity >= cutoff && speed >= 10)
{
auto call = id(Extractor).turn_on();
call.set_speed(speed);
call.perform();
}
else
{
auto call = id(Extractor).turn_off();
call.perform();
}
#####################################################
## Setup of Home Assistant controls ##
## "Quiet Mode", "Low Humidity Cutoff" ##
#####################################################
switch:
- platform: template
name: "Quiet Mode" # Quiet Mode halves the fan-speed, similar to Presence Detection
id: quietModeSwitch
optimistic: True
# turn_on_action: # ToDo: Allow switch to control fan speed immediately via script
# - switch.turn_on: switch2
# turn_off_action:
# - switch.turn_on: switch1
on_state:
then:
- script.execute: update_fan # Update fan to reflect quiet-mode state
number:
- platform: template # Control in Home Assistant to set point where fan should turn off
id: lowHumCutoff
name: "Low Humidity Cutoff"
icon: mdi:waterpercent
disabled_by_default: True # User has to activate the control in the HASS UI
entity_category: ""
optimistic: True
min_value: 1
max_value: 100
step: 1
initial_value: 35 # 35% rel humidity is slightly high as low cutoff
restore_value: True
on_value:
then:
- script.execute: update_fan # Update fan to reflect new cut-off and range