In this project, we will create a WiFi-controlled scheduled relay using a NodeMCU v3, which can be turned on and off at specific times set via a web interface. The current GMT will be displayed live on the server. This project is perfect for automating devices such as lights or fans, ensuring they operate according to a schedule.
Disclaimer:
Handling electricity carries inherent risks. It’s essential to have the appropriate skills to manage it safely. Proceed at your own risk, as the author disclaims responsibility for any misuse, harm, or errors. All content on this website is unique and copyrighted; please avoid unauthorized copying. While most articles are open-source for your benefit, feel free to use the knowledge provided. If you find our resources helpful, consider purchasing available materials to support our work.
For assistance or guidance, leave a comment below; the author is committed to helping. Some articles may contain affiliate links that support the author with a commission at no additional cost to you. Thank you for your understanding and support.
In the last article, we saw how to make a Wi-Fi-based remote-controlled relay. In this article, we’ll take it a step further by adding a scheduling feature to the setup. Why is this necessary? Sometimes we are too busy to activate the switch/relay manually. By adding a schedule, the device can operate automatically at predefined times.
Table of Contents
Components Needed:
- NodeMCU v3
- Relay module
- Breadboard and jumper wires
- Power supply
You may have similar components which you can use if possible.
Circuit diagram:
Setting Up the Arduino IDE:
- Install the Arduino IDE and the necessary libraries (
ESP8266WiFi
,ESP8266WebServer
,WiFiUdp
, andNTPClient
). - Add the NodeMCU board to the Arduino IDE:
- Open Arduino IDE, go to
File
>Preferences
. - In the “Additional Boards Manager URLs” field, add
http://arduino.esp8266.com/stable/package_esp8266com_index.json
. - Go to
Tools
>Board
>Boards Manager
, search forESP8266
and install it.
- Open Arduino IDE, go to
Arduino Code:
Ensure that all the necessary libraries are installed, and the NodeMCU board is added to the Arduino IDE. Then, select ‘NodeMCU 1.0’ as the board.
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <WiFiUdp.h> #include <NTPClient.h> // WiFi credentials const char* ssid = "Your_SSID"; const char* password = "SSID_Password"; // NTP Client setup WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // Update time every 60 seconds ESP8266WebServer server(80); const int relayPin = D1; // GPIO5 time_t onTime = 0, offTime = 0; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); // Start with the relay off server.on("/", handleRoot); server.on("/on", handleRelayOn); server.on("/off", handleRelayOff); server.on("/set_timer", handleSetTimer); server.on("/submit_time", handleSubmitTime); server.on("/get_time", handleGetTime); // Add endpoint to get current time server.begin(); Serial.println("HTTP server started"); // Initialize NTP client timeClient.begin(); } void handleRoot() { String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">WiFi Relay Control</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/on\">Turn On</a></p>"; html += "<p style=\"font-weight:bold;\"><a href=\"/off\">Turn Off</a></p>"; html += "<p style=\"font-weight:bold;\"><a href=\"/set_timer\">Set Timer</a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleRelayOn() { digitalWrite(relayPin, HIGH); String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Relay is ON</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/off\"><strong>Turn Off</strong></a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleRelayOff() { digitalWrite(relayPin, LOW); String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Relay is OFF</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/on\">Turn On</a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleSetTimer() { String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Set Timer</h1>"; html += "<form action=\"/submit_time\" method=\"POST\" style=\"font-weight:bold;\">"; html += "On Time: <input type=\"time\" name=\"on_time\"><br>"; html += "Off Time: <input type=\"time\" name=\"off_time\"><br>"; html += "<input type=\"submit\" value=\"Submit\">"; html += "</form>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleSubmitTime() { if (server.hasArg("on_time") && server.hasArg("off_time")) { String onTimeString = server.arg("on_time"); String offTimeString = server.arg("off_time"); // Parse the time input (HH:MM) into hours and minutes int onHour = onTimeString.substring(0, 2).toInt(); int onMinute = onTimeString.substring(3, 5).toInt(); int offHour = offTimeString.substring(0, 2).toInt(); int offMinute = offTimeString.substring(3, 5).toInt(); // Convert the time to a timestamp (seconds since midnight) onTime = (onHour * 3600 + onMinute * 60); offTime = (offHour * 3600 + offMinute * 60); // Print the on and off times to the serial monitor Serial.print("Relay will turn ON at: "); Serial.print(onHour); Serial.print(":"); if (onMinute < 10) { Serial.print("0"); } Serial.println(onMinute); Serial.print("Relay will turn OFF at: "); Serial.print(offHour); Serial.print(":"); if (offMinute < 10) { Serial.print("0"); } Serial.println(offMinute); String response = "<html><body style=\"background-color:lightblue;\">"; response += "<h1 style=\"font-weight:bold;\">Timer Set</h1>"; response += "<p style=\"font-weight:bold;\">Relay will turn ON at " + onTimeString + "</p>"; response += "<p style=\"font-weight:bold;\">Relay will turn OFF at " + offTimeString + "</p>"; response += "<p style=\"font-weight:bold;\"><a href=\"/\">Back</a></p>"; response += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; response += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; response += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; response += "</body></html>"; server.send(200, "text/html", response); } else { server.send(400, "text/html", "<html><body style=\"background-color:lightblue;\"><h1 style=\"font-weight:bold;\">Invalid Input</h1><p style=\"font-weight:bold;\"><a href=\"/set_timer\">Try Again</a></p></body></html>"); } } void handleGetTime() { server.send(200, "text/plain", timeClient.getFormattedTime()); } void loop() { server.handleClient(); timeClient.update(); time_t now = timeClient.getEpochTime() % 86400; // Get current time in seconds since midnight // Print the actual server time to the serial monitor Serial.print("Current server time: "); Serial.println(timeClient.getFormattedTime()); if (now == onTime) { digitalWrite(relayPin, HIGH); } if (now == offTime) { digitalWrite(relayPin, LOW); } delay(1000); // Add a delay to prevent flooding the serial monitor }
Code explanation:
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <WiFiUdp.h> #include <NTPClient.h> // WiFi credentials const char* ssid = "Your_SSID"; const char* password = "SSID_Password"; // NTP Client setup WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // Update time every 60 seconds ESP8266WebServer server(80); const int relayPin = D1; // GPIO5 time_t onTime = 0, offTime = 0;
Libraries and Constants: We include the necessary libraries and define WiFi credentials, NTP client setup, and pin assignments.
WiFi Credentials: Update ssid
and password
with your WiFi network details.
void setup() { Serial.begin(115200); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); // Start with the relay off server.on("/", handleRoot); server.on("/on", handleRelayOn); server.on("/off", handleRelayOff); server.on("/set_timer", handleSetTimer); server.on("/submit_time", handleSubmitTime); server.on("/get_time", handleGetTime); // Add endpoint to get current time server.begin(); Serial.println("HTTP server started"); // Initialize NTP client timeClient.begin(); }
Setup Function: This function sets up the WiFi connection, initializes the relay pin, and starts the web server.
NTP Client: The timeClient
is initialized to get the current time from the NTP server.
void handleRoot() { String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">WiFi Relay Control</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/on\">Turn On</a></p>"; html += "<p style=\"font-weight:bold;\"><a href=\"/off\">Turn Off</a></p>"; html += "<p style=\"font-weight:bold;\"><a href=\"/set_timer\">Set Timer</a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); }
Handle Root: This function generates the main web page with links to turn the relay on/off and set the timer. It also includes a script to update the current GMT time every second.
void handleRelayOn() { digitalWrite(relayPin, HIGH); String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Relay is ON</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/off\"><strong>Turn Off</strong></a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleRelayOff() { digitalWrite(relayPin, LOW); String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Relay is OFF</h1>"; html += "<p style=\"font-weight:bold;\"><a href=\"/on\">Turn On</a></p>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); }
Handle Relay On/Off: These functions turn the relay on or off and generate a web page to indicate the relay’s current state. They also include the script to update the current GMT time every second.
void handleSetTimer() { String html = "<html><body style=\"background-color:lightblue;\">"; html += "<h1 style=\"font-weight:bold;\">Set Timer</h1>"; html += "<form action=\"/submit_time\" method=\"POST\" style=\"font-weight:bold;\">"; html += "On Time: <input type=\"time\" name=\"on_time\"><br>"; html += "Off Time: <input type=\"time\" name=\"off_time\"><br>"; html += "<input type=\"submit\" value=\"Submit\">"; html += "</form>"; html += "<p style=\"font-weight:bold;\">Note: Time is according to GMT</p>"; html += "<p style=\"font-weight:bold;\">Current GMT Time: <span id=\"gmtTime\"></span></p>"; html += "<script>function updateTime() { fetch('/get_time').then(response => response.text()).then(data => { document.getElementById('gmtTime').innerText = data; }); } setInterval(updateTime, 1000); updateTime();</script>"; html += "</body></html>"; server.send(200, "text/html", html); }
Handle Set Timer: This function generates a form to set the on and off times for the relay. It includes the script to update the current GMT time every second.
void handleSubmitTime() { if (server.hasArg("on_time") && server.hasArg("off_time")) { String onTimeString = server.arg("on_time"); String offTimeString = server.arg("off_time"); // Parse the time input (HH:MM) into hours and minutes int onHour = onTimeString.substring(0, 2).toInt(); int onMinute = onTimeString.substring(3, 5).toInt(); int offHour = offTimeString.substring(0, 2).toInt(); int offMinute = offTimeString.substring(3, 5).toInt(); // Convert the time to a timestamp (seconds since midnight) onTime = (onHour * 3600 + onMinute * 60); offTime
Testing the project:
Like the previous system, run this system and check the serial terminal for the IP address. Ensure your SSID and passwords are correct first. Then browse this through any browser to access the server. You’ll get an interface like this:
Now click Turn On/ Off to turn on/off the relay directly or set a timer to do it. Enjoy the game!
Conclusion:
This is a really exciting and useful project. I’m planning to use it to feed my pets. What other ideas do you have for this project? Share your thoughts in the comments below. I hope this project helps you a lot. See you soon!
For Professional Designs or Help:
Read more:
- Wi-Fi controlled relay switch
- The Rise of the Brainy Bunch: AI in Embedded Systems!
- Understanding Timer0: Learning PIC Microcontrollers [Chapter 9]
0 Comments