/ #ESP32 #weather station 

Smart Weather Station ESP32: Control High-Voltage Appliances with a 2-Way Relay

Last winter my garage turned into a walk‑in freezer every night because I’d simply forget to flip the heater switch before bed. I wanted something that didn’t just display the temperature but actually did something with it—so I set out to build an ESP32 weather station that reads the room conditions and physically switches a high‑voltage appliance. The result is a small, Wi‑Fi‑connected brain that uses a 5V 2‑way relay module to control a space heater and an exhaust fan. It’s been running ever since, and I’ll show you exactly how I put it together, including the mistakes I made along the way.

Building Your ESP32 Weather Station

The idea is simple: a DHT22 sensor feeds temperature and humidity to an ESP32, a tiny OLED display shows the current readings, and when things get too cold or too hot, the 2‑way relay kicks in to turn mains‑powered appliances on or off. All the logic lives in ESPHome—no Arduino IDE compile‑dance required, though I’ll point out the alternative if you prefer C++.

I started with a bare ESP32 DevKitC and a $3 relay module I had lying around, and quickly learned that choosing the right pins and power supply makes the difference between a reliable automation tool and a paperweight.

Materials & Tools

Here’s everything you need. I’ve added notes from my own trial and error so you skip the parts where I smoked a DHT22 (literally).

  • ESP32 Development Board Module
    ESP32-DevKit board: Buy it here
    Any 30‑pin or 38‑pin ESP32 DevKit board will work; I used the standard ESP32‑DevKitC V4.

  • 5V 2‑way relay module (e.g., SRD‑05VDC with optocoupler)
    Look for one that has a JD‑VCC jumper and accepts 3.3 V logic input. Many modules claim 5 V logic but will still trigger with 3.3 V—I’ll cover that in the wiring.

  • DHT22 temperature / humidity sensor (the DHT11 works too, but the DHT22 is far more accurate—see the FAQ for differences).

  • SSD1306 128×64 OLED display (I2C, usually address 0x3C). This is optional; you can always read values over Wi‑Fi.

  • 4.7 kΩ – 10 kΩ resistor (pull‑up for the DHT22 data line).

  • Jumper wires, breadboard, USB power supply (any 5 V ≥ 1 A phone charger).

  • A lamp or small heater for testing (keep a fire extinguisher ready and double‑check your 110/230 V wiring).

Wiring the ESP32 Weather Station

I originally routed the relays straight to GPIO0 and GPIO2. Huge mistake. Those pins are strapping pins that control boot mode, and the ESP32 refused to start unless the relay inputs were floating exactly at the right voltage. After a few hours of head‑scratching I moved to safer GPIOs. Here’s the layout I’ve used ever since.

Pin connections

ESP32 PinComponentNotes
3V3OLED VCC, DHT22 VCC3.3 V power
GNDOLED GND, DHT22 GND, Relay GNDCommon ground – tie everything together
GPIO21 (SDA)OLED SDAI2C data
GPIO22 (SCL)OLED SCLI2C clock
GPIO25DHT22 DATA10 kΩ pull‑up to 3V3
GPIO26Relay IN1Ch 1 control (e.g., heater)
GPIO27Relay IN2Ch 2 control (e.g., fan)
5V (VIN)Relay VCC (JD‑VCC jumper removed)See power note below

Relay module power trick: Many 5 V relay boards have a JD‑VCC jumper that connects the relay coil power to the logic VCC. If you keep the jumper, the relay coils will draw current directly from the ESP32’s 3.3 V or 5 V pin—bad idea for high‑current coils. Remove the jumper and feed the relay JD‑VCC pin from the ESP32’s 5 V (VIN) pin, while VCC (logic side) gets 3.3 V. This isolates the coil supply from the logic, and your ESP32 stays stable.

I also strongly recommend a 10 kΩ pull‑up resistor from the DHT22 data pin to 3.3 V. Without it, you’ll get NaN readings—ask me how I know.

Software Setup: ESPHome and the “IDE”

You can write an Arduino sketch if you like. If that’s your jam, install the ESP32 board manager URL (https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json) and grab the Adafruit SSD1306 and DHT sensor library. But for this weather station, ESPHome makes configuration a breeze and integrates seamlessly with Home Assistant, MQTT, and Grafana—topics I’ll mention later.

Install ESPHome

I use the ESPHome dashboard via Docker; you can also pip install esphome. Once you have the dashboard running:

  1. Click New Device, name it weather-station.
  2. Copy the unique encryption key that ESPHome generates.
  3. Connect the ESP32 via USB, select the serial port, and flash a basic “online” node.

This creates an initial YAML file that we’ll modify.

Configuring the ESP32 Weather Station in ESPHome

Below is the complete ESPHome configuration I landed on. It defines the DHT22 sensor, the OLED display, two relay switches, and a simple automation that turns the heater on when the temperature drops below 5 °C.

substitutions:
  device_name: weather-station
  friendly_name: Garage Weather Station

esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}
  platform: ESP32
  board: esp32dev

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ${device_name} Fallback
    password: !secret fallback_password

logger:
api:
  password: !secret api_password
ota:
  password: !secret ota_password

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: True
  id: bus_a

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    lambda: |-
      it.printf(0, 0, id(my_font), "Temp: %.1f°C", id(garage_temp).state);
      it.printf(0, 20, id(my_font), "Hum: %.1f%%", id(garage_humidity).state);
      it.printf(0, 40, id(my_font), "Heater: %s", id(heater_relay).state ? "ON" : "OFF");      

font:
  - file: "gfonts://Roboto"
    id: my_font
    size: 16

sensor:
  - platform: dht
    pin: GPIO25
    model: DHT22
    temperature:
      name: "Garage Temperature"
      id: garage_temp
    humidity:
      name: "Garage Humidity"
      id: garage_humidity
    update_interval: 30s

switch:
  - platform: gpio
    pin: GPIO26
    name: "Heater Relay"
    id: heater_relay
    restore_mode: ALWAYS_OFF
  - platform: gpio
    pin: GPIO27
    name: "Fan Relay"
    id: fan_relay
    restore_mode: ALWAYS_OFF

# Simple automation: turn heater on when cold
interval:
  - interval: 5s
    then:
      - if:
          condition:
            lambda: 'return id(garage_temp).state < 5.0;'
          then:
            - switch.turn_on: heater_relay
          else:
            - switch.turn_off: heater_relay

Key sections:

  • The i2c block uses the standard pins and enables scanning, helpful when your OLED doesn’t show up.
  • The display lambda updates every time a sensor changes, so the OLED always reflects the current values.
  • restore_mode: ALWAYS_OFF ensures the relays stay off after a power cut—important for safety.
  • The interval automation runs every 5 seconds and decides the heater state; you could easily add a second condition for humidity or time‑of‑day.

Save the YAML, then hit InstallWirelessly (or Plug into this computer) to upload the configuration.

Upload & Test Your ESP32 Weather Station

After a successful upload, the OLED should light up with temperature and humidity. Open the ESPHome dashboard logs (or serial monitor) and you’ll see readings like:

[20:34:52][D][dht:048]: Got temperature=4.8°C humidity=62.0%

Now, connect a low‑power LED or a lamp to the relay’s Normally Open (NO) and COM terminals after unplugging everything from mains. Power up the relay module. When the temperature falls below 5 °C, you should hear the relay click and the appliance turns on.

For a real high‑voltage load, I tested with an old desk lamp plugged into the relay’s input. Always enclose the high‑voltage wiring inside a proper junction box and never touch bare terminals while powered.

Troubleshooting

Real‑world gotchas that drove me crazy:

  • Relay not switching, or intermittent clicking: Many 5 V relay modules expect 5 V on the logic input. The ESP32 GPIO outputs only 3.3 V, which can be marginal. I solved it by choosing a module rated for 3.3 V control (they have a low‑current optocoupler). If yours doesn’t trigger, use a level‑shifter or a simple NPN transistor circuit.
  • NaN temperature / humidity: Almost always a missing pull‑up resistor on the DHT22 data line. Add a 4.7 kΩ – 10 kΩ resistor between DATA and 3.3 V. Also, use short wires (<20 cm).
  • Blank OLED display: Check the I2C address. Run i2c scan in the logs to see if 0x3C is found. Some clones use 0x3D. If nothing appears, verify VCC and GND; the SSD1306 can’t tolerate 5 V on its I2C pins, so don’t power it from the VIN pin.
  • Upload fails, “Timed out waiting for packet”: GPIO0 and GPIO2 strapping pins mess with boot. Move your relays to GPIO26/27 (or any clean GPIO 12, 13, 14, 32, 33) and try again. Also, try holding the BOOT button while flashing.
  • ESP32 reboots when relay toggles: The relay coil draws a spike of current. Power the coil from a separate 5 V rail (the VIN pin) with the JD‑VCC jumper removed, and add a 100 µF capacitor across the relay power supply.

Enhancements & Next Steps

This weather station is just the start. Once you have stable automation, you can:

  • Log data over Wi‑Fi: In the ESPHome YAML, add an mqtt client and push readings to a broker. I later connected the station to Home Assistant, where I combined multiple temperature sensors—including the Aqara ones I set up with Zigbee2MQTT back when I wrote this guide. Home Assistant then becomes the central brain, overriding the local automation when no one’s home.
  • Add visual alerts: I use Grafana to plot long‑term temperature trends and fired‑off alerts with custom messages. If that sounds useful, my Grafana alerting walkthrough shows how to template your own.
  • Deep sleep for battery operation: If you don’t need real‑time switching, put the ESP32 into deep sleep and wake it every 10 minutes. Combine with a relay that latches (use a bistable relay module).
  • Upgrade the sensor: Swap the DHT22 for a BME280 to get barometric pressure. The I²C wiring stays identical—just change the sensor platform in ESPHome.
  • Safety first: Add a temperature fail‑safe: if the sensor reading fails, turn off the relays. In ESPHome, you can use on_value automation with sensor.timestamp to detect stale data.

For a simpler indoor‑only monitoring setup that doesn’t need relay control, I previously documented a pure monitoring build using the Xiaomi Mijia sensor and ESPHome: How to Monitor Your Home Temperature.

FAQ

Can I use a DHT11 instead of the DHT22?
Yes, but the DHT11 has ±2 °C accuracy and a slower update interval, while the DHT22 delivers ±0.5 °C. If you only need approximate readings, the DHT11 will work; just change model: DHT22 to model: DHT11 in the YAML. Personally, I’d spend the extra dollar for the DHT22—when you’re controlling a heater, half a degree matters.

Why is my relay clicking but the appliance doesn’t turn on?
Check that you’re using the normally‑open (NO) terminal, not the normally‑closed (NC). Also make sure the high‑voltage circuit is complete—I once forgot to plug the appliance into the relay output. Finally, verify that the relay coil is actually switching the contacts; sometimes the mechanical armature sticks if the coil power is too weak.

Can I control more than two appliances?
Absolutely. Use an ESP32 with more free GPIOs and connect a 4‑ or 8‑channel relay module. Just be mindful of the total current draw of the relay coils—you may need an external 5 V supply. ESPHome supports up to 128 switch instances.

How do I power the ESP32 and relay from the same 5 V USB supply?
Take 5 V from the USB input (VIN pin) to power the relay coils (JD‑VCC), and let the ESP32’s onboard regulator provide 3.3 V to the logic side. This works as long as your USB source can deliver enough current—typically 2 A for a 2‑channel relay board. I’ve run this 24/7 with a standard 5 V / 2 A phone charger without issues.

Is it safe to control high voltage with this relay module?
The module itself is designed to handle up to 250 VAC at 10 A, but your wiring is what determines safety. Always mount the relay and high‑voltage terminals inside an insulating enclosure, use proper cable glands, and include a dedicated fuse or circuit breaker. If you’re not comfortable with mains electricity, ask an electrician—no tutorial is worth a shock.

My ESPHome configuration fails to find the SSD1306 after a while. What’s wrong?
I’ve seen this with certain clone displays that have a slow power‑on reset. Add reset_pin: GPIO16 (or any unused output pin) and set reset_duration: 10ms in the ssd1306_i2c component. Also, ensure the I2C wires are short and not routed near the relay’s high‑current paths, which can induce noise.


Now that your ESP32 weather station controls appliances, you’ve got a solid foundation for an energy‑efficient, automated space. Keep tinkering—every relay click feels like a small victory.