We spend a lot of money to keep our houses at a comfy temperature. So, it makes a lot of sense to keep a close eye on our climate control systems. That’s why one of the first “big-deal” smart devices was a thermostat. But for $250 I’ll bet we can DIY ourselves something just as good for a lot less dinero.

Let’s start this project by talking about what makes a Thermostat “smart”. For one thing, a smart thermostat needs to be accessible remotely. So you can adjust the temperature from anywhere, anytime you want. I don’t even want to think about how much money I’ve paid to heat or cool an empty house. That brings up our second important smart-stat feature. It needs to be able to interact with other smart home devices. Like presence detection. When no one is “home” the thermostat can automatically adjust the temp to save me some rupees. Having other triggers like open doors or windows, motion detection, and gathering data from a weather service or from a bunch of different temp sensors throughout the house, are good examples of the benefit of interconnecting with the Smart-o-stat. Finally, the feature that the big brand thermostat makers really brag about is making complicated schedules. Including different settings for mornings vs evenings, weekdays vs weekends, and even different seasons. Good news! All of that is totally achievable with our DiY-o-stat. Let’s get to building!

Building the Thermostat:
To replace one of our thermostats, I’m using a D1mini with Tasmota, 3 relay modules, and an AM2302 T&H sensor. Upload Tasmota pre-compiled bin onto the D1mini using FlashEZ and verify and configure it with backlog and Termite.

ESPeasy – https://github.com/letscontrolit/ESPEasy/releases
Tasmota – https://github.com/arendst/Sonoff-Tasmota/releases
Termite – https://www.compuphase.com/software_termite.htm

Configure Tasmota as a Generic Module type, set 3 relays on these pins D1, D2, and D8, and if you’re going to use your new thermostat as a temperature sensor also, then use one pin for your temp sensor. I used D5 for mine. If you use Fahrenheit then in the Console type “Setoption8 1”. It’s going to be really important that these relays don’t activate when they’re not supposed to. We don’t want our AC to randomly switch on in the middle of winter. So we want to set “switchretain 1”, and “powerretain 1”, those are in the backlog command or you can type them in the Console. For more info about why those retain settings are important check out Rob’s video on retaining MQTT messages.

>

As I’ve been doing for you lately, I’ve put all the Tasmota settings you’ll need for the D1mini in a backlog command. If you’re using tasmota a lot, I suggest you keep one backlog command that sets up your wifi and mqtt info. Save it somewhere you can easily copy and paste it every time. Then you can use a different backlog command for the extra settings, like module type, gpio assignments, and naming. Using Backlog is totally optional. It may save you a few minutes during setup, but if it is confusing to you, just go into the Tasmota UI and manually adjust the settings. Here are all the settings you need.

Backlog Commands:
(This is for your Wifi & MQTT) – Backlog SSID1 YourWifiSSID; Password1 YourWifiPW; MqttHost your.mqtt.pi.ip; MqttUser yourMQTTuser; MqttPassword yourMQTTpw

(This is specific for the ThermoZzstat) – Backlog PowerRetain 1; SwitchRetain 1; gpio15 23; gpio4 22; gpio5 21; gpio14 02; setoption8 1; teleperiod 10; module 18

Now the wiring. On these relay modules the D1 pin is the control pin. They also need 5v and Ground. The rest of these holes are here just because these are made to fit on top of a D1mini. You can get other relay modules that are configured differently. I’m connecting the Fan relay to D1, the AC to D2, the Furnace to D8, and the Temp Sensor to D5. You’ll need 5v for power to the D1mini and the relays, and you can send 3v or 5v to the Temp sensor. You can use a microUSB connector for power, or you can run 5v directly from the PS to the shared 5v connection.
On a typical HVAC thermostat (at least in the US) you’ll have 4 wires. The Red is the Common, so that one will go to the middle pole on the relays. Making the Common wire Red is a bit confusing. Don’t know why they do it that way. The Green wire is for the Fan, Yellow is the AC, and White is the Furnace. Each of those wires goes on the NO (Normally Open) pole of the Relay. This diagram shows you all the connections.

Do a quick check in the Tasmota UI to make sure our relays and temp sensor are working. If that’s all good, we can now do our Home Assistant setup. You’ll need to create a switch entity for each relay. These are simple MQTT switches. These look just like every other switch entry we’ve created when using Tasmota. Be systematic in your naming to make it easier to organize them later.

#switch:
– platform: mqtt
name: “Upstairs Fan”
command_topic: “cmnd/ThermoZztat/POWER1”
state_topic: “stat/ThermoZztat/POWER1”
qos: 1
payload_on: “ON”
payload_off: “OFF”
retain: false
– platform: mqtt
name: “Upstairs AC”
command_topic: “cmnd/ThermoZztat/POWER2”
state_topic: “stat/ThermoZztat/POWER2”
qos: 1
payload_on: “ON”
payload_off: “OFF”
retain: false
– platform: mqtt
name: “Upstairs Furnace”
command_topic: “cmnd/ThermoZztat/POWER3”
state_topic: “stat/ThermoZztat/POWER3”
qos: 1
payload_on: “ON”
payload_off: “OFF”
retain: false

You’ll need at least one sensor for temperature. With a temp sensor in Tasmota this is what the sensor entry looks like to get the accurate temperature. The value_template is muy importante.

#sensor:
– platform: mqtt
state_topic: ‘tele/ThermoZztat/SENSOR’
name: ‘Upstairs Temp’ #AM2301
unit_of_measurement: ‘°F’
value_template: ‘{{ value_json.AM2301.Temperature }}’

I’ve got a few different temp sensors I want to use to come up with an average temperature for a specific area in the house. To do that I’m using the min-max sensor type. Here’s how you create it.

#sensor:
– platform: min_max
name: “Average Upstairs Temp”
type: “mean”
round_digits: 1
entity_ids:
– sensor.blink_toy_room_temperature
– sensor.blink_mountain_room_temperature
– sensor.upstairs_temp

With the D1mini and relays setup, and the temp sensors and switches in HA, the next step is to setup the basic Thermostat. To do that we use the HA “climate” component, and create a “generic thermostat” entry.

climate:
– platform: generic_thermostat
name: Upstairs Heat
heater: switch.upstairs_furnace
target_sensor: sensor.average_upstairs_temp
min_temp: 40
max_temp: 90
# min_cycle_duration:
# minutes: 15
initial_operation_mode: “auto”
target_temp: 72
away_temp: 60
cold_tolerance: 0.5
hot_tolerance: 0.5
# keep_alive:
# minutes: 5

Each Climate entry can only control one relay. So if your old thermostat was controlling AC and Heat (like mine), then in HA you’ll need to create two climate entities. One that will control the AC and one that will control the heat. That’s something I hope changes someday.

#climate:
– platform: generic_thermostat
name: Upstairs AC
heater: switch.upstairs_ac
target_sensor: sensor.average_upstairs_temp
min_temp: 40
max_temp: 90
initial_operation_mode: “auto”
# min_cycle_duration:
# minutes: 30
target_temp: 74
away_temp: 80
cold_tolerance: 0.5
hot_tolerance: 0.5
ac_mode: true

That’s a lot of yaml, and yaml is not very forgiving so double check all your entries, then save, check the config, and restart HA. When it comes back up we can test our thermostats from the Home Assistant UI. If you really want a Nest-like thermostat interface there is a nice looking custom component for Lovelace. This a custom card, so to use it you first need to download the custom-cards repository from github. Extract it and copy the file thermostat-card.js to your www folder. Then in your ui-lovelace.yaml file, you need to add it to the top with these lines:

resources:
– url: /local/thermostat-card.js?v=2
type: module

title: Adensville
views:
– title: Upstairs
icon: mdi:home-heart
panel: true
cards:
– type: vertical-stack
cards:
– type: custom:plan-coordinates
– type: picture-elements
image: /local/HHC_2.png
elements:
– type: custom:thermostat-card
entity: climate.upstairs_ac
style:
left: 63%
top: 70%
width: 15%
ambient_temperature: sensor.average_upstairs_temp
hightlight_tap: true
no_card: true
– type: custom:thermostat-card
entity: climate.upstairs_heat
style:
left: 63%
top: 89%
width: 15%
ambient_temperature: sensor.average_upstairs_temp
hightlight_tap: true
no_card: true

Now we need a few automations. This first automation will make sure the AC and Furnace don’t ever run at the same time. We’ll also add a second action so anytime the AC or the Furnace turn on the Fan also turns on. You’ll still be able to run just the Fan, but you’ll never be able to run the AC or the Heater without the Fan.

#automations.yaml
– alias: No AC when the Heat is on
trigger:
– platform: state
entity_id: switch.upstairs_ac
to: “on”
action:
– service: switch.turn_off
entity_id: switch.upstairs_furnace
– service: switch.turn_on
entity_id: switch.upstairs_fan

– alias: No Heat when the AC is on
trigger:
– platform: state
entity_id: switch.upstairs_furnace
to: “on”
action:
– service: switch.turn_off
entity_id: switch.upstairs_ac
– service: switch.turn_on
entity_id: switch.upstairs_fan

Those two automations are really critical. You don’t want to skip those or you could damage your HVAC unit. These next couple of automations are optional, but these are some examples of how to really make our thermostat smarter. This Automation will set both the AC and Furnace thermostat entities to Away, if both my wife and I are not detected as “home” for more than 24hrs. This is our vacation safety net. If we forget to put the Thermostat in “Away” mode before we leave, this will handle it for us.

#automations.yaml
– alias: No one home Away Mode On
trigger:
– platform: state
entity_id: device_tracker.janis7, device_tracker.justin_iphone7
from: ‘home’
to: ‘not_home’
for:
hours: 24
action:
– service: climate.set_away_mode
data:
entity_id: climate.upstairs_ac, climate.upstairs_furnace
away_mode: ‘on’

These next automations are schedule based changes, that will adjust the temperature based on the month of the year and time of day, to let the house get warmer at night and cooler in the daytime during the summer.

#automations.yaml
– alias: Summer Night Temp adjustment
trigger:
– platform: time
at: ’22:30:00′
condition:
condition: or
conditions:
– condition: template
value_template: ‘{{ now().month == 5 }}’
– condition: template
value_template: ‘{{ now().month == 6 }}’
– condition: template
value_template: ‘{{ now().month == 7 }}’
– condition: template
value_template: ‘{{ now().month == 8 }}’
– condition: template
value_template: ‘{{ now().month == 9 }}’
action:
– service: climate.set_temperature
data:
entity_id: climate.upstairs_ac
temperature: 76
operation_mode: Cool

– alias: Summer Daytime Temp adjustment
trigger:
– platform: time
at: ’09:00:00′
condition:
condition: or
conditions:
– condition: template
value_template: ‘{{ now().month == 5 }}’
– condition: template
value_template: ‘{{ now().month == 6 }}’
– condition: template
value_template: ‘{{ now().month == 7 }}’
– condition: template
value_template: ‘{{ now().month == 8 }}’
– condition: template
value_template: ‘{{ now().month == 9 }}’
action:
– service: climate.set_temperature
data:
entity_id: climate.upstairs_ac, climate.main_floor_ac
temperature: 72
operation_mode: Cool

I’ll admit, if you’re going to make a bunch of schedules like this, then using Yaml Automations is going to get cumbersome. Fortunately there are a couple of good options that can make it easier. One option is a yaml-based Appdaemon app called Heaty. Heaty will let you write a schedule like the ones I just showed you, but they will only require a couple simple lines of yaml instead of 20+ lines. The other uses nodeRed and was created by Peter Scargill

 

I haven’t mastered either of these myself (Yet) so I can’t give you a detailed explanation (Yet). But when I’m comfortable using them I’ll create a demo to help you use them.

The final step is to install our new smartystat. In most houses you’ll have red, green, white, and yellow wires coming into the thermostat. The Red will be ground and attach to the the “common” pole on each relay. The other colors go to the NO contacts, one for each relay. Some systems will also have a blue wire that will carry DC voltage, probably 27v. Of course you need to double check your system and your wiring. Open up your AC/Furnace and look at where the different colored wires are attached. Use your voltmeter to double check what voltage you’re getting on the blue wire. The red wire here is the ground. I know, it feels wrong to me too, but someone in the HVAC world decided this was the way to do it, and they didn’t ask me. When you’ve got it all wired up, it’s time for the final test.

Well that’s it. We now have a Thermostat that we can control from anywhere, anytime. It will interact with all our smart home devices through Home Assistant, especially presence detection, and we can setup custom schedules.
You can get all these parts from Amazon for about $20 ($28 total for 2 D1 mini’s and 2 Temp sensors). Or if you don’t mind waiting you can get the parts from Banggood or AliExpress for about $12.

Amazon:

Banggood:

AliExpress:
AliExpress.com Product – D1 mini – Mini NodeMcu 4M bytes Lua WIFI Internet of Things development board based ESP8266 by WeMos AliExpress.com Product – Free shipping 1 channel Relay Shield for Wemos D1 mini Relay Module Smart Electronics AliExpress.com Product – DHT22 Digital Temperature and Humidity Sensor AM2302 Module+PCB with Cable for Arduino Free Shipping Dropshipping

Banggood:
D1mini – https://drzzs.com/D1mini
Relay – https://drzzs.com/D1relay
Temp Sensor – https://drzzs.com/Am2302

Our house is a bit of a special case that probably won’t apply to everyone. If you want to see how I replaced all 9 of the thermostats in our house I’ll talk about it in the next live stream. If you miss the stream, don’t worry. It’ll stay available so you can watch it later.

Speaking of live streams, I try to do one at least weekly, usually on Sundays. I alternate the time to accommodate as many time zones as possible. If you want to get an alert when a live stream starts, click the bell. If you need help or just want to chat in between streams, we’ve got a facebook page and a discord server. And there’s always, twitter and instagram. And if you want to support my early retirement fund, there’s Patreon.

Thanks for your support, thanks to everyone in Discord and Facebook that lends a hand in helping answer questions. I couldn’t do all this without a lot of help.

Adios