Work in progress! esphome thermostat

Hi all,

its been a while since Ive got into any home assistant project and my latest is in relation to understanding, designing, prototyping and building a EspHome based thermostat with a display.

So right out of the gate! I only have a small amount of experience with electronics, I’ve only ever built a few ‘mysensor’ devices and a few small ‘kit’ projects, but I’m not bad at soldering and my components have grown over the years and are in need of use, plus who doesn’t enjoy a project where you learn new things.

So I’ve started doing a little research about powering the device via 240v mains, which my current dumb thermostat is, but the switching has to be a dry contact that signals the heating to turn on (no voltage, or very very small voltage).

So to begin with I will test and prototype a base for my thermostat, based on this this tutorial from Random Nerd Tutorials mainly because it highlights some safety considerations and also because I have several Hi-Link HLK-PM01 modules from a previous project that used mains power before.
This coupled with prototyping a relay module similar to the cheap relay modules you can buy and are mentioned in the tutorial ( again mainly because I have spare songle relays from a previous project)
I would then attach a display, design the UI ( using EspHome) and have this control the thermostat, independent of home assistant just in case home assistant wasn’t available to control it for whatever reason.

finally I have a 3d printer I own and have printed a reasonable amount of projects over the years, so I guess I should add design and print a case for the finished thermostat to the list also

I know this sounds like a lot and it is, especially as a very early electronics hobby project, but I thought I would document my steps along the way and help others who are also interested. Hopefully I’ll also pick up advice from the community as I go along, to stream line and improve the project.

So to show where I currently am in the project (very early days, day 1 in fact) I started by connecting a ILI9341 touchscreen to an esp32 dev board and playing around with EspHome to design a simple UI so I can get to grips with some of the display rendering options and how the touchscreen works and is configured.

I have a few LED’s connected to simulate the relays toggling when the “buttons” on the display are pressed.

currently I have it setup that the backlight turns off after 10s and I have to touch to wake it , but I added an IF condition that I can only activate the buttons if the screen is on, not sure this is the best way to do it but it works at the moment

This is the current yaml for the device

esphome:
  name: thermostat-one
  friendly_name: thermostat-one

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  level: DEBUG
  logs:
    component: ERROR

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

ota:
  password: "**********************"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Thermostat-One Fallback Hotspot"
    password: "****************"

captive_portal:

spi:
  clk_pin: 18
  mosi_pin: 23
  miso_pin: 19

time:
  - platform: homeassistant
    id: my_time

font:
  - file: "fonts/Roboto-Regular.ttf"
    id: my_font
    size: 15

  - file: "fonts/Roboto-Regular.ttf"
    id: big_font
    size: 30

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: 5
    cs_pin: 33
    reset_pin: 16
    dimensions:
      height: 240
      width: 320
    transform:
      swap_xy: true 
      mirror_y: true
      mirror_x: true
    lambda: |-
      auto red = Color(255, 0, 0);
      auto green = Color(0, 255, 0);
      auto blue = Color(0, 0, 255);
      auto white = Color(255, 255, 255);
      it.filled_rectangle(20, 20, 100, 50, white);
      it.print(30, 30, id(my_font), COLOR_OFF, "PUSH HERE");
      it.filled_rectangle(200, 20, 100, 50, red);
      it.print(210, 30, id(my_font), white, "PUSH HERE");
      it.filled_rectangle(20, 150, 100, 50, green);
      it.print(30, 160, id(my_font), white,  "PUSH HERE");
      it.filled_rectangle(200, 150, 100, 50, blue);
      it.print(210, 160, id(my_font), white, "PUSH HERE");
      it.strftime(30, 90, id(big_font), "%Y-%m-%d %H:%M", id(my_time).now());

touchscreen:
  platform: xpt2046
  calibration_x_min: 323
  calibration_x_max: 3769
  calibration_y_min: 438
  calibration_y_max: 3769
  transform:
    swap_xy: true
  id: my_touchscreen
  cs_pin: 32
  #interrupt_pin: 21
  update_interval: 50ms
  threshold: 400
  on_touch:
    then:
      - light.turn_on: back_light
      - delay: 10s
      - light.turn_off: back_light




binary_sensor:
  - platform: touchscreen
    id: top_left
    x_min: 20
    x_max: 120
    y_min: 20
    y_max: 70
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - logger.log: "The backlight is on"
            - switch.toggle: led_one
  - platform: touchscreen
    id: top_right
    x_min: 200
    x_max: 300
    y_min: 20
    y_max: 70
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - logger.log: "The backlight is on"
            - switch.toggle: led_two
        

switch:
  - platform: gpio
    pin: 2
    id: led_one
  - platform: gpio
    pin: 4
    id: led_two

# Define a PWM output on the ESP32
output:
  - platform: ledc
    pin: 17
    id: gpio_17_backlight_pwm

# Define a monochromatic, dimmable light for the backlight
light:
  - platform: monochromatic
    output: gpio_17_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_OFF
    

any advice, tips and recommendations would be greatly received, but for all others, hope you enjoy the journey as I go along.

Update 24 February 2024

so Ive been working on the thermostat yaml all morning and started to create the basis of the a thermostat adding a temp sensor and only one LED to simulate the heating relay going on/off

this is the updated YAML:

spi:
  clk_pin: 18
  mosi_pin: 23
  miso_pin: 19

time:
  - platform: homeassistant
    id: my_time

font:
  - file: "fonts/Roboto-Regular.ttf"
    id: my_font
    size: 15

  - file: "fonts/Roboto-Regular.ttf"
    id: big_font
    size: 30

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: 5
    cs_pin: 33
    reset_pin: 16
    dimensions:
      height: 240
      width: 320
    transform:
      swap_xy: true 
      mirror_y: true
      mirror_x: true
    lambda: |-
      auto red = Color(255, 0, 0);
      auto green = Color(0, 255, 0);
      auto blue = Color(0, 0, 255);
      auto white = Color(255, 255, 255);
      it.strftime(30, 20, id(big_font), "%Y-%m-%d %H:%M", id(my_time).now());
      it.printf(30, 50, id(big_font), "Temp: %.2f°C", id(temp1).state);
      it.printf(30, 80, id(big_font), "Setpoint: %.2f°C", id(my_climate).target_temperature);
      it.filled_rectangle(20, 130, 90, 40, green);
      it.print(40, 135, id(big_font), white,  "ON");
      it.filled_rectangle(20, 180, 90, 40, green);
      it.print(40, 185, id(big_font), white, "OFF");
      it.filled_rectangle(200, 180, 90, 40, blue);
      it.print(240, 185, id(big_font), white,  "-");
      it.filled_rectangle(200, 130, 90, 40, red);
      it.print(240, 135, id(big_font), white, "+");

      

touchscreen:
  platform: xpt2046
  calibration_x_min: 323
  calibration_x_max: 3769
  calibration_y_min: 438
  calibration_y_max: 3769
  transform:
    swap_xy: true
  id: my_touchscreen
  cs_pin: 32
  #interrupt_pin: 21
  update_interval: 50ms
  threshold: 400
  on_touch:
    then:
      - light.turn_on: back_light
      - delay: 20s
      - light.turn_off: back_light



binary_sensor:
  - platform: touchscreen
    id: temp_down
    x_min: 200
    x_max: 290
    y_min: 180
    y_max: 220
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                target_temperature: !lambda return id(my_climate).target_temperature - 0.5;

  - platform: touchscreen
    id: temp_up
    x_min: 200
    x_max: 290
    y_min: 130
    y_max: 170
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                target_temperature: !lambda return id(my_climate).target_temperature + 0.5;

  - platform: touchscreen
    id: heating_on
    x_min: 20
    x_max: 110
    y_min: 130
    y_max: 170
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                mode: HEAT

  - platform: touchscreen
    id: heating_off
    x_min: 20
    x_max: 110
    y_min: 180
    y_max: 220
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                mode: "OFF"
dallas:
  pin: 15

sensor:
  - platform: dallas
    address: 0x5d03139779b91928
    id: temp1
    name: "Temperature sensor"

switch:
  - platform: gpio
    pin: 4
    id: led_one

# Define a PWM output on the ESP32
output:
  - platform: ledc
    pin: 17
    id: gpio_17_backlight_pwm

# Define a monochromatic, dimmable light for the backlight
light:
  - platform: monochromatic
    output: gpio_17_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_OFF

climate:
  - platform: thermostat
    name: "My Thermostat"
    id: my_climate
    sensor: temp1
    on_boot_restore_from: default_preset
    min_heating_off_time: 6s
    min_heating_run_time: 6s
    min_idle_time: 6s
    heat_action:
      - switch.turn_on: led_one
    idle_action:
      - switch.turn_off: led_one
    default_preset: Home
    preset:
      - name: Home
        default_target_temperature_low: 19.0 °C

at the updated UI and added temp sensor


also I stumbled across this post with a Github link that helped me with a a couple of my EspHome yaml elements

update 2nd March 2024

see post Work in progress! esphome thermostat - #18 by GreyLinux

4 Likes

This seems really cool. Looking forward to seeing where this goes.

Question: Do you plan on adding energy monitoring or anything like that?

1 Like

That looks pretty awesome, can’t wait to see the finished product!

Not at the moment, but that would be a cool addition. I think I’ve set my self up for quite a steep learning curve as it is, but if i can incorporate it along the way then all the better.

1 Like

Projects like this can seem overwhelming and they can be if you try to do the whole thing at once. It looks like your going aboit it the right way. Just focus on one component at a time. Get it working and modt importantly, learn how to use it or the basics at a minimum. After you feel comfortable then move to the next component.

Doing it this way, you really learn more and if theres an issue, well you’re only doing one component at a time so its much easier to narrow down any issues. I dont see this guy around on here much anymore but he has some cool stuff and a cool DIY thermostat that might be helpful or inspiring.

1 Like

Thanks for the video, it was definitely helpful, I’m watching a few of his videos now.

yeah I think this is the best approach, it reminds me of the saying, “The best way to eat an elephant, is one bite at a time”

Unfortunately some people actually plop that whole elephant on their plate and then choke on it. Internet guides arent always right/updated, cheap chinese components dont always work right or have instructions and you can make mistakes.

There’s no penalties or fines for compiling and uploading code for one component at a time. Im not kidding here, it can take 3-4x longer to troubleshoot a medium/large size project than it takes to do it right the first time.

1 Like

Thanks for referring to my post and that it was helpful to you. if you want to tinker around to learn, individual components may be fine. But if you want something more complete and ready-made I used this card

https://it.aliexpress.com/item/1005004279039725.html?spm=a2g0o.order_list.order_list_main.47.73943696SY4rY9&gatewayAdapt=glo2ita

I got this two-channel one because my thermostat manages a pellet insert in which the logic when switched on closes the first relay for ignition while the second relay manages the power modulation based on the desired temperature. with that card all I needed was a Dallas DS18B20 temperature sensor and a Nextion touchscreen panel. writing the firmware and managing the panel took some time because on the primary RX TX PINS the panel did not respond, therefore since I needed to connect it to the serial 2 PIN 16 and 17, and since on these PINs who manufactured the board had connected the two relays I had to make a hardware change that allowed me to get my thermostat working well. By virtue of this, if you have a simple boiler, just purchase a module with a single relay

2 Likes

Thanks for the tip with the ready made board, its definitely something to think about, I’m still in two minds at the moment, I already have all the components to create a relay module from a previous load of projects and this post on a Raspberry pi forum goes a long way to helping me create a module, that hopefully one day will soldered onto a custom pcb for this project.

I hope you don’t mind I liked your design for the UI so much I adapted it using the rendering engine in EspHome, as my display doesn’t have a dedicated chip for rendering like the Nextion.

here is the updated yaml:

spi:
  clk_pin: 18
  mosi_pin: 23
  miso_pin: 19

time:
  - platform: homeassistant
    id: my_time

image:
  - file: mdi:power
    id: power
    resize: 28x28
  - file: mdi:fire
    id: fire
    resize: 28x28
  - file: mdi:chevron-up
    id: chevron_up
    resize: 70x70
  - file: mdi:chevron-down
    id: chevron_down
    resize: 70x70
  - file: mdi:home-assistant
    id: home_assistant
    resize: 90x90

font:
  - file: "fonts/Roboto-Regular.ttf"
    id: my_font
    size: 25
  - file: "fonts/Roboto-Regular.ttf"
    id: big_font
    size: 40
  - file: "fonts/Roboto-Regular.ttf"
    id: little_font
    size: 20
  - file: "fonts/Roboto-Bold.ttf"
    id: bold_font
    size: 25

color:
  - id: grey
    hex: D1D0CE
  - id: white
    hex: FFFFFF
  - id: dark_grey
    hex: A0A0A0
  - id: HA_blue
    hex: 03a9f4

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: 5
    cs_pin: 33
    reset_pin: 16
    dimensions:
      height: 240
      width: 320
    transform:
      swap_xy: true 
      mirror_y: true
      mirror_x: true
    lambda: |-
      it.fill(id(white));
      it.strftime(5, 5, id(bold_font), Color::BLACK, "%H:%M", id(my_time).now());
      it.printf(5, 35, id(bold_font), Color::BLACK, "Temperature:");
      it.printf(110, 63, id(little_font), Color::BLACK, "%.1f°C", id(temp1).state);
      it.printf(225, 70, id(big_font), Color::BLACK, "%.1f", id(my_climate).target_temperature);
      it.image(235, 5, id(chevron_up), Color::BLACK);
      it.image(235,110, id(chevron_down), Color::BLACK);
      it.filled_rectangle(205, 180, 110, 55, id(grey));
      it.filled_rectangle(90, 180, 110, 55, id(grey));
      it.image(250, 182, id(fire), id(dark_grey));
      it.print(240, 207, id(little_font), id(dark_grey), "Heat");
      it.image(135, 182, id(power), id(dark_grey));
      it.print(133, 207, id(little_font), id(dark_grey), "Off");
      it.image(5, 80, id(home_assistant), id(HA_blue));
      

touchscreen:
  platform: xpt2046
  calibration_x_min: 323
  calibration_x_max: 3769
  calibration_y_min: 438
  calibration_y_max: 3769
  transform:
    swap_xy: true
  id: my_touchscreen
  cs_pin: 32
  #interrupt_pin: 21
  update_interval: 50ms
  threshold: 400
  on_touch:
    then:
      - light.control: 
          id: back_light
          brightness: 100%
      - delay: 20s
      - light.control: 
           id: back_light
           brightness: 35%



binary_sensor:
  - platform: touchscreen
    id: temp_down
    x_min: 235
    x_max: 295
    y_min: 110
    y_max: 160
    on_press:
      then:
        - climate.control:
            id: my_climate
            target_temperature: !lambda return id(my_climate).target_temperature - 0.5;

  - platform: touchscreen
    id: temp_up
    x_min: 235
    x_max: 295
    y_min: 20
    y_max: 70
    on_press:
      then:
        - climate.control:
            id: my_climate
            target_temperature: !lambda return id(my_climate).target_temperature + 0.5;

  - platform: touchscreen
    id: heating_on
    x_min: 210
    x_max: 315
    y_min: 180
    y_max: 235
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                mode: HEAT

  - platform: touchscreen
    id: heating_off
    x_min: 90
    x_max: 195
    y_min: 180
    y_max: 235
    on_press:
      then:
        if:
          condition:
            light.is_on: back_light
          then:
            - climate.control:
                id: my_climate
                mode: "OFF"
dallas:
  pin: 15

sensor:
  - platform: dallas
    address: 0x5d03139779b91928
    id: temp1
    name: "Temperature sensor"

switch:
  - platform: gpio
    pin: 4
    id: led_one

# Define a PWM output on the ESP32
output:
  - platform: ledc
    pin: 17
    id: gpio_17_backlight_pwm

# Define a monochromatic, dimmable light for the backlight
light:
  - platform: monochromatic
    output: gpio_17_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: RESTORE_DEFAULT_ON

climate:
  - platform: thermostat
    name: "My Thermostat"
    id: my_climate
    sensor: temp1
    heat_deadband: 0.5
    heat_overrun: 0.5
    min_heating_off_time: 6s
    min_heating_run_time: 6s
    min_idle_time: 6s
    heat_action:
      - switch.turn_on: led_one
    idle_action:
      - switch.turn_off: led_one

and here is a pic of the end result for today

one thing I do need to work out is, how to change the colour of the buttons when their state has changed, I’m sure it will be with an If, Else statement, but that’s a job for tomorrow.

2 Likes

Eeww!! I like that display! Clean and crisp graphics plus its a good size and practical. I always see people using those tiny .96" displays and im over here thinking to myself, " did they actually think that theough? Thats F’ing tiny!"

Do you have a brand/model or a link for that display?

Apologies for the amazon link, but it was a generic ILI9341 TFT display 240x320 (2.8"), so still small but it was cheap and what I needed really.

Amazon is fine. I prefer to pay a little more for the peace of mind and F supporting China and aliexpress crooks.

No worries. Just was curious. Really looking forward to this

And, just where do you think that the Amazon seller gets the parts?

2 Likes

@ GreyLinux - I am seriously impressed. When you are finished, please share the stl files because I’ll bet others will want to copy your project.

What will the relays be switching?

1 Like

Many of the same sellers sell the same stuff at aliexpress, amazon and ebay as they are all marketplaces. :globe_with_meridians:

You still support China (or Chinese business) the same way but on top you that you spend extra money to make bezoz happy :muscle: … beside amazon stuff continues peeing in bottles :raised_hands:

1 Like

So, for my use case it will be a single relay, used to switch my heating boiler, to heating ‘ON’ and for my use the boiler doesn’t require any voltage or very low voltage to signal heating ‘ON’ also known as dry contacts. However, depending on the use case it could be potentially used to signal a cooling unit. Although I might design a 2 relay unit for people that require both.

So there has been a massive update to the project, I have the yaml where I think it works well and everything works also I spent all of yesterday soldering the entire circuit to a prototype board and surprisingly everything worked first time.

The updates to the yaml are, incorporating a settings( probably not the best description) page by tapping the cogs icon on the home page, adding an IF statement for changing the HEAT and OFF to a different colour when the other is pressed. Finally the brightness configuration was a bit clunky before and didn’t work as expected so with the help of someone on discord I have remedied this to work perfectly.

This is the updated yaml

## Wiring
## --------
## The SPI pins, MOSI, MISO, and SCK, are shared between the display
## and the touchscreen (and SD card reader). 
## I did not wire TOUCH_IRQ (add update_interval: 50ms to touchscreen instead)
## The SD card pins are not connected.
##
## LCD to ESP32 (30 pin or d1 mini) wiring:
## * SCK/CLK to 18
## * MISO/DO/SDO to 19
## * MOSI/DIN/SDI to 23
## * DISP_CS to 33
## * DISP_LED to 17
## * TOUCH_CS to 32
## * DISP_DC to 21
## * DISP_RESET to 16
## * VCC to 3V3
## * GND to GND
## 
## * Relay to 22
## * Dallas to 14



esphome:
  name: thermostat-one
  friendly_name: thermostat-one

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  level: DEBUG
  logs:
    component: ERROR

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

ota:
  password: "************************************"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Thermostat-One Fallback Hotspot"
    password: "******************"

captive_portal:

spi:
  clk_pin: 18
  mosi_pin: 23
  miso_pin: 19

time:
  - platform: homeassistant
    id: my_time

text_sensor:
  - platform: wifi_info
    ip_address:
      name: IP_Address
      id: IP_Address
  - platform: version
    name: ESPHome_Version
    id: ESPHome_Version
    hide_timestamp: true

image:
  - file: mdi:power
    id: power
    resize: 28x28
  - file: mdi:fire
    id: fire
    resize: 28x28
  - file: mdi:chevron-up
    id: chevron_up
    resize: 70x70
  - file: mdi:chevron-down
    id: chevron_down
    resize: 70x70
  - file: mdi:home-assistant
    id: home_assistant
    resize: 90x90
  - file: mdi:cogs
    id: cogs
    resize: 50x50
  - file: mdi:home
    id: home
    resize: 50x50

font:
  - file: "fonts/Roboto-Regular.ttf"
    id: big_font
    size: 40
  - file: "fonts/Roboto-Regular.ttf"
    id: little_font
    size: 20
  - file: "fonts/Roboto-Bold.ttf"
    id: bold_font
    size: 25

color:
  - id: grey
    hex: D1D0CE
  - id: white
    hex: FFFFFF
  - id: dark_grey
    hex: A0A0A0
  - id: HA_blue
    hex: 03a9f4

display:
  - platform: ili9xxx
    model: ili9341
    id: my_display
    pages:
      - id: homepage
        lambda: |-
          it.fill(id(white));
          it.strftime(5, 5, id(bold_font), Color::BLACK, "%H:%M", id(my_time).now());
          it.printf(5, 35, id(bold_font), Color::BLACK, "Temperature:");
          it.printf(110, 63, id(little_font), Color::BLACK, "%.1f°C", id(temp1).state);
          it.printf(225, 70, id(big_font), Color::BLACK, "%.1f", id(my_climate).target_temperature);
          it.image(235, 5, id(chevron_up), Color::BLACK);
          it.image(235,110, id(chevron_down), Color::BLACK);
          it.image(5, 80, id(home_assistant), id(HA_blue));

          it.image(20, 180, id(cogs), id(dark_grey));
      
          if (id(my_climate).mode != CLIMATE_MODE_HEAT) {
            it.filled_rectangle(90, 180, 110, 55, id(HA_blue));
            it.image(135, 182, id(power), id(white));
            it.print(133, 207, id(little_font), id(white), "Off");
            it.filled_rectangle(205, 180, 110, 55, id(grey));
            it.print(240, 207, id(little_font), id(dark_grey), "Heat");
            it.image(250, 182, id(fire), id(dark_grey));
          } else {
            it.filled_rectangle(90, 180, 110, 55, id(grey));
            it.image(135, 182, id(power), id(dark_grey));
            it.print(133, 207, id(little_font), id(dark_grey), "Off");
            it.filled_rectangle(205, 180, 110, 55, id(HA_blue));
            it.print(240, 207, id(little_font), id(white), "Heat");
            it.image(250, 182, id(fire), id(white));
            }
      - id: settings_page
        lambda: |-
          it.fill(id(white));
          it.image(10, 10, id(home), id(dark_grey));
          it.print(90, 10, id(bold_font), Color::BLACK, "Settings");
          it.printf(5, 60, id(little_font), Color::BLACK, "ESPHome Version: %s",id(ESPHome_Version).state.c_str());
          it.printf(5, 85, id(little_font), Color::BLACK, "IP Address: %s", id(IP_Address).state.c_str());
          it.printf(5, 110, id(little_font), Color::BLACK, "Uptime: %.f minutes",id(ESP_uptime).state);
          it.printf(5, 135, id(little_font), Color::BLACK, "Wifi Signal: %.0f dBm",id(ESP_wifi_signal).state);
          it.printf(5, 160, id(little_font), Color::BLACK, "HA Status: %s", id(HA_status).state ? "Connected" : "Disconnected");
          
    dc_pin: 21
    cs_pin: 33
    reset_pin: 16
    dimensions:
      height: 240
      width: 320
    transform:
      swap_xy: true 
      mirror_y: true
      mirror_x: true
         

      
      
      

touchscreen:
  platform: xpt2046
  calibration_x_min: 323
  calibration_x_max: 3769
  calibration_y_min: 438
  calibration_y_max: 3769
  transform:
    swap_xy: true
  id: my_touchscreen
  cs_pin: 32
  update_interval: 50ms
  threshold: 400
  on_touch:
    - binary_sensor.template.publish:
        id: touching
        state: ON
  on_release:
    - binary_sensor.template.publish:
        id: touching
        state: OFF

binary_sensor:
  - platform: template
    id: touching
    filters:
      delayed_off: 20s
    on_press:
      - light.control: 
          id: back_light
          brightness: 100%
    on_release:
      - light.control: 
          id: back_light
          brightness: 35%

  - platform: status
    name: "Thermostat One State"
    id: HA_status

  - platform: touchscreen
    id: temp_down
    x_min: 235
    x_max: 295
    y_min: 110
    y_max: 160
    page_id: homepage
    on_press:
      then:
        - climate.control:
            id: my_climate
            target_temperature: !lambda return id(my_climate).target_temperature - 0.5;

  - platform: touchscreen
    id: temp_up
    x_min: 235
    x_max: 295
    y_min: 20
    y_max: 70
    page_id: homepage
    on_press:
      then:
        - climate.control:
            id: my_climate
            target_temperature: !lambda return id(my_climate).target_temperature + 0.5;

  - platform: touchscreen
    id: heating_on
    x_min: 210
    x_max: 315
    y_min: 180
    y_max: 235
    page_id: homepage
    on_press:
      then:
        - climate.control:
            id: my_climate
            mode: HEAT

  - platform: touchscreen
    id: heating_off
    x_min: 90
    x_max: 195
    y_min: 180
    y_max: 235
    page_id: homepage
    on_press:
      then:
        - climate.control:
            id: my_climate
            mode: "OFF"

  - platform: touchscreen
    id: settings_menu
    x_min: 20
    x_max: 70
    y_min: 180
    y_max: 235
    page_id: homepage
    on_press:
        - display.page.show: settings_page
        - component.update: my_display

  - platform: touchscreen
    id: home_page_menu
    x_min: 10
    x_max: 60
    y_min: 10
    y_max: 60
    page_id: settings_page
    on_press:
        - display.page.show: homepage
        - component.update: my_display
  
dallas:
  pin: 14
  update_interval: 10s

sensor:
  - platform: dallas
    address: 0x5d03139779b91928
    id: temp1
    name: "Temperature sensor"

  - platform: uptime
    id: ESP_uptime
    filters:
      - lambda: return x / 60.0;
    unit_of_measurement: minutes

  - platform: wifi_signal
    id: ESP_wifi_signal
    update_interval: 60s

switch:
  - platform: gpio
    pin: 22
    id: led_one

# Define a PWM output on the ESP32
output:
  - platform: ledc
    pin: 17
    id: gpio_17_backlight_pwm

# Define a monochromatic, dimmable light for the backlight
light:
  - platform: monochromatic
    output: gpio_17_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: RESTORE_DEFAULT_ON

climate:
  - platform: thermostat
    name: "My Thermostat"
    id: my_climate
    sensor: temp1
    heat_deadband: 0.5
    heat_overrun: 0.5
    min_heating_off_time: 6s
    min_heating_run_time: 6s
    min_idle_time: 6s
    heat_action:
      - switch.turn_on: led_one
    idle_action:
      - switch.turn_off: led_one
    

and here are some photos of the soldered circuit, complete with working relay and the new UI changes.




admittedly not my finest soldering as my best iron broke so I had to use a very old iron with no heating controls


all powered from 240V mains.

later today I will be working on a circuit diagram that I will post of the complete circuit

4 Likes

Here is the Circuit schematic for the above prototype, its not the best layout, Ive not had much experience creating circuit diagrams. Hopefully its legible enough to gain enough of an insight, plus the pinout from the yaml above should also help.

Glad to see you using female headers and then plugging devices into it. It kind of makes me cringe when i see people solder everything to a prototype board. I learned that lesson quickly and its really convenient being able to pull things off if they need replaced.