Automation based on the value of a sensor in a given time

Hi everyone, these days I have been working on automating cooling fans based on the CPU temperature of the RPI4.
I created this automation which based on a certain temperature that I set with input_text as the minimum and maximum value increases or decreases the fan speed.
This is one of the automations:

  - alias: ventole_bassa_velocita_s1
    trigger:
      platform: state
      entity_id: sensor.cpu_temperature
    condition:
      condition: and
      conditions:  
        - condition: template
          value_template: >
            {{ trigger.to_state.state|float   >= states('input_text.velocita_bassa_sopra_s1')|float and 
               trigger.from_state.state|float <=  states('input_text.velocita_bassa_sotto_s1')|float }}
        - condition: state
          entity_id: input_boolean.attivazione_automazione_s1
          state: 'on'
        - condition: state
          entity_id: input_boolean.bassa_velocita_s1
          state: 'off'
    action:
    - service: light.turn_on
      data:
        entity_id: light.tutte_le_ventole_s1
        brightness: 255
    - delay: 00:00:05
    - service: light.turn_on
      data_template:
        {"brightness": "{{ states('input_number.velocita_bassa_s1')|int }}","entity_id": "light.tutte_le_ventole_s1"}
    - service: input_boolean.turn_on
      entity_id: input_boolean.bassa_velocita_s1
    - service: input_boolean.turn_off
      entity_id:
        - input_boolean.ventole_spente_s1
        - input_boolean.media_velocita_s1
        - input_boolean.alta_velocita_s1

It all works only that by doing tests I realized that many times the CPU temperature exceeds the set parameters for a few seconds and the speed changes very often.

My goal is that if the minimum and maximum CPU temperature

        - condition: template
          value_template: >
            {{ trigger.to_state.state|float   >= states('input_text.velocita_bassa_sopra_s1')|float and 
               trigger.from_state.state|float <=  states('input_text.velocita_bassa_sotto_s1')|float }}

it goes back in those values for 5 minutes then everything starts without being instantaneous.
how can i do it? thanks

From what you’ve said you’d like to control the speed but the code you’ve shown doesn’t seem to do that.
You need to clarify in your own head what you see happening and what you think the response should be.

I’d go with a set temperature and bands.
I’d test every 2mins (set for 1min during setup)
If at set temp and within band 1, leave speed alone
If outside band 1 inc/dec speed by 3/255 (tweak this as you experiment)
That ‘should’ be sufficient as the thermal lag and inertia are things you need to relax into. But you ‘could’ introduce another band with inc/dec of (say) 6/255

For my rack fan control I use two automations. One for on, one for off. That way I can set a for: value in the trigger template.

to control the fans that cool the RPI I used a Shelly RGBW2 based on the dimmer value the 12v fans run faster or slower and this is the code that start them:

    action:
    - service: light.turn_on
      data:
        entity_id: light.tutte_le_ventole_s1
        brightness: 255
    - delay: 00:00:05
    - service: light.turn_on
      data_template:
        {"brightness": "{{ states('input_number.velocita_media_s1')|int }}","entity_id": "light.tutte_le_ventole_s1"}

i should just add in this template:

        - condition: template
          value_template: >
            {{ trigger.to_state.state|float   >= states('input_text.velocita_media_sopra_s1')|float and 
               trigger.from_state.state|float <=  states('input_text.velocita_media_sotto_s1')|float }}

something like

      conditions:  
        - condition: template
          value_template: >
            {{ trigger.to_state.state|float   >= states('input_text.velocita_media_sopra_s1')|float and 
               trigger.from_state.state|float <=  states('input_text.velocita_media_sotto_s1')|float }}
          for: 5 minutes

but I don’t know how to write it

This might help:

- id: rack_fan_on
  alias: 'Rack Fan On'
  initial_state: true
  trigger:
  - platform: template
    value_template: "{{ states('sensor.cpu_temperature')|float >= states('input_number.rack_fan_on_temp')|int }}"
    for:
      minutes: "{{ states('input_number.rack_fan_dwell_time')|int }}"
  action:
  - service: switch.turn_on
    entity_id: switch.rack_fan
  - service: notify.telegram_system
    data_template:
      title: '*Information*'
      message: "Rack fan turned on. CPU temperature is {{ states('sensor.cpu_temperature')|float }}°C."

- id: rack_fan_off
  alias: 'Rack Fan Off'
  initial_state: true
  trigger:
  - platform: template
    value_template: "{{ states('sensor.cpu_temperature')|float <= states('input_number.rack_fan_off_temp')|int }}"
    for:
      minutes: "{{ states('input_number.rack_fan_dwell_time')|int }}"
  action:
  - service: switch.turn_off
    entity_id: switch.rack_fan
  - service: notify.telegram_system
    data_template:
      title: '*Information*'
      message: "Rack fan turned off. CPU temperature is {{ states('sensor.cpu_temperature')|float }}°C."

Thank you so much Tom, taking a cue from your configuration, I think something for me can work …

    trigger:
    - platform: template
      value_template: >
        {{ states('sensor.cpu_temperature')|float >= states('input_text.velocita_bassa_sopra_s1')|int and
           states('sensor.cpu_temperature')|float <= states('input_text.velocita_bassa_sotto_s1')|int}}
      for:
        minutes: 5

the HA check doesn’t bother me … I see if it works

Don’t have two equal comparators (it’s just bad practice)
‘>=’ and ‘<=’

better this way?

    - platform: template
      value_template: >
        {{ states('sensor.cpu_temperature')|float > states('input_text.velocita_bassa_sopra_s1')|int and
           states('sensor.cpu_temperature')|float < states('input_text.velocita_bassa_sotto_s1')|int }}

Sorry, I’ve just re-read this.
How can a value (cpu temp) be both greater than x AND less than x ?

I’d go with something like : -

    - platform: template
      value_template: >
        {{ states('sensor.cpu_temperature')|float > states('input_text.velocita_bassa_sopra_s1')|int+1 or
           states('sensor.cpu_temperature')|float < states('input_text.velocita_bassa_sotto_s1')|int-1 }}

practically it is a temperature range ie

if the CPU of the RPI marks 50 degrees and the temperature range is set between a minimum value of 40 degrees and a maximum of 60 degrees then the fans start in slow mode

if the CPU of the RPI marks 70 degrees and the temperature range is set between the minimum value 61 degrees and the maximum 80 degrees then the fans start in fast mode

Okay but you just want the result of this to be true or false (representing fast or slow) ?
So which way round is it ? And write the logic with just the one limit

They’re two seperate input texts Mutt. Look closer. The original template he has is fine.

Ah !
Stupid me.
They looked similar and I didn’t comprehend them so ‘ASSumed’

My apologies !

:blush:

1 Like

I just ran the tests and everything works correctly.
This is how it looks on Lovelace

Thanks again!!