A thermostat measures the temperature and switches something on or off to keep it right. In this lesson you build a smart fan: the DS18B20 temperature module measures the air, and when it's warmer than the target you set in the app, the fan starts. The warmer it gets, the faster it spins. Switch to manual mode and you control the speed yourself with a slider.
What you'll learn
- How to drive a DC motor with the L293D and PWM
- How to read the DS18B20 without blocking the sketch
- How to build automatic and manual modes
- How to turn a temperature difference into a fan speed
What you need
- ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
- DS18B20 temperature module (45-in-1 Sensor Kit)
- L293D motor driver and 3–6 V DC motor (ESP32 IoT Starter Kit)
- A small piece of card or tape to make a fan blade (optional)
- Breadboard and jumper wires (ESP32 IoT Starter Kit)
- A free Blynk account and the Blynk IoT app on a phone
- A 2.4 GHz Wi-Fi network
Wiring

| From | To |
|---|---|
| DS18B20 module S | ESP32 GPIO 33 |
| DS18B20 module + | 3V3 |
| DS18B20 module − | GND |
| L293D pin 1 (EN1) | ESP32 GPIO 25 |
| L293D pin 2 (IN1) | ESP32 GPIO 26 |
| L293D pin 7 (IN2) | ESP32 GPIO 27 |
| L293D pins 3 and 6 (OUT1, OUT2) | The two motor wires |
| L293D pins 4, 5, 12, 13 | GND |
| L293D pins 8 and 16 (VCC2, VCC1) | 5V |
Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.
The notch on the L293D marks pin 1. The DS18B20 module runs from 3V3 so that its signal is safe for the ESP32, while the L293D and the motor run from 5V. The bottom and top rails of the breadboard carry 5V and GND; the DS18B20 gets its 3V3 from its own wire.
Set up Blynk
In the Blynk console, create a new template called Thermostat fan (hardware ESP32, connection type Wi-Fi) and add these datastreams. Lesson 1 shows each step in detail.
| Virtual pin | Name | Data type | Range | Phone widget |
|---|---|---|---|---|
| V0 | Temperature | Double | 0 – 50, units °C | Gauge |
| V1 | Auto mode | Integer | 0 – 1 | Button (switch mode) |
| V2 | Manual speed | Integer | 0 – 100, units % | Slider |
| V3 | Target | Integer | 15 – 35, units °C | Slider |
| V4 | Fan speed | Integer | 0 – 100, units % | Gauge |
Save the template, create a new device from it and copy its three BLYNK_… lines. In the phone app, open the device, tap the wrench icon and add two Gauges (V0, V4), a Button in switch mode (V1) and two Sliders (V2, V3). Link each widget to its datastream.

The sketch
You also need the OneWire and DallasTemperature libraries from the DS18B20 lesson, and ESP32 board package 3.0 or newer for analogWrite().
Replace the three BLYNK_… lines at the top with the ones from your device's Device info page, and add your Wi-Fi name and password (2.4 GHz only). The BLYNK_… lines must stay above #include <BlynkSimpleEsp32.h>.
#define BLYNK_TEMPLATE_ID "YOUR_TEMPLATE_ID"
#define BLYNK_TEMPLATE_NAME "Thermostat fan"
#define BLYNK_AUTH_TOKEN "YOUR_AUTH_TOKEN"
#define BLYNK_PRINT Serial // show connection messages in the Serial Monitor
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>
char ssid[] = "YOUR_WIFI_NAME";
char pass[] = "YOUR_WIFI_PASSWORD";
const int TEMP_PIN = 33;
const int EN_PIN = 25; // speed (PWM)
const int IN1_PIN = 26; // direction
const int IN2_PIN = 27;
OneWire oneWire(TEMP_PIN);
DallasTemperature sensors(&oneWire);
BlynkTimer timer;
bool autoMode = true;
int manualSpeed = 0; // %
int target = 25; // °C
bool fanRunning = false;
BLYNK_WRITE(V1) { autoMode = param.asInt(); }
BLYNK_WRITE(V2) { manualSpeed = param.asInt(); }
BLYNK_WRITE(V3) { target = param.asInt(); }
BLYNK_CONNECTED() { Blynk.syncVirtual(V1, V2, V3); }
void setFan(int percent) {
digitalWrite(IN1_PIN, HIGH); // always the same direction
digitalWrite(IN2_PIN, LOW);
analogWrite(EN_PIN, map(percent, 0, 100, 0, 255));
Blynk.virtualWrite(V4, percent);
}
void control() {
float temp = sensors.getTempCByIndex(0); // result of the last request
sensors.requestTemperatures(); // start the next reading
if (temp == DEVICE_DISCONNECTED_C) {
Serial.println("DS18B20 not found");
return;
}
Blynk.virtualWrite(V0, temp);
int speed;
if (autoMode) {
// switch on at the target, off again 0.5 °C below it
if (temp >= target) fanRunning = true;
if (temp < target - 0.5) fanRunning = false;
// 50 % at the target, rising to 100 % at 3 °C above it
float over = temp - target;
speed = fanRunning ? constrain(50 + (int)(over * 50 / 3), 50, 100) : 0;
} else {
speed = manualSpeed;
}
setFan(speed);
Serial.printf("%.1f °C, fan %d %%\n", temp, speed);
}
void setup() {
Serial.begin(115200);
pinMode(EN_PIN, OUTPUT);
pinMode(IN1_PIN, OUTPUT);
pinMode(IN2_PIN, OUTPUT);
sensors.begin();
sensors.setWaitForConversion(false); // don't wait 0.75 s for each reading
sensors.requestTemperatures();
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
timer.setInterval(2000L, control);
}
void loop() {
Blynk.run();
timer.run();
}
To test it, set the target one degree above the room temperature and hold the sensor between your fingers. After a few seconds the fan starts, and it speeds up as the sensor warms.
How it works
The L293D is an H-bridge: IN1 and IN2 choose the direction, and the PWM signal on EN1 sets how much of the time the motor gets power, which sets its speed. The DS18B20 needs about 0.75 s to measure. Normally the library waits during that time, which would freeze Blynk. With setWaitForConversion(false) the sketch starts a measurement, goes on with its work, and collects the result two seconds later. In auto mode the fan switches on at the target and off 0.5 °C below it (hysteresis again), and its speed rises with every degree above the target. It never runs below 50 %, because small motors often don't start at low power.
Try this next
- Add a second datastream that shows "Cooling" or "Idle" as text.
- Add a Chart with the temperature and the fan speed together.
- Use IN1 and IN2 to make the fan run backwards for two seconds before it stops.
Troubleshooting
-
The device shows "Offline" in the app: check the Serial Monitor at 115200 baud. "Invalid auth token" means the
BLYNK_AUTH_TOKENline is wrong; if it never connects, check the Wi-Fi name and password, and that your network is 2.4 GHz. - "DS18B20 not found": check that S is on GPIO 33, + on 3V3 and − on GND.
- The motor hums but doesn't turn: its speed is too low to start. Give it a little push or raise the minimum speed.
- The ESP32 resets when the motor starts: the motor draws too much from USB. Use a powered USB port or hub, and keep the motor small.