Smart Fan Speed Controller: PWM with Temperature Sensor
A smart fan speed controller that automatically adjusts fan speed based on room temperature is one of the most practical home automation projects for Indian homes. During harsh summers in cities like Nagpur, Hyderabad, or Jaisalmer, a fan running at full speed all night disturbs sleep, while a fan that slows down as the room cools overnight gives perfect comfort. This project uses PWM (pulse width modulation) and a DHT22 or NTC thermistor to create a fully automatic temperature-controlled fan — controllable via Alexa, Google Home, or Home Assistant.
We cover two variants: a low-voltage DC fan controller (for 12V computer fans and exhaust fans) and a 230V AC ceiling fan controller using TRIAC dimming — the most common scenario in Indian households.
PWM vs TRIAC: Which to Use?
Understanding the difference is essential before building:
| Feature | PWM (DC fans) | TRIAC (AC fans) |
|---|---|---|
| Fan type | 12V/24V DC fans | 230V AC ceiling fans |
| Control method | Duty cycle 0-100% | Phase angle cutting |
| Smooth speed range | Excellent | Good (above 20%) |
| Fan noise | None | Slight hum at low speeds |
| Safety complexity | Low (safe DC) | High (230V AC) |
DC Fan PWM Controller (12V)
For computer case fans, exhaust fans, or 12V blowers, PWM control is simple and safe. Use an N-channel MOSFET (IRLZ44N) as the switch:
Components:
- ESP32 or ESP8266 NodeMCU
- IRLZ44N or 2N7000 N-channel MOSFET (logic-level gate, works with 3.3V)
- 10k gate resistor, 10k pull-down resistor
- Flyback diode (1N4007) across motor terminals
- DHT22 temperature sensor
- 12V power supply for fan, 5V for ESP
const int FAN_PIN = 16; // GPIO16 for PWM
const int DHT_PIN = 4; // DHT22 data pin
// Temperature to fan speed mapping
int tempToSpeed(float temp) {
if (temp < 26) return 0; // Off below 26 degrees C
if (temp < 28) return 64; // 25% speed 26-28 C
if (temp < 30) return 128; // 50% speed 28-30 C
if (temp < 33) return 192; // 75% speed 30-33 C
return 255; // 100% above 33 C
}
void setup() {
ledcAttachPin(FAN_PIN, 0);
ledcSetup(0, 25000, 8); // 25 kHz, 8-bit resolution
}
void loop() {
float temp = dht.readTemperature();
int speed = tempToSpeed(temp);
ledcWrite(0, speed);
delay(10000);
}
The 25 kHz PWM frequency is above human hearing range — fans run silently without the buzzing noise that lower PWM frequencies cause. ESP32’s LEDC peripheral is ideal for this application.
Recommended Product
ESP32 Development Board
ESP32 has four hardware PWM channels (LEDC) that can run at 25 kHz for silent fan control. Its dual-core processor handles temperature monitoring on one core and WiFi/home automation on the other — no timing interference.
AC Ceiling Fan TRIAC Controller
Indian ceiling fans run on 230V AC at 50 Hz. Speed control requires a TRIAC that fires at a variable phase angle — the later in the AC cycle it fires, the less power reaches the fan motor and the slower it spins. This is identical to the mechanism used in traditional rotary fan regulators.
Components:
- BT136 or BT137 TRIAC (600V, 4A rating)
- MOC3021 or MOC3041 optocoupler (for isolation between ESP and mains)
- Zero-crossing detector (4N25 optocoupler + 22k resistor)
- 330-ohm gate resistor
- Snubber network (100-ohm + 100nF capacitor) for inductive fan loads
// Zero-crossing interrupt for TRIAC control
volatile bool zeroCross = false;
const int ZC_PIN = 2; // Zero crossing input
const int TRIAC_PIN = 3; // TRIAC gate output
int fanSpeed = 50; // 0-100%, maps to phase angle
void IRAM_ATTR zeroCrossISR() {
zeroCross = true;
}
void setup() {
pinMode(ZC_PIN, INPUT_PULLUP);
pinMode(TRIAC_PIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(ZC_PIN),
zeroCrossISR, RISING);
}
void loop() {
if (zeroCross) {
zeroCross = false;
// Delay proportional to (100 - speed)
// At 50 Hz, half-cycle = 10000 microseconds
int delayUs = (100 - fanSpeed) * 100;
delayMicroseconds(delayUs);
digitalWrite(TRIAC_PIN, HIGH);
delayMicroseconds(50);
digitalWrite(TRIAC_PIN, LOW);
}
}
Temperature Sensing with DHT22
Place the DHT22 sensor away from the fan airstream — measure ambient room temperature, not the air the fan is pushing. Mount it at the opposite wall from the fan, at sitting/sleeping height (1-1.5 metres from floor):
#include <DHT.h>
DHT dht(4, DHT22);
void setup() {
dht.begin();
}
float getAveragedTemp() {
float sum = 0;
int count = 0;
for (int i = 0; i < 5; i++) {
float t = dht.readTemperature();
if (!isnan(t)) { sum += t; count++; }
delay(200);
}
return count > 0 ? sum / count : 25.0;
}
Averaging 5 readings eliminates sensor noise and false triggers. DHT22 accuracy is +/- 0.5 degrees C — sufficient for comfort-based fan control where 1-degree precision is acceptable.
ESPHome Fan Entity
For DC fan control with ESPHome, the fan platform creates a speed-controllable fan entity in Home Assistant:
esphome:
name: smart-fan
platform: ESP32
board: esp32dev
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
logger:
sensor:
- platform: dht
pin: GPIO4
model: DHT22
temperature:
name: "Room Temperature"
id: room_temp
humidity:
name: "Room Humidity"
update_interval: 30s
output:
- platform: ledc
pin: GPIO16
frequency: 25000
id: fan_output
fan:
- platform: speed
output: fan_output
name: "Smart Ceiling Fan"
speed_count: 5 # 5 speed steps like a real fan regulator
The fan entity appears in Home Assistant with speed slider 1-5, on/off toggle, and can be controlled by voice (“Alexa, set the bedroom fan to speed 3”).
Recommended Product
ESP8266 WiFi Relay Module
For a simpler approach, use a relay module to provide on/off control of any fan while adding a physical electronic regulator for speed. The ESP8266 relay gives you WiFi scheduling and voice control without dealing with TRIAC phase angle complexity.
PID Temperature Control
A basic step-function speed mapping is simple but may cause uncomfortable oscillation — fan suddenly jumps from 25% to 75% speed as temperature crosses a threshold. A PID (proportional-integral-derivative) controller provides smooth, gradual speed adjustment:
// Simple P-controller for fan speed
float kP = 15.0; // Proportional gain
float targetTemp = 27.0; // Target room temperature
int calculateFanSpeed(float currentTemp) {
float error = currentTemp - targetTemp;
if (error <= 0) return 0; // At or below target: off
int speed = (int)(kP * error);
return constrain(speed, 0, 100);
}
This proportional controller increases fan speed smoothly as room temperature rises above the target. At 27°C (setpoint), fan is off. At 28°C (1 degree above), fan runs at 15%. At 30°C, fan runs at 45%. At 33°C (6 degrees above), fan runs at 90%.
Home Assistant Dashboard
Build an automation to enforce temperature-based fan speed in Home Assistant:
automation:
- alias: "Auto Fan Speed by Temperature"
trigger:
- platform: state
entity_id: sensor.room_temperature
action:
- choose:
- conditions:
- condition: numeric_state
entity_id: sensor.room_temperature
below: 26
sequence:
- service: fan.turn_off
target:
entity_id: fan.smart_ceiling_fan
- conditions:
- condition: numeric_state
entity_id: sensor.room_temperature
above: 30
sequence:
- service: fan.set_percentage
target:
entity_id: fan.smart_ceiling_fan
data:
percentage: 100
Recommended Product
Raspberry Pi Zero W
Run Home Assistant on a Raspberry Pi Zero W for local smart fan control with no cloud dependency. The Pi handles all automations locally — fan speed adjusts within 5 seconds of temperature change without waiting for any internet round trip.
Frequently Asked Questions
Can I control an existing Usha or Orient ceiling fan with this?
Yes. Indian ceiling fans (Usha, Orient, Crompton, Bajaj, Havells) all run on 230V AC single-phase. The TRIAC controller works with any capacitor-run induction motor ceiling fan. Ensure the TRIAC is rated for at least twice the fan’s current draw (typically 0.4-0.6 A for a 75W fan, so use a 2A TRIAC minimum).
Why does the fan make a buzzing noise at low TRIAC speeds?
Buzzing at low speeds is normal with TRIAC control on inductive motors — phase angle cutting creates harmonic distortion that the motor coil vibrates at. Add a proper snubber network (100-ohm resistor + 100 nF capacitor in series across the TRIAC) to reduce this. Setting a minimum speed of 30-40% also helps.
What is the minimum temperature the fan should turn on?
For Indian comfort standards (ASHRAE adaptive comfort model for warm-humid climates), fans should run above 26-27°C. Below 26°C, fan air movement feels cold and uncomfortable. The automation should turn off the fan when temperature drops below this threshold.
Can the DHT22 be mounted inside the switch box?
No. Switch boxes are too small and get warm from wiring heat. Mount the DHT22 sensor in open air, away from direct sunlight, the fan airstream, and AC vents. A small white plastic enclosure on the wall at sitting height works well.
Will this work with BLDC inverter fans?
BLDC fans (like Crompton Energion, Atomberg Efficio) have their own electronics and speed control — they cannot be controlled with a TRIAC. Use a relay for on/off control only, and use the fan’s IR remote (with an ESP32 IR blaster) for speed changes.
Build Your Smart Fan Controller
Automatic temperature-based fan speed for every room in your home. Browse ESP32 boards, sensors, and relay modules at Zbotic to get started today.
Add comment