Project

Programmable Smart Thermostat with OLED and Schedule

Off-the-shelf smart thermostats are $200 and tend to brick the day the manufacturer's cloud goes down. The hardware is genuinely cheap — a temperature sensor, a relay, a small display, an ESP32. The trick is the firmware: hysteresis (don't oscillate around the setpoint), schedules (warm in the morning, cooler at night), and graceful WiFi-down behavior (it must keep heating sensibly even with the network out).

Architecture

flowchart TD BME[BME280
I2C, 0x76] -->|temp/humidity| ESP32 OLED[SSD1306 OLED
I2C, 0x3C] <--> ESP32 ESP32[[ESP32]] -->|hysteresis logic| Relay Relay[Relay
24VAC contactor] --> Heater[Boiler / HVAC] ESP32 -->|MQTT temp/setpoint| HA[Home Assistant] Browser[Phone] -->|HTTP /set?temp=22| ESP32 NTP[pool.ntp.org] --> ESP32

The OLED shows live temp + setpoint. The relay closes the heater's 24VAC control circuit. Schedule + setpoint live in flash, so they survive reboots.

Bill of materials

  • ESP32 dev board — $7
  • BME280 sensor — $5
  • 0.96" SSD1306 OLED, I2C, 128×64 — $4
  • 5V relay module rated for 24VAC — $2
  • 5V/1A wall adapter — $4
  • Wall-mount project box — $5
  • Two pushbuttons (manual setpoint up/down) — $1

Total around $35. Most home heaters use 24VAC for the thermostat control — verify yours before connecting.

Wiring

I2C bus (BME280 + OLED share)
ESP32 GPIO 21 (SDA) -- BME280 SDA -- OLED SDA
ESP32 GPIO 22 (SCL) -- BME280 SCL -- OLED SCL
ESP32 3.3V          -- BME280 VCC -- OLED VCC
ESP32 GND           -- BME280 GND -- OLED GND

Relay
ESP32 GPIO 26 -- Relay IN
ESP32 5V      -- Relay VCC
ESP32 GND     -- Relay GND
Relay COM     -- Heater R wire (24VAC)
Relay NO      -- Heater W wire (call for heat)

Buttons (INPUT_PULLUP)
ESP32 GPIO 32 -- button + UP   -- GND
ESP32 GPIO 33 -- button + DOWN -- GND

The relay's COM/NO replace where the existing thermostat connects R and W. Don't pull mains AC into the ESP32 — 24VAC stays on the relay output side.

Firmware design

The control loop runs once per second. It reads the temperature, checks the schedule (which gives a target setpoint for the current hour), applies hysteresis (heat below target − 0.5°C, stop heating above target + 0.5°C), and toggles the relay. The OLED is updated every 500 ms with current temp, target, and heating state.

The schedule is stored as 24 hourly setpoints (one per hour of day) in flash. The web UI lets you set them with a simple form — POST to /schedule overwrites the entire array.

Going further

  • Add a PIR sensor: drop the setpoint by 2° if no motion for 30 minutes.
  • Two zones: split the relay output, two BME280s, one ESP32 controlling both.
  • Adaptive setpoint: learn how long the house takes to warm up, start heating that much earlier than the schedule says.

Key code: main loop

This is the heart of the firmware, taken from the working sketch. The complete file (with config template, library list, and the rest of the helpers) is around 98 lines and is included in the downloadable project package — request it via the form below.

void loop() {
static unsigned long lastCtrlMs = 0;
    if (millis() - lastCtrlMs > 1000) {
        lastCtrlMs = millis();
        controlLoop();
    }
    if (millis() - lastDisplayMs > 500) {
        lastDisplayMs = millis();
        drawDisplay();
    }
    // Manual override: hold buttons to bump setpoint of current hour
    if (digitalRead(BTN_UP) == LOW) {
        struct tm ti; if (getLocalTime(&ti)) schedule[ti.tm_hour] += 0.5f;
        delay(200);
    }
    if (digitalRead(BTN_DOWN) == LOW) {
        struct tm ti; if (getLocalTime(&ti)) schedule[ti.tm_hour] -= 0.5f;
        delay(200);
    }
    delay(20);
}
Project package

Get the complete project package

The article above shows the core firmware and the principles behind it. The complete project package — assembled, tested, and ready to flash — is available by email request. We send it manually, and we read every request.

  • Complete Arduino sketch (.ino) with full error handling
  • List of required libraries with version numbers
  • Printable wiring diagram (PDF)
  • Bill of materials with current part numbers
  • Build guide and troubleshooting tips
  • Configuration template (WiFi, MQTT, etc.)

We send the package by email within 24 hours, usually faster. Free, no spam, no mailing list. Your email is used once, for this reply.

Share your thoughts

Worked with this in production and have a story to share, or disagree with a tradeoff? Email us at support@mybytenest.com — we read everything.