Build a Raspberry Pi‑Powered Smart Thermostat with Python in Under 2 Hours

Ever walked into a room that feels like a freezer or a sauna and thought, “If only the thermostat could read my mind?” In 2024 the cheap, powerful Pi lets us turn that wish into a real, working device without a PhD in HVAC. In this post I’ll walk you through a complete smart thermostat build that you can finish in under two hours – from wiring the sensor to writing the Python code that keeps your home comfy and your energy bill honest.

What You’ll Need

Hardware

  • Raspberry Pi 4 (2 GB is fine) with power supply
  • DHT22 temperature‑humidity sensor (or the cheaper DHT11 if you’re on a budget)
  • 2‑channel relay board (5 V) – one channel for the heating element, the other for cooling/fan
  • Small 12 V or 24 V heating pad or a simple 5 V fan for testing
  • Breadboard and jumper wires
  • Optional: 0.96″ I2C OLED display for a quick glance at the current temperature

Software

  • Raspberry Pi OS (Lite or Desktop, whichever you prefer)
  • Python 3 (already on Pi)
  • Adafruit_DHT library for sensor reading
  • gpiozero for controlling the relay
  • flask if you want a web UI (optional, but I’ll show a tiny snippet)

All of these can be installed with a single pip install command, so you won’t waste time hunting down packages.

Wiring the Parts – Keep It Simple

  1. Power the Pi – Plug in the official 5 V micro‑USB or USB‑C supply.
  2. Connect the DHT22 – The sensor has three pins: VCC, Data, GND.
    • VCC → Pi 3.3 V (pin 1)
    • GND → Pi GND (pin 6)
    • Data → any GPIO, I usually pick GPIO 4 (pin 7).
      Add a 10 kΩ pull‑up resistor between VCC and Data; the sensor needs it to stay stable.
  3. Hook up the Relay Board – Each relay channel has IN, VCC, GND, and COM/NO/NC terminals.
    • VCC → Pi 5 V (pin 2)
    • GND → Pi GND (pin 9)
    • IN1 → GPIO 17 (pin 11) – controls heating
    • IN2 → GPIO 27 (pin 13) – controls cooling/fan
    • COM → one side of your heating pad or fan power source
    • NO (normally open) → the other side of the load
      When the Pi drives the IN pin high, the relay closes the circuit and powers the load.

If you’re using an OLED display, wire SDA to GPIO 2 and SCL to GPIO 3 – the Pi’s default I2C pins.

Getting the Pi Ready – A Quick Setup

Open a terminal on your Pi (or SSH in) and run:

sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip -y
pip3 install adafruit-circuitpython-dht gpiozero flask

The adafruit-circuitpython-dht package includes the Adafruit_DHT module we need.

Now create a new folder for the project:

mkdir ~/smart_thermostat && cd ~/smart_thermostat

Writing the Core Python Script

Create a file called thermostat.py and paste the following code. I’ve kept it short but added comments so you can tweak it later.

#!/usr/bin/env python3
import time
import Adafruit_DHT
from gpiozero import OutputDevice

# ---- Configuration ----
SENSOR = Adafruit_DHT.DHT22
PIN_SENSOR = 4               # GPIO where DHT data line is connected
HEAT_RELAY = OutputDevice(17, active_high=True, initial_value=False)
COOL_RELAY = OutputDevice(27, active_high=True, initial_value=False)

TARGET_TEMP = 22.0           # Desired room temperature in Celsius
HYSTERESIS = 0.5             # Prevents rapid on/off switching

def read_temp():
    humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN_SENSOR)
    return temperature

def control_loop():
    while True:
        temp = read_temp()
        if temp is None:
            print("Failed to read sensor")
            time.sleep(2)
            continue

        print(f"Current temp: {temp:.1f}°C")

        if temp < TARGET_TEMP - HYSTERESIS:
            HEAT_RELAY.on()
            COOL_RELAY.off()
            print("Heating ON")
        elif temp > TARGET_TEMP + HYSTERESIS:
            HEAT_RELAY.off()
            COOL_RELAY.on()
            print("Cooling ON")
        else:
            HEAT_RELAY.off()
            COOL_RELAY.off()
            print("System idle")

        time.sleep(5)

if __name__ == "__main__":
    try:
        control_loop()
    except KeyboardInterrupt:
        HEAT_RELAY.off()
        COOL_RELAY.off()
        print("\nShutting down")

A few notes:

  • Hysteresis prevents the relay from flickering when the temperature hovers around the set point.
  • read_retry tries a few times before giving up – the DHT sensors can be a bit flaky.
  • The script runs forever, checking the temperature every five seconds. You can change the interval to suit your hardware.

Make the script executable:

chmod +x thermostat.py

Run it with sudo ./thermostat.py (the relays need root access). If everything is wired correctly you’ll see the temperature printed and the relays click as the script turns heating or cooling on.

Adding a Tiny Web Dashboard (Optional but Fun)

If you like to peek at the numbers from your phone, add this tiny Flask endpoint at the bottom of the same file:

from flask import Flask, jsonify
app = Flask(__name__)

@app.route("/status")
def status():
    temp = read_temp()
    return jsonify({
        "temperature": temp,
        "target": TARGET_TEMP,
        "heating": HEAT_RELAY.is_active,
        "cooling": COOL_RELAY.is_active
    })

if __name__ == "__main__":
    from threading import Thread
    Thread(target=control_loop, daemon=True).start()
    app.run(host="0.0.0.0", port=5000)

Now you can point any browser to http://<pi_ip>:5000/status and see a JSON dump of the current state. No fancy UI – just raw data you can parse or feed into Home Assistant later.

Testing and Calibration

  1. Power the Pi and let the script start.
  2. Place the DHT sensor in the room you want to control.
  3. Plug in the heating pad (or fan) to the relay’s COM/NO terminals.
  4. Watch the console – you should see “Heating ON” when the room is cold and “Cooling ON” when it gets warm.

If the relay never clicks, double‑check the GPIO numbers and that the relay board’s VCC is tied to the Pi’s 5 V, not the 3.3 V line.

For fine‑tuning, adjust TARGET_TEMP and HYSTERESIS. I usually set a 0.5 °C hysteresis for a small room; larger spaces can tolerate a wider band.

Going Further – What’s Next?

  • Add a rotary encoder to let you change the target temperature without touching the Pi.
  • Log data to a local SQLite file or push it to Logzly (our own cloud) for trend analysis.
  • Integrate with voice assistants using MQTT – a few lines of code and you can say “Hey Google, set the living room to 21 degrees.”

All of these upgrades are just Python modules away, which is why I love the Pi for IoT: you start with a working prototype in minutes, then layer on features as your imagination grows.

Wrap‑Up

Building a smart thermostat with a Raspberry Pi is a perfect weekend project for anyone who enjoys tinkering and wants a tangible payoff – a more comfortable home and a glimpse into real‑world automation. The whole process, from wiring the DHT22 to writing a few dozen lines of Python, fits comfortably into a two‑hour window if you have the parts ready. Once it’s up and running, you’ll feel that satisfying “I built this” buzz every time the relay clicks on or off.

Give it a try, tweak the code to match your space, and let the Pi keep your house at the perfect temperature while you focus on the next cool IoT idea.

Reactions
Do you have any feedback or ideas on how we can improve this page?