How I Built a Smart Thermostat

Yazeed Sabri
The Startup
Published in
7 min readMay 12, 2020

The pursuit of minimizing my commute to work led me to move into an apartment with no temperature control. Given how common this is for downtown Chicago apartments with reasonable rent, I thought to myself, if other people can live without it, I’m sure I can too. Well, I was partially right, it was livable but not comfortable. So here is the story of how I built my own smart thermostat.

Before I dive into the details, here is a video of the final product:

The Constraints

The apartment didn’t come with a traditional thermostat control unit with all the lettered and colored wiring.

Instead, the control unit is fairly simple with an on and off switch and another three fan speed switch. The temperature dial doesn’t work, the building controls whether its heating or cooling time. Even though it changes based on the temperature outside, for the sake of simplicity we will assume the temperature of the air coming out of the heater is constant.

Given how old the building is and that I am renting, I chose not to install a controller with relay or program one with a Raspberry Pi. I had to build a system that interacts with the control unit the same way I do.

The Parts

Turning this into a smart thermostat was the motive behind choosing the Raspberry Pi.

Flipping the on and off switch requires both torque and precision, so I went with a pair of SG90 servo motors.

The servo motor is able to move precisely within a 180 degrees

I started the quest of finding a temperature sensor with the DHT22, and I strongly recommend against using it. The way the sensor is designed makes it susceptible to heating up thus messing up its accuracy. I eventually went with the DS18B20 sensor since interfaces with the Pi better, has a longer wire, and is more accurate. Lesson learned here, do your research instead of going off the first YouTube tutorial you watch.

I knew I wanted to use Lego to build the frame. Unlike 3D printing, Lego builds can be changed quickly and at no cost. At the same time, Lego pieces are designed to fit with each other in specific dimensions and increments. This made working around the Raspberry Pi and servo motors dimensions more challenging. Further more, I was constrained by the limited number of pieces I had.

The Lego Design

The build took many iterations that ended up with it being more practical and sturdy than pretty. The limited amount of pieces pushed me to get creative with my building techniques. As you can see in the picture above and in this album, I relied on axles to give me the freedom to slide the motors to where their arms are perpendicular to the on and off switch. Without getting too Lego technical, the motors are tightly held in place from all directions using half-studs, axels, and half-pegs/pins.

The System Design

The Spring Boot application along with the Python scripts are running on the Raspberry Pi

Before we begin, the entire codebase for the projects can be found here, feel free to checkout it out and leave any feedback.

I first wrote the Python scripts to control the motors and probe the temperature sensor. Writing these scripts was relatively easy given the abundance of online tutorials about these Raspberry Pi parts.

Once I figured out the details around the thermostat logic, writing a Spring Boot application that exposes that thermostat’s API endpoints and houses it’s logic were straight forward, with the exception of calling the python scripts. Despite its age, this article nicely describes why calling another process in Java bears such complexity. The Google Home integration was later added to the same application, the details of the integration are outlined in a later section.

In order: The Google Home request fulfillment endpoint, the thermostat endpoints and Google Home authentication endpoints

The Thermostat Logic

Writing the thermostat logic opened my eye to a small portion of the vast design decisions and trade offs involved in making one.

The simple stupid approach for the logic is as follows: keep the apartment temperature as close as possible to the temperature we set. This is not realistic as it would keep turning the system on and off very frequently, thus why the system needs a tolerance window. Introducing a tolerance window would let the temperature veer off the one we set by a Fahrenheit degree or two. If done right, the tolerance window will minimize the number of on and off cycles thus keeping the system on or off for longer, all without sacrificing our comfort.

This tolerance window can be introduced into the system in two ways. For one, I can add a degree or two to the detected temperature. Or I can extend the duration in which the system polls the temperature sensor. Doing both together is possible as well.

Knowing myself and how I will probably try and work around it, I decided to abandon adding a constant to the temperature reading. As for the best polling time, it varies a lot because of how sensitive our poorly insulated apartment is to the temperature outside. And to make matters even more complex, between noon and sunset, the sun takes an active part in heating the place for us. So eventually, after a few trial and error days, setting the polling time to 20 minutes seemed like a good middle ground.

A snippet of the logs showing how the temperature fluctuates every 20 minutes

While talking about the constraints, I glossed over two more factors that affect the system’s behavior. The fan speed and the temperature of the fluid running through pipes. These two go hand in hand to specify the effectiveness of the system. The fluid temperature is out of our control since the building adjusts it based on the outside temperature. On the other hand, the fan has three adjustable speeds we get to control. Without worrying too much about the pipe’s temperature, I found that setting the fan speed to high resulted in a better heat distribution throughout the apartment, since the system was heating a bigger volume of air. I’m assuming the opposite would work better for a smaller space.

The “ideal” temperature sensor position is far away from the vent, the sun, and is in the lower middle of the wall

To position the temperature sensor in what I believed to be the ideal height, I did some experimentation with the help of an indoor thermometer. Many days later, I realized that the position of the sensor doesn’t matter, it’s our perception of the temperature that does. Our perception will adopt regardless of the thermostat’s reading. In other words, instead of always setting the temperature to 70, we’d either set it to 71 or even 72 degrees and achieve the same result.

Google Home Integration

This step turned out to be more complex than anticipated. The picture below shows the information follow from the user to the Google Assistant and eventually to the smart device:

Source: Smart Home integration docs

Google’s Smart Home documentation outlines the integration as follows:
1) Setting up OAuth 2.0 for authorization and account linking.
2) Creating a Smart Home action in the Action Console.
3) Adding authentication.

Actions in Google’s landscape are the equivalent of Amazon’s Alexa skills. Smart Home is a type of action that deals with smart devices integration.

While going through the steps, I was disappointed to find out that regardless of whether I intent to publish my Smart Home action or not, I had to go through all of the steps. I couldn’t find a way that allows me to skip the OAuth and authentication steps in order to create a quick and easy test for my action. I don’t understand the reasoning behind such decision, since as of now, with everything setup, no one except me has access to my action unless I explicitly invite them.

Moreover, enforcing steps 1 and 3 means that anyone who plans to experiment with a Smart Home action must possess a publicly accessible URL. I was able to overcome this by using ngrok, an awesome tool that tunnels traffic from a public URL to your local machine. Since the free version of ngrok uses a new random URL after each restart, I decided to pay for their basic plan which gives me the ability to reserve URLs on their domain. I recommend doing this, since I now don’t have to worry about changing the URL settings after any restart.

Lastly, setting up the actions fulfillment endpoint that Google Cloud will call was a mix of looking at the documentation, samples, and reverse engineering.

Final thoughts

Like any project, I had my ups and downs while working on this but I’m very satisfied with the final product and how well it works. Before I sign off, I want to give a shoutout to the Pi-hole project, they help you setup a DNS black hole to achieve network-wide ad blocking, I strongly recommend setting it up if you have a Raspberry Pi or any compatible hardware.

--

--