DEV Community

Cover image for DIY Local Wireless Control System With ESP8266 And Relay - No Internet Required
Payam Hoseini
Payam Hoseini

Posted on

DIY Local Wireless Control System With ESP8266 And Relay - No Internet Required

I think this is one of the most important projects if you are interested in iot. This project connects an ESP8266 (D1 Mini) to a 5-pin relay module, creating a web server that hosts a control interface. I select ESP8266 for this project because of its WIFI and I used D1 mini because it is one of the best ESP8266 variant, it's compact and powerful enough and has many pins.
You can toggle the relay on/off from any device on your local network by accessing the ESP8266's IP address in a web browser. This is a simple and effective solution for controlling devices remotely using a web interface.
I use a transistor(2n2222) and a diod(1n4007) because my relay is 5 volt and d1 mini pins has around 3 volt output and i use transistor to be able to use 5 volt pin of d1 mini to trigger relay coil. ( If you have 3V relays, You only need to connect D1 mini and relay together )

✨ Features

  • 🌐 Web-based control interface
  • 💡 Real-time status updates
  • 🔄 Automatic status refresh
  • 📱 Mobile-friendly responsive design
  • 🔌 Control any device connected to the relay
  • 🏠 Works on your local network (no internet required)

🛠️ Hardware Requirements

  • ESP8266 D1 Mini (or any ESP8266-based board)
  • 5V Relay Module
  • NPN Transistor (e.g., 2N2222)
  • 1kΩ Resistor
  • Jumper Wires
  • Micro USB Cable
  • Power Supply (for the relay if needed)

📊 Circuit Diagram

Local Wireless Control System With ESP8266 And Relay Circuit Diagram

My Wiring

My Wiring for Local Wireless Control System With ESP8266 And Relay

🔧 Setup Instructions

Parts Pinout

5V Relay

5V 5Pin Relay Pinout

2N2222 Transistor

2N2222 Transistor Pinout

1N4007 Diode

1N4007 Diode Pinout

Hardware Setup

  1. Connect the D1 pin of the ESP8266 to the base of the NPN transistor through a 1kΩ resistor
  2. Connect the collector of the transistor to the control pin of the relay module
  3. Connect the emitter of the transistor to ground
  4. Connect the VCC of the relay module to the 5V output of the ESP8266 (or external power supply for larger relays)
  5. Connect the GND of the relay module to the GND of the ESP8266

Sketch

Here is the sketch that you need to upload to your ESP8266 board :
( If you dont know how to upload this sketch to your board, After sketch there is a simple guide to install Arduino IDE and required packages for uploading it )

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>

// WiFi credentials
const char* ssid = "YourWifiSSID";      // Replace with your WiFi name
const char* password = "YourWifiPassword";  // Replace with your WiFi password

// Pin definitions
const int relayPin = D1;  // D1 pin connected to transistor base via resistor

// Web server on port 80
ESP8266WebServer server(80);

// LED state
bool ledState = false;

void setup() {
  // Initialize serial communication
  Serial.begin(115200);

  // Set relay pin as output
  pinMode(relayPin, OUTPUT);

  // Initially turn off the relay
  digitalWrite(relayPin, LOW);

  // Connect to WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Connected to WiFi. IP address: ");
  Serial.println(WiFi.localIP());

  // Define server routes
  server.on("/", handleRoot);
  server.on("/toggle", handleToggle);
  server.on("/status", handleStatus);
  server.onNotFound(handleNotFound);

  // Start the server
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

// Handle root page
void handleRoot() {
  String html = R"(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LED Control</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f5f5f5;
        }
        .container {
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            padding: 30px;
            text-align: center;
            max-width: 400px;
            width: 100%;
        }
        h1 {
            color: #333;
            margin-bottom: 30px;
        }
        .status {
            margin: 20px 0;
            font-size: 18px;
        }
        .switch {
            position: relative;
            display: inline-block;
            width: 60px;
            height: 34px;
            margin: 20px 0;
        }
        .switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: .4s;
            border-radius: 34px;
        }
        .slider:before {
            position: absolute;
            content: "";
            height: 26px;
            width: 26px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            transition: .4s;
            border-radius: 50%;
        }
        input:checked + .slider {
            background-color: #2196F3;
        }
        input:checked + .slider:before {
            transform: translateX(26px);
        }
        .led-icon {
            font-size: 48px;
            margin: 20px 0;
            transition: color 0.3s;
        }
        .led-off {
            color: #ccc;
        }
        .led-on {
            color: #ffcc00;
            text-shadow: 0 0 10px #ffcc00;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>LED Control Panel</h1>

        <div class="led-icon" id="ledIcon">💡</div>

        <div class="status">
            LED Status: <span id="ledStatus">OFF</span>
        </div>

        <label class="switch">
            <input type="checkbox" id="toggleSwitch">
            <span class="slider"></span>
        </label>

        <div>
            <p>IP Address: )" + WiFi.localIP().toString() + R"(</p>
        </div>
    </div>

    <script>
        const toggleSwitch = document.getElementById('toggleSwitch');
        const ledStatus = document.getElementById('ledStatus');
        const ledIcon = document.getElementById('ledIcon');

        // Get initial state
        fetchStatus();

        // Toggle switch event
        toggleSwitch.addEventListener('change', function() {
            fetch('/toggle')
            .then(response => response.json())
            .then(data => {
                updateUI(data.state);
            })
            .catch(error => console.error('Error:', error));
        });

        // Fetch current status
        function fetchStatus() {
            fetch('/status')
            .then(response => response.json())
            .then(data => {
                updateUI(data.state);
            })
            .catch(error => console.error('Error:', error));
        }

        // Update UI based on state
        function updateUI(state) {
            toggleSwitch.checked = state;
            ledStatus.textContent = state ? 'ON' : 'OFF';
            if (state) {
                ledIcon.classList.add('led-on');
                ledIcon.classList.remove('led-off');
            } else {
                ledIcon.classList.add('led-off');
                ledIcon.classList.remove('led-on');
            }
        }

        // Refresh status every 5 seconds
        setInterval(fetchStatus, 5000);
    </script>
</body>
</html>
  )";

  server.send(200, "text/html", html);
}

// Handle toggle request
void handleToggle() {
  ledState = !ledState;
  digitalWrite(relayPin, ledState ? HIGH : LOW);

  DynamicJsonDocument doc(64);
  doc["state"] = ledState;

  String response;
  serializeJson(doc, response);
  server.send(200, "application/json", response);
}

// Handle status request
void handleStatus() {
  DynamicJsonDocument doc(64);
  doc["state"] = ledState;

  String response;
  serializeJson(doc, response);
  server.send(200, "application/json", response);
}

// Handle 404 Not Found
void handleNotFound() {
  server.send(404, "text/plain", "Not Found");
}
Enter fullscreen mode Exit fullscreen mode

Software Setup

  1. Install the Arduino IDE from arduino.cc
  2. Add ESP8266 board support:
    • Open Arduino IDE
    • Go to File > Preferences
    • Add http://arduino.esp8266.com/stable/package_esp8266com_index.json to Additional Boards Manager URLs
    • Go to Tools > Board > Boards Manager
    • Search for ESP8266 and install
  3. Install required libraries:
    • Go to Sketch > Include Library > Manage Libraries
    • Search for and install:
      • ESP8266WiFi
      • ESP8266WebServer
      • ArduinoJson
  4. Open the sketch.ino file in Arduino IDE
  5. Update the WiFi credentials:
   const char* ssid = "YourWifiSSID";      // Replace with your WiFi name
   const char* password = "YourWifiPassword";  // Replace with your WiFi password
Enter fullscreen mode Exit fullscreen mode
  1. Select your board (Tools > Board > ESP8266 Boards > LOLIN(WEMOS) D1 R2 & mini)
  2. Select the correct port (Tools > Port)
  3. Upload the sketch to your ESP8266

🚀 Usage

  1. Power on your ESP8266
  2. The device will connect to your WiFi network
  3. Check the Serial Monitor (115200 baud) to see the assigned IP address
  4. Open a web browser on any device connected to the same network
  5. Enter the IP address in the address bar
  6. Use the toggle switch on the web interface to control the relay

Sample of LED Control Panel

Sample of LED Control Panel

🔍 Troubleshooting

  • ESP8266 not connecting to WiFi: Double-check your WiFi credentials in the code
  • Relay not switching: Verify your wiring connections and ensure the transistor is properly connected
  • Cannot access web interface: Make sure your device is connected to the same network as the ESP8266
  • Relay switching erratically: Check for proper grounding and consider adding a flyback diode if not already included in your relay module

If there is any unknown problems, don't hesitate to contact me.

🛡️ Safety Warnings

  • This project involves working with electricity which can be dangerous
  • Never connect the relay to mains voltage without proper knowledge and safety precautions
  • Always disconnect power before making any changes to the circuit
  • Consider using an optocoupler for additional safety when working with higher voltages

📧 Contact

Payam Hoseini - [email protected]
WebSite: [https://payamdev.com]

Project Link: https://github.com/payamhsn/Iot-ESP8266andRelay


I wrote most of this blog post by myself and use chatgpt for some parts.
Made with ❤️ by [Payam Hoseini]

Top comments (0)