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