From 218941c2c519ff16d93de497053b4df43ceb1290 Mon Sep 17 00:00:00 2001 From: nc Date: Sat, 17 May 2025 10:24:06 +0200 Subject: [PATCH] Add bathroom-fan.yaml --- bathroom-fan.yaml | 231 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 bathroom-fan.yaml diff --git a/bathroom-fan.yaml b/bathroom-fan.yaml new file mode 100644 index 0000000..c427844 --- /dev/null +++ b/bathroom-fan.yaml @@ -0,0 +1,231 @@ +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 # ToDo: Call script to trigger immediately + pin: + number: ${pinPIR} + mode: + input: True + pulldown: True + device_class: motion + filters: + - delayed_off: 180s + +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 + 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: 2.0 # Don't react to every small change + on_value: + then: + if: + condition: + sensor.in_range: # We're always in range due to the Clamp above + id: humid + above: 0 + below: 100 + then: + - lambda: |- # ToDo: Convert to script and call it + float cutoff = id(lowHumCutoff).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)) * x + (100-((75/ (80-cutoff))*80)); + + // Clamp between 25 and 100 + if( x <= cutoff ) + speed = 25; + if( x >= 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 + if( x >= cutoff ) + { + 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 + +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