I have created a control for a two speed, whole house fan based on the fan template and python scripts. Further down, you will see I need a little help with the “speed_template” for the fan, I can’t get this to compile
The fan is a two-speed fan which has neutral and then two active wires. Energize red and its low speed, energize black for high speed. But do not energize both at the same time! The fan is pretty big, the motor plate reports 6.5A on hi and 3.7A on Lo.
I wanted a hardware solution to prevent energizing both speed wires at the same time. I did not want to rely on a software protocol to overcome an unsafe hardware arrangement (cite Boeing Max 8).
So I have Aeotec Heavy Duty Switch as the master on/off. I chose this to handle the large inductive load. Smaller “lighting” switches appear to have the current rating but that is not for an inductive load (such as a motor).
Then I have an a Aeotec Nano switch + Digital Loggers AC Power Control Relay. The Nano switch controls the relay and the relay routes the active (from the Heavy Duty Switch) from its COMMON terminal to either NO or NC terminal. The NO / NC termainal then connect to red / black on the motor. Becasue the relay is SPDT its physically impossible to power the motor’s red and black wires at the same time.
=> Note I had some trouble with the Digital Logger’s relay. Its overload protection trips occasionally when the motor starts. So I disabled this protection, which I feel is safe given the Heavy Duty Switch before it (and the circuit breaker before that).
So here is my fan template from configuration.yaml
fan:
- platform: template
fans:
house_fan:
friendly_name : "House Fan"
value_template : "{{ states('switch.aeotec_zw078_heavy_duty_smart_switch_gen5_switch') }}"
# speed_template: "{{% if is_state('switch.aeotec_zw139_nano_switch_switch', "on") %}Hi{% else %}Lo{% endif %}}"
# speed_template: "{% if is_state('switch.aeotec_zw139_nano_switch_switch', "on") %}Hi{% else %}Lo{% endif %}"
turn_on:
service: python_script.house_fan_on
turn_off:
service: python_script.house_fan_off
set_speed:
service: python_script.house_fan_speed
data_template:
speed: "{{ speed }}"
speeds:
- 'Hi'
- 'Lo'
I cannot get either of the commented speed_template lines to work.
They always give me configuration errors, even though it works fine if I write them into the web engine’s template editor. Any help appreciated.
Then here are my python scripts.
There are two important things for the scripts to do.
- Before turning on the fan we must have adequate air flow. So I open two skylights (or at least ensure they are already open)
- The fan has louvers. They open with the airflow and they do not fully open if you start the fan on Lo. So I start the fan on high and then switch to low after a few seconds. The factory controller for the fan does this too.
python_scripts/house_fan_on.py
#
# Script to safely turn on the house fan
#
# Ensure there is adequate airlow
def adequate_airflow(hass, logger):
# Ensure the skylights are open
SkyWindow1 = hass.states.get('cover.skylight_1').attributes.copy()
SkyWindow1 = SkyWindow1.get('current_position')
SkyWindow2 = hass.states.get('cover.skylight_2').attributes.copy()
SkyWindow2 = SkyWindow2.get('current_position')
if (SkyWindow1 < 100 or SkyWindow2 < 100):
logger.info("Opening Skylight Windows to turn on House Fan")
hass.services.call('cover', 'open_cover', service_data={ 'entity_id': 'cover.skylight_1' })
hass.services.call('cover', 'open_cover', service_data={ 'entity_id': 'cover.skylight_2' })
# Skylights take around a minute to open / close
# This is a timeout set to 2-3x expected time
timeout = 180
while (timeout > 0) :
timeout = timeout - 1
SkyWindow1 = hass.states.get('cover.skylight_1').attributes.copy()
SkyWindow1 = SkyWindow1.get('current_position')
SkyWindow2 = hass.states.get('cover.skylight_2').attributes.copy()
SkyWindow2 = SkyWindow2.get('current_position')
if (SkyWindow1 < 100 or SkyWindow2 < 100) :
time.sleep(1)
else :
break
# Be really sure they are open before returning True
if (SkyWindow1 == 100 and SkyWindow2 == 100):
return True
else :
return False
# main
HouseFan = hass.states.get('switch.aeotec_zw078_heavy_duty_smart_switch_gen5_switch').state
Hi_Lo = hass.states.get('switch.aeotec_zw139_nano_switch_switch').state
if (HouseFan == "off") :
if (adequate_airflow(hass,logger)) :
# OK to turn on the house fan
# Ensure the fan always starts on Hi, so there is enough wind to full open louvers
hass.services.call('switch', 'turn_off', service_data={ 'entity_id': 'switch.aeotec_zw139_nano_switch_switch' })
time.sleep(1)
hass.services.call('switch', 'turn_on', service_data={ 'entity_id': 'switch.aeotec_zw078_heavy_duty_smart_switch_gen5_switch' })
# Fan Template will call set_seed automatically after this, just insert a little delay here
# So the fan can get up to full speed and open the louvers
time.sleep(3)
else :
logger.error("Failed to open Skylight Windows for whole house fan, aborting the command to turn on the fan")
I don’t quite understand why I need to pass hass and logger to the function adequare_airflow. I thought I could access global names within a function. Even defining hass and logger to be global within the function did not help
python_scripts/house_fan_off.py
#
# Turn off the house fan
#
# Turn off the fan
hass.services.call('switch', 'turn_off', service_data={ 'entity_id': 'switch.aeotec_zw078_heavy_duty_smart_switch_gen5_switch' })
# Set Hi/Lo to Hi speed
hass.services.call('switch', 'turn_off', service_data={ 'entity_id': 'switch.aeotec_zw139_nano_switch_switch' })
python_scripts/house_fan_speed.py
#
# Set the speed of the fan
#
speed = data.get('speed')
HouseFan = hass.states.get('switch.aeotec_zw078_heavy_duty_smart_switch_gen5_switch').state
# When switch is off==Hi speed, on==Lo speed
Hi_Lo = hass.states.get('switch.aeotec_zw139_nano_switch_switch').state
if (speed == "Hi"):
hass.services.call('switch', 'turn_off', service_data={ 'entity_id': 'switch.aeotec_zw139_nano_switch_switch' })
logger.info("Set house fan speed set to Hi")
elif (speed == "Lo"):
hass.services.call('switch', 'turn_on', service_data={ 'entity_id': 'switch.aeotec_zw139_nano_switch_switch' })
logger.info("Set house fan speed set to Lo")
So that’s it so far.
The Nano switch has two inputs S1 / S2. I have wired these to the old factory switch of the fan. This is actually a (proprietary) wireless switch. My thought was to detect S1/S2 and be able to write automations to pass on the commands. But its not obvious how to get the state of S1/S2 from the default state for the nano switch. I probably need to do some reading on the switch and the zwave integration of it.
Oh - The reason for all this is to fully automate the fan, skylights, and shades to minimize the use of the HVAC. This is a work in progress and I’ll post that when its a bit more mature.