I am currently working to build out a node utilizing three relays with interlocks to control a three speed fan from HASS. I haven’t wired it all up and tested yet.
What I am currently trying to figure out is how to utilize one momentary button switch as a binary sensor (unless there is a better route) to toggle between modes. i.e. If off, go low, if low go med, if med go high and if high go low by checking and determining which if any relays are on (utilizing interlock). Does anyone have any suggestions as to how to program the automation. Looking to do this onboard and not have the logic reliant on HASS.
After some time experimenting and then walking away and then trying again I have a solution.
I wanted a singular push button to toggle between states, however I was struggling with Lamda, so instead of each press moving to the next setting, I decided to use multi_click. A long press turns off the fan, and one to three quick presses turning it on and into the given fan mode. As I mostly use High, I went High, Med, Low for 1, 2, and 3 clicks respectively. See the code below.
esphome:
name: box_fan_one
platform: ESP8266
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
manual_ip:
static_ip: x.x.x.x
gateway: x.x.x.x
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Box Fan Fallback Hotspot"
password: !secret ap_fallback_pass
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
password: !secret api_pass
ota:
password: !secret ota_pass
substitutions: #for the name of the fan to input below
name: box_fan_one
binary_sensor:
- platform: gpio # For push button onboard
id: push_button
pin:
number: D2
mode: INPUT_PULLUP
on_multi_click:
- timing:
- ON for 1s to 3s
- OFF for at least 0.2s
then:
- logger.log: "Long Press"
- switch.turn_off: relay1
- switch.turn_off: relay2
- switch.turn_off: relay3
- timing:
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Single Press"
- switch.turn_on: relay1
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Double Press"
- switch.turn_on: relay2
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Triple Press"
- switch.turn_on: relay3
switch:
- platform: gpio
name: "${name}_High"
pin:
number: D5
inverted: True
icon: mdi:fan-speed-3
id: relay1
interlock: &interlock_group [relay1, relay2, relay3]
interlock_wait_time: 300ms
- platform: gpio
name: "${name}_Medium"
pin:
number: D6
inverted: True
icon: mdi:fan-speed-2
id: relay2
interlock: *interlock_group
interlock_wait_time: 300ms
- platform: gpio
name: "${name}_Low"
pin:
number: D7
inverted: True
icon: mdi:fan-speed-1
id: relay3
interlock: *interlock_group
interlock_wait_time: 300ms
This gave me the physical control I desired.
Next step is understanding the fan template to get this to be usable as a fan rather than three switch devices.
I hope this helps someone, if anyone has questions or improvements let me know!
Never was able to do it. Its theoretically possible to do using templating. I just have each of the fan speeds available on a single row on the dashboards that I need it. I primarily use button stations around the apartment so I didn’t end up needing to fuss with it as the 3 interlocking switches works fine.
This is spectacular, ty for sharing your code. I was able to incorporate it into my existing code to have a proper fan entity in HA. MUCH better than the three switches I had before. I also tweaked the code for the onboard button I have, now rather than triggering relays it uses the fan entity so it feeds back to HA properly. LMK if you see any glaring issues in the code but I am pleased to report that I think that this is (for now) the final stage of this project.
I don’t personally use the status sensor but I do have the RSSI and uptime (converted to human readable, don’t recall where I found that so I cant credit anyone) included as well.
esphome:
name: boxfanone
platform: ESP8266
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
manual_ip:
static_ip: x.x.x.x
gateway: x.x.x.x
subnet: 255.255.0.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Box Fan Fallback Hotspot"
password: !secret ap_fallback_pass
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
password: !secret api_pass
ota:
password: !secret ota_pass
substitutions: #for the name of the fan to input below
name: Bedroom Box Fan
binary_sensor:
- platform: gpio # For push button onboard
id: push_button
pin:
number: D2
mode: INPUT_PULLUP
on_multi_click:
- timing:
- ON for 1s to 3s
- OFF for at least 0.2s
then:
- logger.log: "Long Press"
- fan.turn_off:
id: bedroomboxfan
- timing:
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Single Press"
- fan.turn_on:
id: bedroomboxfan
speed: 3
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Double Press"
- fan.turn_on:
id: bedroomboxfan
speed: 2
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Triple Press"
- fan.turn_on:
id: bedroomboxfan
speed: 1
switch:
- platform: gpio
internal: true
name: "${name} High Relay"
pin:
number: D5
inverted: True
icon: mdi:fan-speed-3
id: relay3
interlock: &interlock_group [relay1, relay2, relay3]
interlock_wait_time: 300ms
- platform: gpio
name: "${name} Medium Relay"
internal: true
pin:
number: D6
inverted: True
icon: mdi:fan-speed-2
id: relay2
interlock: *interlock_group
interlock_wait_time: 300ms
- platform: gpio
name: "${name} Low Relay"
internal: true
pin:
number: D7
inverted: True
icon: mdi:fan-speed-1
id: relay1
interlock: *interlock_group
interlock_wait_time: 300ms
- platform: restart
name: "$name Restart"
output:
- platform: template
id: fan_1
type: float
write_action:
- if:
condition:
lambda: return ((state == 0));
then:
# action for off
- switch.turn_off: relay1
- switch.turn_off: relay2
- switch.turn_off: relay3
- if:
condition:
lambda: return ((state > 0) && (state < 0.4));
then:
# action for speed 1
- switch.turn_off: relay2
- switch.turn_off: relay3
- switch.turn_on: relay1
- if:
condition:
lambda: return ((state > 0.4) && (state < 0.7));
then:
# action for speed 2
- switch.turn_off: relay1
- switch.turn_off: relay3
- switch.turn_on: relay2
- if:
condition:
lambda: return ((state > 0.7));
then:
# action for speed 3
- switch.turn_off: relay1
- switch.turn_off: relay2
- switch.turn_on: relay3
fan:
- platform: speed
id: bedroomboxfan
output: fan_1
name: "Bedroom Box Fan"
speed_count: 3
text_sensor: #Human Readable Uptime
- platform: template
name: $name Uptime
id: uptime_human
icon: mdi:clock-start
sensor:
- platform: wifi_signal
name: "$name WiFi Signal"
update_interval: 60s
- platform: uptime #Uptime in Seconds
name: $name Uptime Sensor
id: uptime_sensor
update_interval: 60s
internal: True
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str();
Just a follow up on this fan project of mine, I have the fan working perfectly in HA but I really want to be able to use the 3 speed settings as per the old HA fan usage, not the stupid % based method.
Currently my fan seems to show both in HA, but I can only set it via %. As you can see below, the descriptive fan speeds are listed under ‘attributes’, but I can only seem to set it via %. I realise the fan speeds (descriptive) was deprecated (stupid decission)… but…
Is there any way to force the 3 speeds to be accessible as low, medium and high? (I have this for another fan running Tasmota and integrated over MQTT)
Thanks. I actually got it sorted out as described in my post above. The only thing I can’t figure out is how to select the fan speeds via the description (ie: off, low, med, high) in HA. Currently I have to use a slider to select the percentage steps. I have another fan which can be selected by descriptor but that’s running Tasmota, not ESPhome so this issue is taken care of in the HA MQTT fan code.
I am really curious if you built this out just because it was an interest project? There are a handful of devices across multiple protocols that already do this in a compact little unit that you shove into the fan wiring already. Don’t take my question as criticism, just curious.
At the time I didn’t really know about the solutions, and I found a project similar to this so I just decided to try and do it myself, really didn’t think about it past that. I’m glad I did though, learned a lot about ESPHome from this project.
Edit: Most everything I build for my smarthome is 1 part functionality and 2 parts, I wonder if I can do X.
The reasoning was because the fan I’m controlling is too powerful for the off-the-shelf devices. Unfortunately I found this out the hard way because I didn’t realise the fan controller I had wouldn’t handle my fan… it let the magic smoke out.
This fan controller I made can handle much larger / higher power fans.
Thanks for updating your code with the fan settings. This is working perfectly for me with a three relay board that I’ll put in a pedestal fan.
Can I ask as question - for the button, how did you wire that up? Do you also pull it low/high with a resistor to something as I’m seeing the button go on/off in the logs when I’m not touching anything.
Its been a long while since I have had the box open. You should be able wire it with a resistor to stop it from floating like that. Any button wiring you like should work.
Is there no other way to represent three states with one key? I have the same problem and find the solution on_multi_click not very attractive. I switch the fan via solid state relays but that doesn’t really matter. I am looking for a simple solution for automation…
Press button level 1
press button again level 2
press button again level 3
button again fan off
And then again from the beginning. I can’t find a solution myself.
Sorry, but I can only communicate in English through the translator. I would like to achieve the automation only via ESPHome. Everything else makes no sense for a fan. Would like to switch the part even if there is no network. Would be great if you had a solution for me.