Control a Smart Fan with ESP32 and Home Assistant Using Temperature Triggers
I’ve always been fascinated with making my home smarter, especially when it comes to energy efficiency and comfort. There’s something deeply satisfying about having your home respond to environmental conditions without lifting a finger. In this tutorial, I’ll show you how I built a system that automatically controls a fan based on room temperature using an ESP32 and Home Assistant.
Why I Built This System
Living in a climate with hot summers, I found myself constantly adjusting fans throughout the day. The bedroom would get stuffy in the afternoon, but I didn’t want the fan running all day unnecessarily. Commercial smart fans either didn’t offer temperature-based triggers or were surprisingly expensive. So I decided to build my own solution using components I had lying around from previous projects.
What You’ll Need
Before we dive in, here’s what you’ll need to follow along:
- ESP32 development board (I used the ESP32 DevKit C, but any variant will work)
- DHT22 temperature and humidity sensor (the DHT11 works too but is less accurate)
- 5V relay module (to safely control the fan)
- Jumper wires (male-to-female and male-to-male)
- Breadboard (for prototyping, optional but helpful)
- USB cable for powering the ESP32
- A fan that can be modified for external control (I used a simple desk fan)
- Home Assistant instance (I’m running version 2023.8)
Safety Note: When working with mains electricity for the fan, exercise extreme caution. If you're not comfortable with electrical work, consider using a low-voltage DC fan instead or consult an electrician.
Step 1: Wiring the Components
Let’s start by connecting our components. The wiring is straightforward:
Connect the DHT22 sensor:
- VCC to 3.3V on ESP32
- GND to GND on ESP32
- DATA to GPIO 4 on ESP32 (you can use any GPIO)
Connect the relay module:
- VCC to 5V on ESP32
- GND to GND on ESP32
- IN to GPIO 5 on ESP32
For the fan connection:
- Carefully wire the fan’s power through the relay’s normally open (NO) and common (COM) terminals
Here’s a diagram of how everything connects:
I found that adding a small capacitor (100nF) between the data line and ground of the DHT22 helps stabilize readings if you experience inaccurate temperature measurements.
Step 2: Flashing ESPHome to the ESP32
Now for the software part. I’m using ESPHome because it makes configuring ESP devices for Home Assistant incredibly simple.
First, make sure you have ESPHome installed in your Home Assistant environment. If you don’t, you can add it via the Home Assistant add-on store.
Create a new ESPHome configuration:
esphome:
name: smart-fan-controller
platform: ESP32
board: nodemcu-32s
wifi:
ssid: "Your_WiFi_SSID"
password: "Your_WiFi_Password"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Smart-Fan-Controller Fallback Hotspot"
password: "fallback_password"
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "your_encryption_key"
ota:
password: "your_ota_password"
# Sensor configuration
sensor:
- platform: dht
pin: GPIO4
temperature:
name: "Room Temperature"
id: room_temperature
filters:
- offset: -1.0 # Calibrate if needed
humidity:
name: "Room Humidity"
update_interval: 30s
# Relay configuration
switch:
- platform: gpio
pin: GPIO5
name: "Fan Relay"
id: fan_relay
restore_mode: ALWAYS_OFF # Safety first - don't restore to ON after power loss
Replace the WiFi credentials with your own, and generate encryption keys using esphome secrets
or manually.
Now compile and flash this to your ESP32. If you’re using ESPHome Dashboard, you can do this with a single click. Otherwise, use the command line:
esphome run smart-fan-controller.yaml
Step 3: Integrating with Home Assistant
Once flashed, your ESP32 should automatically appear in Home Assistant’s discovered devices. If it doesn’t, check your WiFi connection and ESPHome logs.
The entities should appear as:
sensor.room_temperature
sensor.room_humidity
switch.fan_relay
I recommend giving these entities friendly names in Home Assistant for easier reference later. I named mine "Office Temperature," "Office Humidity," and "Desk Fan."
Step 4: Creating the Automation
Now for the fun part - creating the automation that will control the fan based on temperature.
In Home Assistant, go to Settings > Automations & Scenes > Create Automation.
I set up mine with the following trigger:
trigger:
- platform: numeric_state
entity_id: sensor.room_temperature
above: 24 # Temperature in Celsius
And the action:
action:
- service: switch.turn_on
target:
entity_id: switch.fan_relay
Then create a second automation to turn the fan off when the temperature drops:
trigger:
- platform: numeric_state
entity_id: sensor.room_temperature
below: 23 # Adding hysteresis to prevent rapid cycling
action:
- service: switch.turn_off
target:
entity_id: switch.fan_relay
I added a 1°C difference between the on and off thresholds (called hysteresis) to prevent the fan from rapidly cycling on and off when the temperature is right at the threshold.
Step 5: Testing and Refinement
After setting up, test your automation by either changing the temperature thresholds or artificially warming up the sensor (carefully with your hands) to trigger the fan.
I found that adding a delay prevented short temperature spikes from triggering the fan:
trigger:
- platform: numeric_state
entity_id: sensor.room_temperature
above: 24
for:
minutes: 5 # Only trigger if temperature stays above for 5 minutes
Troubleshooting Common Issues
Sensor reading inaccuracies: The DHT22 can be affected by heat from the ESP32 itself. Keep them separated if possible.
WiFi connectivity issues: If your ESP32 keeps disconnecting, try adding a static IP assignment in your ESPHome configuration:
wifi:
# ... your existing wifi config
manual_ip:
static_ip: 192.168.1.100
gateway: 192.168.1.1
subnet: 255.255.255.0
- Relay not switching: Double-check your GPIO pin assignment and ensure your relay is activated by LOW signal if it’s an active-low relay.
Enhancing Your Setup
Once you have the basic setup working, here are some enhancements I’ve added:
Multiple temperature sensors: Average readings from multiple rooms for better control.
Occupancy detection: Only activate the fan when someone is in the room using motion sensors.
Time-based thresholds: Different temperature thresholds for day and night.
Manual override: An input boolean in Home Assistant that allows temporary manual control without disabling the automation.
Wrapping Up
Building this temperature-triggered smart fan system has not only made my home more comfortable but also saved energy by ensuring the fan only runs when needed. The best part is that once set up, it works completely autonomously.
If you enjoyed this project, you might want to check out my other articles on monitoring home temperature with ESP32 and setting up Zigbee2MQTT with Aqara sensors.
Frequently Asked Questions
Q: Can I use a different temperature sensor? A: Absolutely! ESPHome supports many sensors including DS18B20, BME280, and LM35. Just update the sensor configuration in your ESPHome YAML.
Q: What if I want to control a ceiling fan? A: The same principles apply, but you’ll need a relay rated for higher current. Consider using a solid-state relay for better reliability with inductive loads.
Q: Can I make the fan speed variable based on temperature? A: Yes, but you’ll need a fan with speed control and a different approach. For DC fans, you could use PWM. For AC fans, you might need a specialized controller.
Q: How accurate is the DHT22 sensor? A: The DHT22 has an accuracy of ±0.5°C, which is sufficient for room temperature control. For better accuracy, consider a DS18B20 or BME280 sensor.
Q: Can I use an ESP8266 instead of an ESP32? A: Yes, the ESP8266 works perfectly for this application. Just change the platform in your ESPHome configuration to ESP8266 and adjust the board type accordingly.