Temperature control with DHT22

Hey there, I try to use a Wemos D1 mini to contol the temperature in a cabinet.
For this I use a DHT22 to get the temp and the PWM output to set the fans speed. As an addition I want to have an override switch, which turned on deactivate the automatic adjustment of the fan and let me adjust it by hand using a slider. All of this should run on the ESP directly so even when it cant reach HA it should be able to controll the temperature.
In this particular setup I got two identical fans on seperate PWM pins. I want to keep it that way so I can set them to different speed easier in the futer (for now they are doing the exact same thing).
I got it generally setup and the Hardware is doing its job and I am able to controll it with the slider, but after the startup of the ESP when it gives me the first measurements from my DHT it wont start the fans. could anyone help me figure out what I am doing wrong.

esphome:
  name: esphome-web-d04086
  friendly_name: Lueftung_Server

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxx"

ota:


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "xxx"
    password: "xxx"

captive_portal:
    
text_sensor:

  # Send IP Address                                                                                                                                                                                                                      
  - platform: wifi_info
    ip_address:
      name: $friendly_name IP Address

  # Send Uptime in raw seconds                                                                                                                                                                                                           
  - platform: template
    name: $friendly_name Uptime
    id: uptime_human
    icon: mdi:clock-start
    
sensor:

  # Send WiFi signal strength & uptime to HA                                                                                                                                                                                             
  - platform: wifi_signal
    name: $friendly_name WiFi Strength
    update_interval: 60s

  # RPM Signal from Fan                                                                                                                                                                                                                  
  - platform: pulse_counter
    pin:
      number: D4
      mode: INPUT_PULLUP
    name: Fan Speed 1
    id: fan_pulse_1
    unit_of_measurement: 'RPM'
    filters:
      - multiply: 0.5
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE
    update_interval: 30s

  - platform: pulse_counter
    pin:
      number: D3
      mode: INPUT_PULLUP
    name: Fan Speed 2
    id: fan_pulse_2
    unit_of_measurement: 'RPM'
    filters:
      - multiply: 0.5
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE
    update_interval: 30s

  - platform: dht
    pin: D6
    model: DHT22
    temperature:
      name: "Server Temperature"
      id: server_fan_temperature
      accuracy_decimals: 3
      on_value_range:
        - above: 25.0
          then:
            if:
              condition:
                and:
                  - fan.is_off: server_fan_toggle_1
                  - fan.is_off: server_fan_toggle_2
              then:
                - logger.log: "Set fan level 100 over 25C"
                - output.set_level:
                    id: server_luefter_1
                    level: 100%
                - output.set_level:
                    id: server_luefter_2
                    level: 100%
        - above: 20.0
          below: 25.0
          then:
            if:
              condition:
                and:
                  - fan.is_off: server_fan_toggle_1
                  - fan.is_off: server_fan_toggle_2
              then:
                - logger.log: "Set fan level 66 over 20C"
                - output.set_level:
                    id: server_luefter_1
                    level: 66%
                - output.set_level:
                    id: server_luefter_2
                    level: 66%
        - below: 20
          then:
            if:
              condition:
                and:
                  - fan.is_off: server_fan_toggle_1
                  - fan.is_off: server_fan_toggle_2
              then:
                - logger.log: "Set fan level 0 under 20C"
                - output.set_level:
                    id: server_luefter_1
                    level: 0%
                - output.set_level:
                    id: server_luefter_2
                    level: 0%

    humidity:
      name: "Humidity"
      id: rack_fan_humidity
                                                                                                                                                                                                          
    update_interval: 5s

  # This is a bit of overkill. It sends a human readable                                                                                                                                                                                 
  # uptime string                                                                                                                                                                                                                        
  # 1h 41m 32s instead of 6092 seconds                                                                                                                                                                                                   
  - platform: uptime
    name: $friendly_name Uptime
    id: uptime_sensor
    update_interval: 60s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human
            # Custom C++ code to generate the result                                                                                                                                                                                     
            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 ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (minutes ? to_string(minutes) + "m " : "") +
                (to_string(seconds) + "s")
              ).c_str();                                                                                                                                                                                                                 

output:
  # Wire this pin (15) into the PWM pin of your 12v fan                                                                                                                                                                                  
  # ledc is the name of the pwm output system on an esp32                                                                                                                                                                                
  - platform: esp8266_pwm
    id: server_luefter_1
    pin: D1
    frequency: "1000 Hz"                                                                                                                                                                              

  - platform: esp8266_pwm
    id: server_luefter_2
    pin: D2
    frequency: "1000 Hz"

fan:
  - platform: speed
    output: server_luefter_1
    name: Server LĂĽfter 1
    id: server_fan_toggle_1
    on_turn_on:
     - output.set_level:
          id: server_luefter_1
          level: !lambda |-
             return id(server_fan_1_speed_override).state/100.0;
    on_turn_off:
      - logger.log: "Power of Fan turned OFF"
      - delay: 1s
      - output.set_level:
          id: server_luefter_1
          level: !lambda |-
            if (id(server_fan_temperature).raw_state > 25){
              return 1;}
            else if (id(server_fan_temperature).raw_state > 20){
              return 0.66;}
            else
              return 0;

  - platform: speed
    output: server_luefter_2
    name: Server LĂĽfter 2
    id: server_fan_toggle_2
    on_turn_on:
     - output.set_level:
          id: server_luefter_2
          level: !lambda |-
             return id(server_fan_2_speed_override).state/100.0;
    on_turn_off:
      - logger.log: "Power of Fan turned OFF"
      - delay: 1s
      - output.set_level:
          id: server_luefter_2
          level: !lambda |-
            if (id(server_fan_temperature).raw_state > 25){
              return 1;}
            else if (id(server_fan_temperature).raw_state > 20){
              return 0.66;}
            else
              return 0;
          
number:
  - platform: template
    name: "Server Fan 1 Speed Override"
    id: server_fan_1_speed_override
    internal: false
    max_value: 100.0
    min_value: 0.0
    step: 33.3
    optimistic: true
    mode: slider
    on_value:
      then:
        if:
          condition:
            fan.is_on: server_fan_toggle_1
          then:
          - output.set_level:
              id: server_luefter_1
              level: !lambda "return x/100;"

  - platform: template
    name: "Server Fan 2 Speed Override"
    id: server_fan_2_speed_override
    internal: false
    max_value: 100.0
    min_value: 0.0
    step: 33.3
    optimistic: true
    mode: slider
    on_value:
      then:
        if:
          condition:
            fan.is_on: server_fan_toggle_2
          then:
          - output.set_level:
              id: server_luefter_2
              level: !lambda "return x/100;"

switch:
  # Expose an ESP restart button to HA                                                                                                                                                                                                 
  - platform: restart
    name: "Server Fan D1 Mini Restart"

on_value_range: only triggers when the sensor transitions from outside the ranges you test into the range. If the temp is already within the range on startup it won’t trigger.

If you want the action to happen on startup, use a simple on_value: and check for conditions rather than using the range.

1 Like

Ahhh okay, that makes totally sense!
Would there be an other way to use the temperature I get every 5 sec to update the fan?
For example I want to add a Lambda that also gets executet in the same intervall as the sensor reads its values, but everywhere I tryed to setup the Lambda I got an error. The Code inside the Lamda is something I’m able to figure out, but where and how do I add it?
I tried adding

- lambda: !lamda | -

inside the DHT but without success. Where would be the right place to put the Lambda?

The way you are doing it is fine - just on_value_range: is the issue.
So using conditions would look something like:

  - platform: dht
    pin: D6
    model: DHT22
    temperature:
      name: "Server Temperature"
      id: server_fan_temperature
      accuracy_decimals: 3
      on_value:
        - if:
            condition:
              lambda: |-
                return (x>25);
            then:
              if:
                condition:
                  and:
                    - fan.is_off: server_fan_toggle_1
                    - fan.is_off: server_fan_toggle_2
                then:
                  - logger.log: "Set fan level 100 over 25C"
                  - output.set_level:
                      id: server_luefter_1
                      level: 100%
                  - output.set_level:
                      id: server_luefter_2
                      level: 100%
        - if:
            condition:
              lambda: |-
                return (x>20 && x<=25);
            then:
              if:
                condition:
                  and:
                    - fan.is_off: server_fan_toggle_1
                    - fan.is_off: server_fan_toggle_2
                then:
                  - logger.log: "Set fan level 66 over 20C"
                  - output.set_level:
                      id: server_luefter_1
                      level: 66%
                  - output.set_level:
                      id: server_luefter_2
                      level: 66%
# ... etc

Indentation may be a bit off but I hope you get the idea. on_value: will execute every time the value changes (not every update, just when an update is different from the previous). You then check each condition to see what to do.

BYW the variable “x” always contains the value of the sensor your code is embedded in.

I mean instead of on_value_range or on_value.
Something like this:

- platform: dht
    pin: D6
    model: DHT22
    temperature:
      name: "Server Temperature"
      id: server_fan_temperature
      accuracy_decimals: 3
      lambda: | -
         #C++ Code that handles the conditions and everything
# ... etc

Reason for this would be to use lambda in more automations and I want to learn how to use it properly, although there are other/easier ways to do this.

Also thank you very much for your help, it is very appreciated. ^^

No - you can’t do this. Every action needs a trigger, such as on_value:

If you want to do something every 5 minutes you can add a time based trigger: