This capstone brings everything in the path together in one model smart home. A white LED is the ceiling lamp. The DC motor from the kit, driven by the L293D chip, is a fan. The DHT11 measures the temperature, and a reed switch watches the front door. One Arduino Cloud dashboard controls the lot: switch the lamp and the fan, read the temperature, see if the door is open, and arm an alarm that sounds the buzzer if the door opens while you are away. In auto mode the fan starts by itself when the house gets warm.
What you'll learn
- How to plan a bigger IoT device within five cloud variables
- How to drive a DC motor with the L293D from the cloud
- How to combine automatic rules with manual control
- How to build the project in stages and test each part
What you need
- ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
- White LED and 1 resistor, 220 Ω (ESP32 IoT Starter Kit)
- L293D motor driver chip and 3–6 V DC motor with fan blade (ESP32 IoT Starter Kit)
- DHT11 temperature and humidity sensor (ESP32 IoT Starter Kit)
- Passive buzzer (ESP32 IoT Starter Kit)
- Reed switch module (45-in-1 Sensor Kit) and a small magnet
- A 2.4 GHz Wi-Fi network
- The printed parts from the 3D printing box below (model house), or the cardboard version described there
- Breadboard and jumper wires (ESP32 IoT Starter Kit)
Wiring

| From | To |
|---|---|
| ESP32 GPIO 13 | 220 Ω resistor, then the white LED's long leg |
| LED short leg | GND |
| L293D EN1 (pin 1) | ESP32 GPIO 25 |
| L293D IN1 (pin 2) | ESP32 GPIO 26 |
| L293D IN2 (pin 7) | ESP32 GPIO 32 |
| L293D OUT1 and OUT2 (pins 3 and 6) | The two wires of the DC motor |
| L293D pins 4, 5, 12, 13 | GND |
| L293D VCC1 (pin 16) and VCC2 (pin 8) | 5V |
| DHT11 S (data) | ESP32 GPIO 27 |
| DHT11 + and − | 3V3 and GND |
| Reed switch module S | ESP32 GPIO 33 |
| Reed switch module + and − | 3V3 and GND |
| Passive buzzer + | ESP32 GPIO 23 |
| Passive buzzer − | GND |
Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.
The motor driver and the fan are wired exactly as in the Blynk thermostat fan, which explains how the L293D works. The motor runs on the 5V pin, so use a good USB port.
Set up Arduino Cloud
In Arduino Cloud, open Things, create a new Thing called Smart Home, link it to your ESP32 device and fill in its network settings. Then add these variables. Lesson 1 of this path shows each step with pictures in words.
| Variable | Type | Permission | Update |
|---|---|---|---|
| lamp | Light | Read & Write | On change |
| fan | Integer number (0–100 %) | Read & Write | On change |
| temperature | Temperature sensor (°C) | Read only | Every 30 s |
| door | Contact sensor | Read only | On change |
| mode | Integer number (0 home, 1 auto, 2 away) | Read & Write | On change |
Open Dashboards, create a dashboard and add a Switch (lamp), a Slider 0–100 (fan), a Gauge (temperature), a Status widget (door) and a Value or Stepper widget from 0 to 2 (mode), each linked to its variable. The same dashboard appears in the free Arduino IoT Remote app on your phone.
Build it in stages
- Lamp. Wire the LED and upload. The lamp switch works.
- Fan. Add the L293D and the motor. The fan slider sets the speed.
- Climate. Add the DHT11. Set mode to 1 (auto): the fan starts above 26 °C and stops below 25 °C.
- Door and alarm. Add the reed switch and the buzzer. Set mode to 2 (away) and open the door: the alarm sounds until you set mode back to 0.
The sketch
Arduino Cloud writes the sketch's first version for you, with a thingProperties.h tab that lists your variables and a Secret tab with your Wi-Fi details and device key. In the Thing, open the Sketch tab, click Open full editor, replace the main sketch with the code below and upload. Leave the other tabs as they are.
Add the DHT sensor library by Adafruit under Libraries. Start the sketch with the front door closed.
#include "thingProperties.h"
#include <DHT.h>
const int LAMP_PIN = 13, EN_PIN = 25, IN1_PIN = 26, IN2_PIN = 32;
const int DHT_PIN = 27, REED_PIN = 33, BUZZER_PIN = 23;
const float FAN_ON = 26.0, FAN_OFF = 25.0; // auto mode
const int HOME = 0, AUTO = 1, AWAY = 2;
DHT dht(DHT_PIN, DHT11);
int closedReading;
bool alarmOn = false;
unsigned long lastClimate = 0;
void setFan(int percent) {
digitalWrite(IN1_PIN, HIGH); // always the same direction
digitalWrite(IN2_PIN, LOW);
int duty = percent == 0 ? 0 : map(percent, 1, 100, 120, 255); // small values can't start the motor
analogWrite(EN_PIN, duty);
}
void climate() {
float t = dht.readTemperature();
if (isnan(t)) return;
temperature = t;
if (mode != AUTO) return;
if (t > FAN_ON && fan == 0) fan = 100; // the dashboard slider follows
if (t < FAN_OFF && fan != 0) fan = 0;
setFan(fan);
}
void setup() {
Serial.begin(115200);
delay(1500);
pinMode(LAMP_PIN, OUTPUT);
pinMode(EN_PIN, OUTPUT);
pinMode(IN1_PIN, OUTPUT);
pinMode(IN2_PIN, OUTPUT);
pinMode(REED_PIN, INPUT);
closedReading = digitalRead(REED_PIN);
dht.begin();
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(2); // connection messages in the Serial Monitor
ArduinoCloud.printDebugInfo();
}
void loop() {
ArduinoCloud.update();
bool open = digitalRead(REED_PIN) != closedReading;
if (open != door) {
door = open;
Serial.println(open ? "Door open" : "Door closed");
if (open && mode == AWAY) alarmOn = true; // somebody came in while you were away
}
if (alarmOn) {
bool high = (millis() / 250) % 2;
tone(BUZZER_PIN, high ? 1400 : 900);
digitalWrite(LAMP_PIN, high); // the lamp flashes too
}
if (millis() - lastClimate >= 10000) {
lastClimate = millis();
climate();
}
}
void onLampChange() {
if (!alarmOn) digitalWrite(LAMP_PIN, lamp);
}
void onFanChange() {
setFan(fan);
}
void onModeChange() {
if (mode != AWAY && alarmOn) { // leaving away mode switches the alarm off
alarmOn = false;
noTone(BUZZER_PIN);
digitalWrite(LAMP_PIN, lamp);
}
Serial.printf("Mode %d\n", (int)mode);
lastClimate = 0;
}
For reference, this is the thingProperties.h that Arduino Cloud creates from the variables above. Yours has your own device ID, and may use an older but equally valid style such as addProperty(led, READWRITE, ON_CHANGE, onLedChange).
// Code generated by Arduino Cloud (yours has your own device ID)
#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>
const char DEVICE_LOGIN_NAME[] = "YOUR_DEVICE_ID";
const char SSID[] = SECRET_SSID; // from the Secret tab
const char PASS[] = SECRET_OPTIONAL_PASS;
const char DEVICE_KEY[] = SECRET_DEVICE_KEY;
void onLampChange();
void onFanChange();
void onModeChange();
CloudLight lamp;
int fan;
CloudTemperatureSensor temperature;
CloudContactSensor door;
int mode;
void initProperties() {
ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME);
ArduinoCloud.setSecretDeviceKey(DEVICE_KEY);
ArduinoCloud.addProperty(lamp, Permission::ReadWrite).onUpdate(onLampChange);
ArduinoCloud.addProperty(fan, Permission::ReadWrite).onUpdate(onFanChange);
ArduinoCloud.addProperty(temperature, Permission::Read).publishEvery(30);
ArduinoCloud.addProperty(door, Permission::Read).publishOnChange(0);
ArduinoCloud.addProperty(mode, Permission::ReadWrite).onUpdate(onModeChange);
}
WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);How it works
Five variables is the free plan's limit, so the design has to be smart. Instead of separate switches for "auto" and "away", one mode number covers three situations: 0 at home (everything manual), 1 automatic fan, 2 away with the alarm armed.
The fan speed is a percentage, but a DC motor doesn't start at 1 % of its power. setFan() maps 1–100 % onto the PWM range 120–255, where the motor actually turns. In auto mode the fan follows the temperature with hysteresis: on above 26 °C, off below 25 °C. When the ESP32 changes fan itself, the dashboard slider moves too.
The alarm latches: once the door opens in away mode, alarmOn stays true even if the door closes again, until you change the mode from your phone. Real alarm systems work the same way, so a burglar can't silence it by shutting the door.
Try this next
- Switch the lamp on automatically when the door opens after dark.
- Use Arduino Cloud triggers (on a paid plan) or ntfy to send an alert when the alarm goes off.
- Add a second Thing for a garden sensor, and show both on one dashboard.
Troubleshooting
- The device stays "Offline": open the Serial Monitor at 115200 baud. Check the Wi-Fi name and password in the Secret tab (2.4 GHz only) and that the secret device key is the one you saved when you added the device.
- Compile error about a variable: the variable names in the sketch must match the ones in your Thing exactly, including capital letters. Rename the Thing's variable or the sketch's to match.
- The fan hums but doesn't turn: raise the lowest duty value 120, or give it a small push.
- The ESP32 restarts when the fan starts: the motor draws a lot of current. Use a powered USB hub or a good USB charger.
- The alarm sounds at once in away mode: the door was open when the ESP32 started. Restart it with the door shut.
- A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.