Make a smart switch with a timer

Switch a relay from the Blynk app or a button on the breadboard, keep both in sync, and switch it off automatically with a countdown timer.
  • Level:Advanced
  • Duration: 55 min
  • Ages 13+
  • Platform: ESP32

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Make a smart switch with a timer – EEMENTOR STEM™ lesson

Smart plugs switch things on from an app and off again with a timer. In this lesson you build the electronics behind one: a relay you control from the Blynk app or from a push button on the breadboard. Both always show the same state, and a countdown switches the relay off after the time you set. For safety, this project switches low-voltage things only.

What you'll learn

  • How to keep a physical button and an app switch in sync
  • How active-LOW relay modules work
  • How to build a countdown timer with millis()
  • Why the device, not the app, decides the state after a restart

What you need

  • ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
  • 2-channel relay module (ESP32 IoT Starter Kit)
  • Button module (45-in-1 Sensor Kit)
  • 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

Safety first

Never connect the relay to mains electricity (the sockets in your wall). This lesson only switches the relay itself: you hear it click and see its LED. To switch a real load, use a battery-powered one, such as the DC motor with the 9 V battery from the kit.

Wiring

Breadboard wiring diagram: Make a smart switch with a timer
Breadboard view. Check each connection against the wiring table below.
From To
Relay VCC 5V
Relay GND GND
Relay IN1 ESP32 GPIO 23
Button module S ESP32 GPIO 27
Button module + 3V3
Button module − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

Set up Blynk

In the Blynk console, create a new template called Smart switch (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 Power Integer 0 – 1 Button (switch mode)
V1 Auto-off Integer 0 – 60, units min Slider
V2 Timer String n/a Value Display

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 a Button in switch mode (V0), a Slider (V1) and a Value Display (V2). Link each widget to its datastream.

Example Blynk web dashboard and phone app for: Make a smart switch with a timer
Example dashboard with sample values. Your layout may look different.

The sketch

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>.

Some versions of this module switch their output to HIGH when they trigger, others to LOW. The sketch reads the output when it starts (keep things still for a moment) and treats any change from that resting state as a trigger, so it works with both.

#define BLYNK_TEMPLATE_ID "YOUR_TEMPLATE_ID"
#define BLYNK_TEMPLATE_NAME "Smart switch"
#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>

char ssid[] = "YOUR_WIFI_NAME";
char pass[] = "YOUR_WIFI_PASSWORD";

const int RELAY_PIN = 23;
const int BUTTON_PIN = 27;
const int RELAY_ON = LOW;     // most relay modules switch on with LOW
const int RELAY_OFF = HIGH;

BlynkTimer timer;
bool relayOn = false;
unsigned long onSince = 0;
int autoOffMinutes = 0;       // 0 = no timer
int buttonRest;
bool wasPressed = false;

void setRelay(bool on) {
  relayOn = on;
  digitalWrite(RELAY_PIN, on ? RELAY_ON : RELAY_OFF);
  onSince = millis();
  Blynk.virtualWrite(V0, on);  // keep the app's switch in sync
  Serial.println(on ? "Relay on" : "Relay off");
}

BLYNK_WRITE(V0) { setRelay(param.asInt()); }
BLYNK_WRITE(V1) { autoOffMinutes = param.asInt(); }

BLYNK_CONNECTED() {
  Blynk.syncVirtual(V1);          // get the timer setting
  Blynk.virtualWrite(V0, relayOn); // tell the app the real relay state
}

void checkButton() {
  bool pressed = digitalRead(BUTTON_PIN) != buttonRest;
  if (pressed && !wasPressed) setRelay(!relayOn);   // toggle on each press
  wasPressed = pressed;
}

void updateTimer() {
  if (!relayOn) { Blynk.virtualWrite(V2, "Off"); return; }
  if (autoOffMinutes == 0) { Blynk.virtualWrite(V2, "On, no timer"); return; }

  long left = autoOffMinutes * 60L - (long)((millis() - onSince) / 1000);
  if (left <= 0) {
    setRelay(false);
    Blynk.virtualWrite(V2, "Switched off by the timer");
  } else {
    Blynk.virtualWrite(V2, String(left / 60) + " min " + String(left % 60) + " s left");
  }
}

void setup() {
  Serial.begin(115200);
  digitalWrite(RELAY_PIN, RELAY_OFF);   // make sure it starts off
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  delay(200);
  buttonRest = digitalRead(BUTTON_PIN);

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  timer.setInterval(30L, checkButton);
  timer.setInterval(1000L, updateTimer);
}

void loop() {
  Blynk.run();
  timer.run();
}

How it works

Every change goes through one function, setRelay(), whether it comes from the app, the button or the timer. That function switches the relay and also writes the new state back to V0, so the app's switch moves when you press the real button. This is called two-way sync. After a restart the relay always starts off, and BLYNK_CONNECTED() tells the app so, instead of asking the app what to do. For a switch, that is the safer choice: a power cut never switches something on by surprise. The countdown compares millis() with the moment the relay was switched on, so it keeps working while Blynk runs.

Try this next

  • Use the second relay channel (IN2) with a second button widget.
  • Add a Time Input widget to switch on at a set time each day.
  • Count how long the relay has been on today and show it in the app.

Troubleshooting

  • The device shows "Offline" in the app: check the Serial Monitor at 115200 baud. "Invalid auth token" means the BLYNK_AUTH_TOKEN line is wrong; if it never connects, check the Wi-Fi name and password, and that your network is 2.4 GHz.
  • The relay is on when the app says off: your module is active HIGH. Swap LOW and HIGH in RELAY_ON and RELAY_OFF.
  • The relay LED lights but it doesn't click: check that VCC is on 5V, not 3V3.
  • One press toggles twice: increase the button check interval from 30 to 60 ms.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

ESP32 IoT Starter Kit | Arduino IDE Compatible | Free Tutorials $57.00

Shop the kit