Best way to create dynamic fan speed adjustments in response to environmental conditions?

Here’s how I did it, in case this is useful for anyone else in the future:

This automation controls the fan speed relative to the temperature, you’ll need to set up a bunch of helpers, their names are in the code. I’ve set my fan up to be controlled by a numerical input value between 0-10


alias: Fan Temp Automation
description: ""
trigger:
  - platform: state
    entity_id: sensor.tasmota_am2301_temperature #Replace with your temerature sensor's entity ID 
  - platform: state
    entity_id: input_number.fan_min_speed #define all these helpers
  - platform: state
    entity_id: input_number.fan_max_speed
  - platform: state
    entity_id: input_number.fan_boost_increment #Each time the temperature increases beyond the set point by this value, The fan speed increases by the value of "fan_boost_amount"
  - platform: state
    entity_id: input_number.fan_boost_amount
  - platform: state
    entity_id: input_number.temperature_setpoint
  - platform: state
    entity_id:
      - input_number.humidity_setpoint
  - platform: state
    entity_id:
      - sensor.tasmota_am2301_humidity
  - platform: time_pattern
    seconds: /5
action:
  - service: number.set_value
    target:
      entity_id: number.fan_speed
    data:
      value: >
        {% set min_speed = states('input_number.fan_min_speed') | int %} 
        {% set max_speed = states('input_number.fan_max_speed') | int %}  
        {% set fan_boost_increment = states('input_number.fan_boost_increment') | float %} 
        {% set boost_amount = states('input_number.fan_boost_amount') | int %}
        {% set temp_threshold = states('input_number.temperature_setpoint') | int %} 
        {% set current_temp = states('sensor.tasmota_am2301_temperature') | int %}

        {% if current_temp <= temp_threshold %}
           {{ min_speed | int }}
        {% elif current_temp >= temp_threshold + (max_speed - min_speed) %}
           {{ max_speed | int }}
        {% else %}
           {% set speed_increase = ((current_temp - temp_threshold) / fan_boost_increment) | int %}
           {% set new_speed = min_speed + (speed_increase * boost_amount) | int %}
          {% if new_speed > max_speed %}
             {{ max_speed | int }}
          {% else %}
             {{ new_speed | int }}
           {% endif %}
        {% endif %}

This is a separate automation that controls the fan based on the humidity, It behaves the same way but instead uses the input from the humidity sensor and the value of the humidity set point helper.

alias: Fan Humidity Automation
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.tasmota_am2301_humidity
  - platform: state
    entity_id: input_number.fan_min_speed
  - platform: state
    entity_id: input_number.fan_max_speed
  - platform: state
    entity_id: input_number.fan_boost_increment
  - platform: state
    entity_id: input_number.fan_boost_amount
  - platform: state
    entity_id:
      - input_number.humidity_setpoint
  - platform: state
    entity_id:
      - sensor.tasmota_am2301_temperature
  - platform: state
    entity_id:
      - input_number.temperature_setpoint
  - platform: time_pattern
    seconds: /5
condition: []
action:
  - service: number.set_value
    target:
      entity_id: number.fan_speed
    data:
      value: >
        {% set min_speed = states('input_number.fan_min_speed') | int %} 
        {% set max_speed = states('input_number.fan_max_speed') | int %}  
        {% set fan_boost_increment = states('input_number.fan_boost_increment') | float %} 
        {% set boost_amount = states('input_number.fan_boost_amount') | int %}
        {% set humidity_threshold = states('input_number.humidity_setpoint') | int %} 
        {% set current_humidity = states('sensor.tasmota_am2301_humidity') | int %}

        {% if current_humidity <= humidity_threshold %}
           {{ min_speed | int }}
        {% elif current_humidity >= humidity_threshold + (max_speed - min_speed) %}
           {{ max_speed | int }}
        {% else %}
           {% set speed_increase = ((current_humidity - humidity_threshold) / fan_boost_increment) | int %}
           {% set new_speed = min_speed + (speed_increase * boost_amount) | int %}
          {% if new_speed > max_speed %}
             {{ max_speed | int }}
          {% else %}
             {{ new_speed | int }}
           {% endif %}
        {% endif %}

I wrote a third automation to prioritise control of the fan speed by the other 2 automations, based on which environmental condition is furthest away from it’s set point.

alias: Automation Priority Allocator
description: ""
trigger:
  - platform: state
    entity_id: sensor.tasmota_am2301_temperature
  - platform: state
    entity_id: sensor.tasmota_am2301_humidity
  - platform: state
    entity_id: input_number.fan_min_speed
  - platform: state
    entity_id: input_number.fan_max_speed
  - platform: state
    entity_id: input_number.fan_boost_increment
  - platform: state
    entity_id: input_number.fan_boost_amount
  - platform: state
    entity_id:
      - input_number.humidity_setpoint
  - platform: state
    entity_id:
      - input_number.temperature_setpoint
action:
  - service: automation.turn_on
    data_template:
      entity_id: >
        {% set temperature_deviation =
        states('sensor.tasmota_am2301_temperature') | float -
        states('input_number.temperature_setpoint') | float %}

        {% set humidity_deviation = states('sensor.tasmota_am2301_humidity') |
        float - states('input_number.humidity_setpoint') | float %}      

        {% if temperature_deviation > humidity_deviation %}
          automation.temp_fan_automation
        {% else %}
          automation.humidity_fan_automation
        {% endif %}
  - service: automation.turn_off
    data_template:
      entity_id: >
        {% set temperature_deviation =
        states('sensor.tasmota_am2301_temperature') | float -
        states('input_number.temperature_setpoint') | float %}

        {% set humidity_deviation = states('sensor.tasmota_am2301_humidity') |
        float - states('input_number.humidity_setpoint') | float %}

        {% if temperature_deviation > humidity_deviation %}
          automation.humidity_fan_automation
        {% else %}
          automation.temp_fan_automation
        {% endif %}
1 Like