Weather regulator on ESPHome (esp12)

Hello everyone,

I am trying to build a weather regulator for a mixing valve (3-way) of water.

Components connected to ESP12:

  1. The regulator has two temperature sensors, one to measure the external temperature, the other to measure the water temperature behind the mixer.
  2. The regulator has two relays, one responsible for controlling the mixer in a clockwise direction, the other for controlling the mixer in a counter-clockwise direction.

Principle of operation:

  1. On the basis of the external temperature and the selected heating curve, the water temperature behind the mixing valve is calculated.
  2. The measured temperature behind the mixing valve is compared with the calculated temperature (point 1). If the measured temperature behind the valve is lower, then the relay switches on for a specified time, which opens the valve (CW). If the measured temperature behind the valve is higher, it activates the relay for a certain time, which closes the valve (CCW). Opening or closing is to take place at certain intervals for a certain period of time. For example, the relay is closed for 2s every 60s.

I wrote sample code in YML on ESPHome, but it doesn’t quite work as I want and I can’t do some things. All code below.

globals:
  - id: valveopening
    type: int
    restore_value: no
    initial_value: '0'
  - id: curve
    type: float
    restore_value: no
    initial_value: '0.4'
  - id: tmixer
    type: float
    restore_value: yes

dallas:
  pin: GPIO16
  update_interval: 10s

sensor:
  - platform: dallas
    address: 0xdb3c01e07607f328
    name: "Temp External"
    id: tempexternal

  - platform: dallas
    address: 0x183c01e076081428
    name: "Temp Mixer"
    id: tempmixer
  
  - platform: template
    name: "Temp Behind the Mixer"
    id: tempbehindmixer
    update_interval: 10s
    unit_of_measurement: "°C"
    accuracy_decimals: 0
    lambda: |-
      return static_cast<int>(id(tempmixer).state);

  - platform: template
    name: "Mix Temperature Set"
    id: mixtemperatureset
    lambda: |-
      int t_external = static_cast<int>(id(tempexternal).state);
      float t_mixer;
      t_mixer = id(curve) * ( 20 - t_external ) + 20;
      return static_cast<int>(t_mixer);
    update_interval: 10s
    accuracy_decimals: 0
    unit_of_measurement: "°C"

  - platform: template
    name: "Mixer Control"
    update_interval: 10s
    unit_of_measurement: "%"
    icon: mdi:valve
    lambda: |-
      if( id(tempbehindmixer).state < id(mixtemperatureset).state ){
        if(id(valveopening) >= 0 && id(valveopening) < 120){
          id(valveopening) = id(valveopening) + 2;
          id(cw).turn_on();
          delay(id(tmixer) * 1000);
          id(cw).turn_off();
        }
      }else if( id(tempbehindmixer).state > id(mixtemperatureset).state ){
        if(id(valveopening) <= 120 && id(valveopening) > 0){
          id(valveopening) = id(valveopening) - 2;
          id(ccw).turn_on();
          delay(id(tmixer) * 1000);
          id(ccw).turn_off();
          }
      }else id(valveopening) = id(valveopening);
      return id(valveopening);

switch:
  - platform: gpio
    name: "CW"
    pin: GPIO13
    id: cw
    inverted: True

  - platform: gpio
    name: "CCW"
    pin: GPIO12
    id: ccw
    inverted: True

number:
  - platform: template
    name: "Mixer Pulse Time"
    id: mixerpulsetime
    optimistic: True
    min_value: 0
    max_value: 20
    step: 0.5
    on_value:
      then:
        - globals.set:
            id: tmixer
            value: !lambda |-
                    return id(tmixer) = x;
    
  - platform: template
    name: "Mixer Pulse Period"
    id: mixerpulseperiod
    optimistic: True
    min_value: 20
    max_value: 120
    step: 0.5

  - platform: template
    name: "Heating Curve"
    id: heatingcurve
    optimistic: True
    min_value: 0.1
    max_value: 1
    step: 0.1

The code in the “Mixer Control” section works as I want and shows me the value of valve opening in %. But rather it must be included differently than in the sensor template, because in this case I can’t set the period at which the opening or closing of the valve should work. I am asking for hints on how to do it right, where to put the code so that it works independently. I hope you can do it in another simple way without writing code in C++ and take full advantage of ESPHome.

I have created a number template with which I will set the values I need and then they will be used in the code for calculations and setting the mixer. I know how to make this value from the number template go to the globals variable. I have an example done in “Mixer Pulse Time”. I still need these values to be saved in the ESP12 memory when the power supply is disconnected and then the number template values set to those values from the ESP12 memory that were set earlier. I try different settings but each time it either doesn’t work or ESP12 crashes.

Please help, advice and questions, I will describe the problem in detail.

Hello … I think this is quite involved. I have never found something works straight away; what is difficult to do is work out what is wrong right at the end!

I would break it down into bits and check the logs on the ESP Home dashboard for each section set up:

  • set up your sensors => check logs
  • set up relays => check logs and operate from HA
  • do some formulas and get them to turn out a value => check logs and read values from HA
  • start connect them all together one bit at a time => check logs at each stage

Somebody might know something but if you are on your own it becomes a bit of hunt down the component/ sensor / formula that is not working