Local control?

There activate the logger. What I notice is that when I switch from HA esphome detects the change in the variable. So with this I realize that the problem is HA and not esphome. Because when I restart HA, the variables remain with the default value, which is 28, and not with the last one that I modified. So I don’t know if when I restart HA I would have to ask esphome what the values ​​of the variables are or if it works in another way.

It occurs to me that perhaps instead of cobbling together a thermostat using scripts, you could implement an actual heater thermostat in ESPHome and expose it to Home Assistant as that rather than as relays.

climate:
  - platform: bang_bang
    name: "Fish Heater"
    icon: "mdi:fishbowl"
    sensor: temp
    default_target_temperature_low: 27.5 °C
    default_target_temperature_high: 28.5 °C
    visual:
      min_temperature: 20 °C
      max_temperature: 30 °C
      temperature_step: 0.1 °C
    heat_action:
      - switch.turn_on: relay_2
      - switch.turn_on: relay_3
    idle_action:
      - switch.turn_off: relay_2
      - switch.turn_off: relay_3

@Pablo_Gustavo_Fiscel If I understand correctly, it’s the reboot of the esphome node. The number resets to the default but that does not match the global value stored. Add this to the esphome: section of your config file.

esphome:
  # ...
  on_boot:
    priority: -100
    then:
      - number.set:
        id: temp_max_set
        value: !lambda 'return id(temp_max);'
      - number.set:
        id: temp_min_set
        value: !lambda 'return id(temp_min);'

@simondotau The problem with the thermostat is meeting the condition that it is, below/above the set point for 5 min before turning the heater on/off.

Would you know how fast the bang-bang thermostat kicks in? Is it instant or is there a delay?

The point is that a climate component is fit for purpose and gives you the right interface in Home Assistant. With bang_bang the actions are instantaneous, but if arbitrary delay is a requirement you can implement that as scripts in a similar way to how others have proposed.

I’m confused why you’d want the heater to run for an arbitrary five minutes after reaching the target instead of just setting the target slightly higher. You really ought to check your requirements because I’m quite sure a delay isn’t necessary. Just set your temperatures and allow hysteresis to do its thing.

If your temperature probe is noisy/unreliable, use filters to exclude spurious data.

The Thermostat Climate Controller — ESPHome has hysteresis and is probably better for this.

Thermostat supports combination heating-cooling systems but requires hysteresis to be hard-coded.

Bang_bang supports dynamically adjustable hysteresis points but only supports either heating or cooling. Given that the requirement is to control a heating element, it is more suited to this task.

1 Like

it was already discussed

That doesn’t matter. So long as the sensor is measuring the correct thing, it doesn’t matter if heat is injected into the water directly or from a distance. If anything, this would be reasonable justification for turning the heating off early rather than after a delay. It’s certainly not reasonable justification for adding more unnecessary delays to the thermostat operational cycle.

uff. I have a lot to read and to change. I think that implementing a climate is what best suits what I need and the code is smaller and more verbose. Thanks for the answers

If you wanted to maintain the temperature between 28.3 and 28.5, you should also activate the cooler and turn off the heater there, right? Because at low temperature it turns on the heater but then it is not turning it off. Now change the code and leave it like this but when I put a thermostat in UI, the maximum and minimum values ​​are 0.5 between them. I don’t know if what I’m doing is right.

climate:
  - platform: thermostat
    name: "Termostato acuario"
    sensor: temp
    default_target_temperature_low: 28.3 °C
    default_target_temperature_high: 28.5 °C
    min_cooling_off_time: 300s
    min_cooling_run_time: 300s
    min_heating_off_time: 300s
    min_heating_run_time: 300s    
    min_idle_time: 30s
    heat_deadband: 0.2
    cool_action:
      - switch.turn_off: relay_2
      - switch.turn_off: relay_3
    heat_action:
      - switch.turn_on: relay_2
      - switch.turn_on: relay_3
    idle_action:
      - switch.turn_off: relay_2
      - switch.turn_off: relay_3

Thermostat is more complicated to implement than bang_bang and its advantages are minimal if you don’t actually need the cooling integrated. You can have a second, separate bang_bang climate entity to automate your cooling fan.

If you do stick with thermostat, your off_time and run_time settings should be much shorter (e.g. 5s) as you are not operating a gas furnace or similar which has mechanical issues with short cycling. You’re using electric resistive heating, so short cycling is desirable. Allow hysteresis to do its thing.

You have set the default cooling and heating to be extremely close. I don’t know anything about fish but it seems unlikely that 0.2 degrees is the difference between freezing them and and boiling them. Plus it’s a ridiculous setting if you’re then going to force your heater to be on for an arbitrary five minutes.

Your cool action needs to switch off the heater, the heat action needs to switch off the cooler, and the idle action needs to switch off both.

Perfect. Thanks Friend. I am going to leave the firmware configured as a thermostat since it is more verbose.

Hello friends. I have a problem with the sensor. Unfortunately climate is what I was looking for but it didn’t always work. At times the temperature exceeded the limit and did not cut or did not turn on. I decided to go back to the old code that worked and the same thing is happening to me. Please. Someone help me to see what the problem is. I would really appreciate a little more help. Thank you

esphome:
  name: meteo

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  level: VERBOSE

# Enable Home Assistant API
api:

ota:
  password: "0664f60f6c5f7f8fe07e26bf0b9e1eac"

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

  ap:
    ssid: "meteo_ap"
    password: !secret wifi_password


captive_portal:
    
    
esp32_ble_tracker:

dallas:
  - pin: GPIO23

globals:
   - id: temp_max
     type: float
     restore_value: yes
     initial_value: '28.5'
   - id: temp_min
     type: float
     restore_value: yes
     initial_value: '28.3'
    
number:
   - platform: template
     name: "Set max temp"
     id: temp_max_set
     optimistic: true
     min_value: 28.0
     max_value: 29.0
     step: 0.1
     on_value:
       - globals.set:
           id: temp_max
           value: !lambda 'return id(temp_max_set).state;'
   - platform: template
     name: "Set min temp"
     id: temp_min_set
     optimistic: true
     min_value: 28.0
     max_value: 29.0
     step: 0.1
     on_value:
       - globals.set:
           id: temp_min
           value: !lambda 'return id(temp_min_set).state;'

binary_sensor:
   - platform: template
     name: maxs
     id: maxs
     lambda: |-
       if (id(temp).state >= id(temp_max)) {
         return true;
       } else {
         return false;
       }
     on_state:
       if:
         condition:
           for:
             time: 5min
             condition:
               binary_sensor.is_on: maxs
         then:
           - switch.turn_off: relay_2
           - switch.turn_off: relay_3
        
   - platform: template
     id: mins
     name: mins
     lambda: |-
       if (id(temp).state <= id(temp_min)) {
         return true;
       } else {
         return false;
       }
     on_state:
       if:
         condition:
           for:
             time: 5min
             condition:
               binary_sensor.is_on: mins
         then:
           - switch.turn_on: relay_2
           - switch.turn_on: relay_3          


#climate:
#  - platform: thermostat
#    name: "Termostato acuario"
#    sensor: temp
#    default_target_temperature_low: 28.3 °C
#    default_target_temperature_high: 28.5 °C
#    min_cooling_off_time: 90s
#    min_cooling_run_time: 90s
#    min_heating_off_time: 90s
#    min_heating_run_time: 90s    
#    min_idle_time: 30s
#    heat_deadband: 0.2
#    cool_action:
#      - switch.turn_off: relay_2
#      - switch.turn_off: relay_3
#    heat_action:
#      - switch.turn_on: relay_2
#      - switch.turn_on: relay_3
#    idle_action:
#      - switch.turn_off: relay_2
#      - switch.turn_off: relay_3

sensor:
  - platform: dallas
    address: 0x630516b54fc2ff28
    name: "Temperatura acuario_principal"
    id: temp
    filters:
      - offset: 1.0
  - platform: dht
    pin: GPIO33
    temperature:
      name: "Temperatura Comedor"
    humidity:
      name: "Humedad Comedor"
    update_interval: 60s   
  - platform: pvvx_mithermometer
    mac_address: "A4:C1:38:7B:D2:35"
    temperature:
      name: "Temperatura cuarto principal"
      accuracy_decimals: 1
    humidity:
      name: "Humedad cuarto principal"
      accuracy_decimals: 0
    battery_level:
      name: "Nivel de Bateria cuarto principal"

switch:
  - platform: gpio
    name: "Relay 1"
    pin: GPIO27
    inverted: true
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 2"
    id: relay_2
    pin: GPIO26
    inverted: true
    restore_mode: ALWAYS_OFF 
  - platform: gpio
    name: "Relay 3"
    id: relay_3
    pin: GPIO25
    inverted: true    
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 4"
    pin: GPIO5
    inverted: true
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 5"
    pin: GPIO18
    inverted: true
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 6"
    pin: GPIO19
    inverted: true    
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 7"
    pin: GPIO21
    inverted: true
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "Relay 8"
    id: relay_8
    pin: GPIO22
    inverted: true
    restore_mode: ALWAYS_OFF

the condition is fulfilled but it does not turn off the relays

Could it be an identification problem? It doesn’t make sense.

Has it been fulfilled for 5 minutes?

This worked fine like this. But I programmed it with a climate because the code was more verbose. The problem is that the climate did not always work and that is why I decided to go back to the initial code that with those 5 minutes worked well.

remove the 5 minute condition. It worked once so I’m going to wait a while to see how it goes