ESPHome Relay On/Off Control with Adjustable setpoints from HA

I’m really struggling with the learning curve on this stuff. If this was a PLC, i’d be done in 5 seconds. If there’s a getting started lab book on writing custom code I’m not finding it.

I essentially have a device that will be triggered by a pressure sensor from i2c bus, but for now I’d just like to get it working with a gpio input. I’d like it to retain last entered setpoint values & not rely on HA automations or scripts.

On_Time_Setpoint INT Adjustable via HA
Off_Time_Setpoint INT Adjustable via HA

While Trigger == True
-set gpio == True
-wait On_Time_Sepoint
-set gpio == False
-wait Off_Time_Setpoint
loop

I appreciate you taking the time to help.

So what you want is for the ESP to use values from HA to know what the setpoints are, so read this. You can create input_numbers in HA and use those as outlined in the link. Then create the automation to control your GPIO in ESPhome on the device. It will still need a connection to HA to get those setpoints but the automation is done without HA.

No need to import input numbers form home assistant as sensors. Numbers can be created on the ESP device now. Template Number — ESPHome just don’t forget to set the restore_value to true or they reset after esp device restart.

Oh nice! So I take it the ESP will provide a service to HA where that value can be modified? (Yep)

EDIT: just read the rest of the linked page.

1 Like

Awesome! Thank you for the extra info. number: does exactly what I was hoping. Here’s where I’m currently stuck. The While loop logic is my current hangup. I don’t know where or how to add this. I’ve tried various methods of adding it under my spdx sensor but it always complains when using “on_value” you can’t have a while loop. I’ve also tried using on_state but that’s not a valid argument for a sensor.

Current working yaml

number:
  - platform: template
    id: diffuser_on_setpoint
    name: "Diffuser On Setpoint"
    optimistic: true
    min_value: 0.0
    max_value: 300.0
    step: 1.0
    initial_value: 30.0
    restore_value: true
    unit_of_measurement: seconds
  - platform: template
    name: "Diffuser Off Setpoint"
    optimistic: true
    min_value: 0.0
    max_value: 300.0
    step: 1.0
    initial_value: 30.0
    restore_value: true
    unit_of_measurement: seconds

sensor:
  - platform: sdp3x
    name: "HVAC Filter Pressure drop"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s

switch:
  - platform: gpio
    name: "Diffuser"
    pin: GPIO16
    id: relay

Section I want to run the automation but don’t know where to put or the correct on_…: notation.

 on_...:
      - while:
          condition:
          sensor.in_range:
          id: filter_pressure
          below: 10.0
          then:
          - logger.log: "Still executing"
          - switch.on: relay
          - delay:
            seconds: 'Diffuser On Setpoint'
          - switch.off: relay
          - delay:
            seconds: 'Diffuser Off Setpoint'

Are you quoting your yaml when posting? The indentation appears wrong - but it’s hard to tell. Use the “preformatted text” tags - shown as </> in the posting toolbar.

Yes, I was using the quotes. Indentation in code is correct.

Don’t quote, as zoogara said, use code </>; it is made for yaml :wink:

No, it isn’t… this is:

sensor:

  - platform: sdp3x
    name: “HVAC Filter Pressure drop”
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 10s

etcetc

please read 1.1 of how-to-ask-questions

The code was correct in my .yaml and not related to the issues I’m seeing was what I was referencing. I’ve edited my original coded post to fix the issue. Thank you for pointing out the errors of my ways.

1 Like

The automation goes in the sensor that would trigger the action - in an on_value: block or similar - - or if you want it checked at a regular interval then in a time block:

time:
  - platform: sntp
    # ...
    on_time:
      # Every 5 minutes
      - seconds: 0
        minutes: /5
        then:

That’s what I’m trying to figure out. Where do I put it and what notation of on_… I’ve tried something similar to these and all have various errors and won’t compile.

sensor:
  - platform: sdp3x
    name: "HVAC Filter Pressure drop"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s
    - while:
      condition:
        sensor.in_range:
        id: filter_pressure
        below: 10.0
      then:
      - logger.log: "Still executing"
      - switch.on: relay
      - delay:
        seconds: 'Diffuser On Setpoint'
      - switch.off: relay
      - delay:
        seconds: 'Diffuser Off Setpoint'
sensor:
  - platform: sdp3x
    name: "HVAC Filter Pressure drop"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s
    on_value:
      - while:
          condition:
           sensor.in_range:
            id: filter_pressure
            below: 10.0
          then:
          - logger.log: "Still executing"
          - switch.turn_on: relay
          - delay:
             seconds: 10
          - switch.turn_off: relay
          - delay:
             seconds: 10
sensor:
  - platform: sdp3x
    name: "HVAC Filter Pressure drop"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s
    on_value:
      - while:
          condition:
           sensor.in_range:
            below: 10.0
          then:
          - logger.log: "Still executing"
          - switch.turn_on: relay
          - delay:
             seconds: 10
          - switch.turn_off: relay
          - delay:
             seconds: 10

The last one looks like it should work - but you can’t imply the sensor id:

sensor:
  - platform: sdp3x
    name: "HVAC Filter Pressure drop"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s
    on_value:
      - while:
          condition:
           sensor.in_range:
            id: filter_pressure
            below: 10.0
          then:
          - logger.log: "Still executing"
          - switch.turn_on: relay
          - delay: 10s
          - switch.turn_off: relay
          - delay: 10s

Also I think the delay format you are using may be supported, but the docs use the above.

Trying that code gives the following error while editing the yaml.

Outside of the While: loop I’m trying, I was able to get seconds: to kind of work. I want the delays adjustable. I haven’t found a way to append the ‘s’ notation at the end of the number objects use in HA to adjust these delays.

The only thing i can see wrong is indentation…

shouldn’t that be 2 spaces below conditions, sensor and id?

And the id; filter_pressure, is it needed there?

Yaml doesn’t care how many spaces, just that indentation is present.

That said - yes 2 spaces is the defacto standard.

After talking with a few others via discord this has been sorted out. While my case is turning off and on a home scent diffuser triggered by static pressure differential, this same automation can be used for any scenario where an analog input is required to cycle an output on and off. Once I complete the final install I’ll post my hardware design and practical use case. I’m not too happy with the size of tubing on the differential pressure sensor so I’m looking at alternatives.

Functional description:

Examine analog static pressure differential sensor to determine if HVAC is running with a binary sensor object. As configured in included yaml "If differential pressure is greater than HVAC_running_setpoint, then HVAC is running. Using “HVAC running” binary sensor a script is triggered that WHILE TRUE turn relay on for XX Seconds (HA Adjustable via diffuser_on_setpoint) THEN turn relay off for XX Seconds (HA Adjustable via diffuser_off_setpoint)

Setpoints: (Rename as you see fit, located in the NUMBERS section of the yaml)

  • HVAC_running_setpoint: Used as the trigger to start the automation. Adjustable via HA rather than hard coded to make initial setup easier than multiple reflashes of esp32 device.

  • diffuser_on_setpoint: Used as the duration of the ON action trigger. Configured in seconds. Adjustable via HA.

  • diffuser_off_setpoint: Used as the duration of the OFF action trigger. Configured in seconds. Adjustable via HA.

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true
  frequency: 100kHz

number:
  - platform: template
    id: diffuser_on_setpoint
    name: "Diffuser On Setpoint"
    optimistic: true
    min_value: 0.0
    max_value: 300.0
    step: 1.0
    initial_value: 30.0
    restore_value: true
    unit_of_measurement: seconds
  - platform: template
    id: diffuser_off_setpoint
    name: "Diffuser Off Setpoint"
    optimistic: true
    min_value: 0.0
    max_value: 300.0
    step: 1.0
    initial_value: 30.0
    restore_value: true
    unit_of_measurement: seconds
  - platform: template
    id: HVAC_running_setpoint
    name: "HVAC Running Setpoint"
    optimistic: true
    min_value: -10.0
    max_value: 10.0
    step: 0.001
    initial_value: 0.015
    restore_value: true
    unit_of_measurement: hpa

sensor:
  - platform: sdp3x
    name: "HVAC Pressure"
    address: 0x21
    id: filter_pressure
    measurement_mode: differential_pressure
    update_interval: 5s
  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: "WiFi Signal dB"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"

binary_sensor:
  - platform: template
    name: "HVAC Running"
    id: HVAC_running
    lambda: return id(filter_pressure).state > id(HVAC_running_setpoint).state;
    on_press:
      - script.execute: run_diffuser

script:
  - id: run_diffuser
    mode: single
    then:
      - while:
          condition:
            binary_sensor.is_on: HVAC_running
          then:
            - switch.turn_on: relay
            - delay: !lambda return id(diffuser_on_setpoint).state * 1000;
            - switch.turn_off: relay
            - delay: !lambda return id(diffuser_off_setpoint).state * 1000;

switch:
  - platform: gpio
    pin: GPIO16
    name: relay
    id: relay