ESP32 Relay Module – Control AC Appliances (Web Server)

Using a relay with the ESP32 is a great way to control AC household appliances remotely. This tutorial explains how to control a relay module with the ESP32. We’ll take a look at how a relay module works, how to connect the relay to the ESP32 and build a web server to control a relay remotely (or as many relays as you want).

Control a Relay Module with an ESP32 (Web Server)

Learn how to control a relay module with ESP8266 board: Guide for ESP8266 Relay Module – Control AC Appliances + Web Server Example.

Watch the Video Tutorial

Watch the following video tutorial or keep reading this page for the written instructions and all the resources.

Introducing Relays

A relay is an electrically operated switch and like any other switch, it that can be turned on or off, letting the current go through or not. It can be controlled with low voltages, like the 3.3V provided by the ESP32 GPIOs and allows us to control high voltages like 12V, 24V or mains voltage (230V in Europe and 120V in the US).

1, 2, 4, 8, 16 Channels Relay Modules

There are different relay modules with a different number of channels. You can find relay modules with one, two, four, eight and even sixteen channels. The number of channels determines the number of outputs we’ll be able to control.

Relay modules with different number of channels 1, 2, 4, 8, 16 Channels

There are relay modules whose electromagnet can be powered by 5V and with 3.3V. Both can be used with the ESP32 – you can either use the VIN pin (that provides 5V) or the 3.3V pin.

Additionally, some come with built-in optocoupler that add an extra “layer” of protection, optically isolating the ESP32 from the relay circuit.

Get a relay module:

Relay Pinout

For demonstration purposes, let’s take a look at the pinout of a 2-channel relay module. Using a relay module with a different number of channels is similar.

2-channel Relay Module Pinout

On the left side, there are two sets of three sockets to connect high voltages, and the pins on the right side (low-voltage) connect to the ESP32 GPIOs.

Mains Voltage Connections

Relay module mains voltage side

The relay module shown in the previous photo has two connectors, each with three sockets: common (COM), Normally Closed (NC), and Normally Open (NO).

  • COM: connect the current you want to control (mains voltage).
  • NC (Normally Closed): the normally closed configuration is used when you want the relay to be closed by default. The NC are COM pins are connected, meaning the current is flowing unless you send a signal from the ESP32 to the relay module to open the circuit and stop the current flow.
  • NO (Normally Open): the normally open configuration works the other way around: there is no connection between the NO and COM pins, so the circuit is broken unless you send a signal from the ESP32 to close the circuit.

Control Pins

2-channel Relay Module

The low-voltage side has a set of four pins and a set of three pins. The first set consists of VCC and GND to power up the module, and input 1 (IN1) and input 2 (IN2) to control the bottom and top relays, respectively.

If your relay module only has one channel, you’ll have just one IN pin. If you have four channels, you’ll have four IN pins, and so on.

The signal you send to the IN pins, determines whether the relay is active or not. The relay is triggered when the input goes below about 2V. This means that you’ll have the following scenarios:

  • Normally Closed configuration (NC):
    • HIGH signal – current is flowing
    • LOW signal – current is not flowing
  • Normally Open configuration (NO):
    • HIGH signal – current is not flowing
    • LOW signal – current in flowing

You should use a normally closed configuration when the current should be flowing most of the times, and you only want to stop it occasionally.

Use a normally open configuration when you want the current to flow occasionally (for example, turn on a lamp occasionally).

Power Supply Selection

2-channel relay module control pins

The second set of pins consists of GND, VCC, and JD-VCC pins. The JD-VCC pin powers the electromagnet of the relay. Notice that the module has a jumper cap connecting the VCC and JD-VCC pins; the one shown here is yellow, but yours may be a different color.

With the jumper cap on, the VCC and JD-VCC pins are connected. That means the relay electromagnet is directly powered from the ESP32 power pin, so the relay module and the ESP32 circuits are not physically isolated from each other.

Without the jumper cap, you need to provide an independent power source to power up the relay’s electromagnet through the JD-VCC pin. That configuration physically isolates the relays from the ESP32 with the module’s built-in optocoupler, which prevents damage to the ESP32 in case of electrical spikes.

Wiring a Relay Module to the ESP32

Connect the relay module to the ESP32 as shown in the following diagram. The diagram shows wiring for a 2-channel relay module, wiring a different number of channels is similar.

Warning: in this example, we’re dealing with mains voltage. Misuse can result in serious injuries. If you’re not familiar with mains voltage ask someone who is to help you out. While programming the ESP or wiring your circuit make sure everything is disconnected from mains voltage.

Alternatively, you can use a 12V power source to control 12V appliances.

In this example, we’re controlling a lamp. We just want to light up the lamp occasionally, so it is better to use a normally open configuration.

We’re connecting the IN1 pin to GPIO 26, you can use any other suitable GPIO. See ESP32 GPIO Reference Guide.

Controlling a Relay Module with the ESP32 – Arduino Sketch

The code to control a relay with the ESP32 is as simple as controlling an LED or any other output. In this example, as we’re using a normally open configuration, we need to send a LOW signal to let the current flow, and a HIGH signal to stop the current flow.

Control a Lamp with the ESP32 using a Relay

The following code will light up your lamp for 10 seconds and turn it off for another 10 seconds.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-relay-module-ac-web-server/
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

const int relay = 26;

void setup() {
  Serial.begin(115200);
  pinMode(relay, OUTPUT);
}

void loop() {
  // Normally Open configuration, send LOW signal to let current flow
  // (if you're usong Normally Closed configuration send HIGH signal)
  digitalWrite(relay, LOW);
  Serial.println("Current Flowing");
  delay(5000); 
  
  // Normally Open configuration, send HIGH signal stop current flow
  // (if you're usong Normally Closed configuration send LOW signal)
  digitalWrite(relay, HIGH);
  Serial.println("Current not Flowing");
  delay(5000);
}

View raw code

How the Code Works

Define the pin the relay IN pin is connected to.

const int relay = 26;

In the setup(), define the relay as an output.

pinMode(relay, OUTPUT);

In the loop(), send a LOW signal to let the current flow and light up the lamp.

digitalWrite(relay, LOW);

If you’re using a normally closed configuration, send a HIGH signal to light up the lamp. Then, wait 5 seconds.

delay(5000);

Stop the current flow by sending a HIGH signal to the relay pin. If you’re using a normally closed configuration, send a LOW signal to stop the current flow.

digitalWrite(relay, HIGH);

Control Multiple Relays with ESP32 Web Server

Control Multiple Relays with ESP32 Web Server

In this section, we’ve created a web server example that allows you to control as many relays as you want via web server whether they are configured as normally opened or as normally closed. You just need to change a few lines of code to define the number of relays you want to control and the pin assignment.

To build this web server, we use the ESPAsyncWebServer library.

Installing the ESPAsyncWebServer library

Follow the next steps to install the ESPAsyncWebServer library:

  1. Click here to download the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncWebServer-master folder
  3. Rename your folder from ESPAsyncWebServer-master to ESPAsyncWebServer
  4. Move the ESPAsyncWebServer folder to your Arduino IDE installation libraries folder

Alternatively, in your Arduino IDE, you can go to Sketch > Include Library > Add .ZIP library… and select the library you’ve just downloaded.

Installing the Async TCP Library for ESP32

The ESPAsyncWebServer library requires the AsyncTCP library to work. Follow the next steps to install that library:

  1. Click here to download the AsyncTCP library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get AsyncTCP-master folder
  3. Rename your folder from AsyncTCP-master to AsyncTCP
  4. Move the AsyncTCP folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Alternatively, in your Arduino IDE, you can go to Sketch > Include Library > Add .ZIP library… and select the library you’ve just downloaded.

After installing the required libraries, copy the following code to your Arduino IDE.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-relay-module-ac-web-server/
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"

// Set to true to define Relay as Normally Open (NO)
#define RELAY_NO    true

// Set number of relays
#define NUM_RELAYS  5

// Assign each GPIO to a relay
int relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const char* PARAM_INPUT_1 = "relay";  
const char* PARAM_INPUT_2 = "state";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?relay="+element.id+"&state=1", true); }
  else { xhr.open("GET", "/update?relay="+element.id+"&state=0", true); }
  xhr.send();
}</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons ="";
    for(int i=1; i<=NUM_RELAYS; i++){
      String relayStateValue = relayState(i);
      buttons+= "<h4>Relay #" + String(i) + " - GPIO " + relayGPIOs[i-1] + "</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"" + String(i) + "\" "+ relayStateValue +"><span class=\"slider\"></span></label>";
    }
    return buttons;
  }
  return String();
}

String relayState(int numRelay){
  if(RELAY_NO){
    if(digitalRead(relayGPIOs[numRelay-1])){
      return "";
    }
    else {
      return "checked";
    }
  }
  else {
    if(digitalRead(relayGPIOs[numRelay-1])){
      return "checked";
    }
    else {
      return "";
    }
  }
  return "";
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  // Set all relays to off when the program starts - if set to Normally Open (NO), the relay is off when you set the relay to HIGH
  for(int i=1; i<=NUM_RELAYS; i++){
    pinMode(relayGPIOs[i-1], OUTPUT);
    if(RELAY_NO){
      digitalWrite(relayGPIOs[i-1], HIGH);
    }
    else{
      digitalWrite(relayGPIOs[i-1], LOW);
    }
  }
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Send a GET request to <ESP_IP>/update?relay=<inputMessage>&state=<inputMessage2>
  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    String inputMessage2;
    String inputParam2;
    // GET input1 value on <ESP_IP>/update?relay=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1) & request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
      inputParam2 = PARAM_INPUT_2;
      if(RELAY_NO){
        Serial.print("NO ");
        digitalWrite(relayGPIOs[inputMessage.toInt()-1], !inputMessage2.toInt());
      }
      else{
        Serial.print("NC ");
        digitalWrite(relayGPIOs[inputMessage.toInt()-1], inputMessage2.toInt());
      }
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage + inputMessage2);
    request->send(200, "text/plain", "OK");
  });
  // Start server
  server.begin();
}
  
void loop() {

}

View raw code

Define Relay Configuration

Modify the following variable to indicate whether you’re using your relays in normally open (NO) or normally closed (NC) configuration. Set the RELAY_NO variable to true for normally open os set to false for normally closed.

#define RELAY_NO true

Define Number of Relays (Channels)

You can define the number of relays you want to control on the NUM_RELAYS variable. For demonstration purposes, we’re setting it to 5.

#define NUM_RELAYS 5

Define Relays Pin Assignment

In the following array variable you can define the ESP32 GPIOs that will control the relays:

int relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

The number of relays set on the NUM_RELAYS variable needs to match the number of GPIOs assigned in the relayGPIOs array.

Network Credentials

Insert your network credentials in the following variables.

const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Wiring 8 Channel Relay to ESP32

For demonstration purposes, we’re controlling 5 relay channels. Wire the ESP32 to the relay module as shown in the next schematic diagram.

ESP32 8-channel relay module wiring diagram schematic

Demonstration

After making the necessary changes, upload the code to your ESP32.

Open the Serial Monitor at a baud rate of 115200 and press the ESP32 EN button to get its IP address.

Then, open a browser in your local network and type the ESP32 IP address to get access to the web server.

You should get something as follows with as many buttons as the number of relays you’ve defined in your code.

ESP32 Web Server controlling AC lamp with relay module

Now, you can use the buttons to control your relays remotely using your smartphone.

Enclosure for Safety

For a final project, make sure you place your relay module and ESP inside an enclosure to avoid any AC pins exposed.

Enclosure for Relay Module

Wrapping Up

Using relays with the ESP32 is a great way to control AC household appliances remotely. You can also read our other Guide to control a Relay Module with ESP8266.

Controlling a relay with the ESP32 is as easy controlling any other output, you just need to send HIGH and LOW signals as you would do to control an LED.

You can use our web server examples that control outputs to control relays. You just need to pay attention to the configuration you’re using. In case you’re using a normally open configuration, the relay works with inverted logic. You can use the following web server examples to control your relay:

Learn more about the ESP32 with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

122 thoughts on “ESP32 Relay Module – Control AC Appliances (Web Server)”

  1. When deciding on whether to use NO or NC to control something. Consider when the ESP32 has a fault or loses power. with NC through the relay the power will flow. That could be a good thing or bad.

    Reply
  2. Nice job! I have made similar solution using SMS (LILYGO® TTGO T-Call V1.3 ESP32 harware) messaging in order to control appliances in my summer cottage. I am using EEPROM to store relay status in order to recover relays after power failure. ESP confirms received commands using SMS message. ESP accepts commands from predefined phone number only.

    Reply
  3. Hello, thanks for great tutorials!
    I own one 8 relay module and works perfectly with my esp8266.
    I am just unhappy for a reason: when the esp is switched off my module is on (because the pins are low).
    The same in the case of supply fault: all the switches suddently become on.
    I fix this problem by adding 8 transistors BC547 so that when I send high signal to base the module pin goes low and the switches give light.
    ut…do exist a better way?
    Thank you

    Reply
  4. Just wondering if when assigning the relay gpio number is it would be possible to enter a corresponding name to the relay. example int relayGPIOs[NAME_RELAYS] = {Front, West, Rear, East, South}; so when it displays the information on the webpage, you can see what the relay is connected up to.

    Reply
    • Hi Fernando.
      That’s a great idea and that would definitely be possible.
      However, it is not implemented in the code.
      But if you take a closer look at the code you’ll find a way to do it. See the part of the code for the BUTTONPLACEHOLDER. You’ll need to add something for the relay name.
      Regards,
      Sara

      Reply
    • I added this:

      int relayGPIOs[NUM_RELAYS] = { 26, 27, 25};
      String relayNames[NUM_RELAYS] = { “Light East”, “Water”, “Light West” };

      and replaced the “buttons+=” line in the processor function with

      buttons+= "<h4>" + relayNames[i-1] + " - GPIO " + relayGPIOs[i-1] + "</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"" + String(i) + "\" "+ relayStateValue +"><span class=\"slider\"></span></label>";

      Reply
      • Hallooo Dears Thanks for your information
        i have added the relay names exactly you have given same
        and replaced the button position and getting error

        int relayGPIOs[NUM_RELAYS] = {26, 27, 25};
        String relayNames[NUM_RELAYS] = { “Light East”, “Water”, “Light West” };

        // Replace with your network credentials

        button position like this add
        String relayStateValue = relayState(i);
        buttons+= ”

        ” + relayNames[i-1] + ” – GPIO ” + relayGPIOs[i-1] + ”

        “;
        return buttons;
        }
        return String();
        }

        getting error like down can you explain me what should do for it
        error message

        Arduino: 1.8.13 (Windows Store 1.8.42.0) (Windows 10), Board: “DOIT ESP32 DEVKIT V1, 80MHz, 921600, None”

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\234’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\235’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\234’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\235’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\234’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\342’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\200’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:1: error: stray ‘\235’ in program

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:38: error: ‘Light’ was not declared in this scope

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:44: error: expected ‘}’ before ‘East’

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:44: error: expected ‘,’ or ‘;’ before ‘East’

        ESP-lolin32_26Relay_Web_ServerPORT_FWD-test-3:21:83: error: expected declaration before ‘}’ token

        Multiple libraries were found for “WiFi.h”

        Used: C:\Users\noush\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\libraries\WiFi

        Not used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\WiFi

        exit status 1

        stray ‘\342’ in program

        This report would have more information with
        “Show verbose output during compilation”
        option enabled in File -> Preferences.

        Reply
        • Bonjour à tous,
          J’ai apporté la modification donnée par Norbert pour attribuer des noms différents aux relais. Mais j’ai le même résultat que Noushad.
          Je pense qu’il y a une erreur dans le script. Quelqu’un a un script qui fonctionne?
          PS: félicitations à Sara qui fait un très bon travail.

          Reply
          • Sorry, the sketch is correct! be carreful with the type of quotes used in this line: Chaîne relayNames [NUM_RELAYS] = {“Light East”, “Water”, “Light West”};

  5. Good Tutorial, but as there are not so many available Pins on the ESP modules,
    If you used a Serial in Parallel out shift Register, it would use less Pins on the ESP Clock, Strobe and Serial data. cascade 2 and the 16 relay board is useable..
    Also Mains should really be double switched (both Line and Neutral).

    Reply
  6. This is amazing. I lost my fate in the public internet a few years ago and IOT is on the horizon. So started learning PHP. I know that PHP was not the best lang but it looked relatively easy thanks to WordPress.

    But its WordPress. I noticed a few things and told my self. From now on no frameworks or other stuff. Just native PHP and JavaScript. It was not always fun i can tell you. A month ago i started with NodeJS. And now this comes on my path. Now i can say. My fate in the internet is a little bit restored.

    With this, not only this post. I can create what i want. The limit is my imagination. Just imagine having a ‘smart’ home application thats ‘smart enough’ to do what you forget, anticipate on that without having your data stored in the ‘cloud’ but still having all the nice graphs and features that are existing.

    Endless possibilities. Thanks for sharing this information.
    A Dutch Guy

    Reply
  7. if you want 3D styled buttons on a dark background. then replace the style part in the const char index_html part
    with this.

    html {
    font-family: Arial;
    color:#fff;
    display: inline-block;
    text-align: center;
    }

    h2 {font-size: 2.0rem;
    }

    p {font-size: 1.0rem;
    }

    body {
    max-width: 600px;
    margin:0px auto;
    padding-bottom: 25px;
    background:#151515;
    }
    input[type=checkbox] {

    position: relative;
    display: inline-block;
    width:120px;
    height:40px;
    -webkit-appearance: none;
    background: linear-gradient(0deg, #333, #000);
    outline: none;
    border-radius: 20px;
    box-shadow: 0 0 0 4px #353535, 0 0 0 5px #3e3e3e, inset 0 0 10px rgba(0,0,0,1);
    }

    input:checked[type=”checkbox”]:nth-of-type(1) {
    background: linear-gradient(0deg, #e67e22, #f39c12);
    box-shadow: 0 0 0 4px #353535, 0 0 0 5px #3e3e3e, inset 0 0 10px rgba(0,0,0,1);
    }

    input[type=checkbox]:before {
    content:”;
    position:absolute;
    top:0;
    left:0;
    width:80px;
    height:40px;
    background: linear-gradient(0deg, #000, #6b6b6b);
    border-radius: 20px;
    box-shadow: 0 0 0 1px #232323;
    transform: scale(.98,.96);
    transition:.5s;
    }

    input:checked[type=checkbox]:before {
    left:40px;
    }

    input[type=checkbox]:after{
    content:”;
    position:absolute;
    top:calc(50% – 2px);
    left:70px;
    width:4px;
    height:4px;
    background: linear-gradient(0deg, #6b6b6b, #000);
    border-radius: 50%;
    transition:.5s;
    }

    input:checked[type=checkbox]:after {
    left:110px;
    }

    Reply
  8. Hi Sara and Rui,

    Congratulations by nice tutorial. I´m trying to set a relay module(2 channel-5V), but the Pinout 5 of my NodeMcu seem that can´t trigger, I believe that being because of current or voltage that this port provide. When I put 5V into relay module, it trigger normally.
    What I need to solve this problem? Should I buy another 3.3v relay?

    Reply
  9. Hi Rui and Sara.
    thank you for your tutorials and the great way you present it.
    there were some errors in the last post from me.
    I post this where the bugs are fixed.

    if you want 3D styled buttons on a dark background. then replace the style part in the const char index_html part
    with this.

    html {
    font-family: Arial;
    color:#fff;
    display: inline-block;
    text-align: center;
    }

    h2 {font-size: 2.0rem;
    }

    p {font-size: 1.0rem;
    }

    body {
    margin:0;
    padding:0;
    background:#151515;

    }

    input[type=checkbox] {
    position:relative;
    width:120px;
    height:40px;
    -webkit-appearance: none;
    background: linear-gradient(0deg, #333, #000);
    outline: none;
    border-radius: 20px;
    box-shadow: 0 0 0 4px #353535, 0 0 0 5px #3e3e3e, inset 0 0 10px rgba(0,0,0,1);
    }

    input[type=checkbox]:before {
    content:”;
    position:absolute;
    top:0;
    left:0;
    width:80px;
    height:40px;
    background: linear-gradient(0deg, #000, #6b6b6b);
    border-radius: 20px;
    box-shadow: 0 0 0 1px #232323;
    transform: scale(.98,.96);
    transition:.5s;
    }

    input[type=checkbox]:after{
    content:”;
    position:absolute;
    top:15px;
    left:65px;
    width:8px;
    height:8px;
    background: linear-gradient(0deg, #6b6b6b, #000);
    border-radius: 20px;
    transition:.5s;
    }

    input:checked[type=checkbox]:before {
    left:40px;
    }

    input:checked[type=checkbox]:after {
    left:105px;
    }

    input:checked[type=”checkbox”]:nth-of-type(1) {
    background: linear-gradient(0deg, #e67e22, #f39c12);
    box-shadow: 0 0 0 4px #353535, 0 0 0 5px #3e3e3e, inset 0 0 10px rgba(0,0,0,1);
    }

    }

    Reply
    • Hi, Jørgen
      Thanks for the above code, it’s really looking good, we were half successful though – we have a slight problem. Whenever there is a power cut, it is required for us to Press “RESET” button on the ESP32. Please help further on this issue.

      Reply
      • Hi Mahe.
        I don’t think I can help you since I don’t have that circuit running anymore.
        Do you not have to press RESET button when using Rui’s original sketch.
        I hope there is someone who can help you.
        Best regards Jørgen.

        Reply
  10. Hi again
    I hope it finally gets right.
    I am sorry but there are still errors when copying the code from your page.
    the places with content:”; must be replaced with 2 quotes, that assigns empty.

    And in this part, you also need to insert new quotes as they appear incorrect when copied from your site.
    input:checked[type=”checkbox”]:nth-of-type(1) {

    Reply
    • Hi.
      It is better to share a link to pastebin or github because the comment’s section will mess up formatting of your code.
      Thanks for sharing.
      Regards,
      Sara

      Reply
    • Hi guys,

      Thank you for your extremely detailed tutorials!
      Unfortunately I encountered this error while trying to upload the code to my ESP32.

      C:\Users\admin\Documents\Arduino\libraries\AsyncTCP\src\AsyncTCP.cpp: In function ‘bool _start_async_task()’:
      C:\Users\admin\Documents\Arduino\libraries\AsyncTCP\src\AsyncTCP.cpp:221:141: error: ‘xTaskCreateUniversal’ was not declared in this scope

      xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);

      exit status 1
      Error compiling for board ESP32 Dev Module.

      May I kindly ask for a solution of this?
      Thank you in advance!

      Best regards,
      Alexandar Mandradzhiev

      Reply
      • Hi Alexandar.
        You may need to update your ESP32 boards.
        Go to Tools > Board > Boards Manager and Search for “ESP32”, then, install the most recent version.
        Regards,
        Sara

        Reply
        • Hi,

          I tried updating my board to the latest version, it didn’t work, then to the previous one, still not working. Then completely uninstalled and installed it again, still nothing.
          Seems like there is a problem with my system.

          Thanks for the fast response!
          Greetings

          Reply
  11. Hi Sara,

    I measured the pin 5, this port delivere 3,3V normally when I send a comand button on the HTML client.
    I connected the 3,3V of my board, directly to the rele module and it still doesn’t work. It working only 5V, but my rele module rele seem to be same of you.

    Reply
  12. Dear Sara,
    I just wanted to give a static ip for this project, so i implemented the example code for static ips from your homepage in the code above, but i allways get the same error when compiling: ‘server’ does not name a type
    Would it be possible to give me a hint what to do for giving a static ip?
    Kind regards, Boris

    Reply
      • Dear Sara, thanks for your quick reply :-)…
        I checked the Async-Webserver and the code is there… the error occures at the end of the script…
        // Start server
        server.begin();
        RelaisESP32:140:3: error: ‘server’ does not name a type
        The code is in the link below:
        github.com/Bobischlock/ESP32/blob/master/Server%20Error
        I am relatively new in programming with Arduino, so maybe its an newbie error..:-)

        Reply
  13. Hello, I’m new with ESP32, and want to ask is it possible to do this project like you did with “ESP32 Web Server using SPIFFS”. I want to create website more fascinating (graphs, panels, buttons, sliders – separated with TABS) and upload separately, in this case all your code is written in arduino ide, in this case it’s a bit confusing. I’m not sure if I asked clearly 🙂
    Thank YOU for great tutorials 🙂

    Reply
    • Hi.
      Yes, you can use SPIFFS to save your web page files like CSS, HTML or a few icons.
      Then, you just need to reference the files when you receive a request for those files like the tutorial you refer: https://randomnerdtutorials.com/esp32-web-server-spiffs-spi-flash-file-system/

      However, notice that this particular example, creates the HTML dynamically depending on the number of relays.
      To use SPIFFS, you need to know beforehand how many relays you’ll have and create the appropriate HTML text for that.

      I think I answered your question.

      Regards,
      Sara

      Reply
  14. first of all, thankyou so much for the tutorial. i want to ask, so is it safe to connect the relay directly to my esp32 3.3v board? i mean you said that it is not physically isolated from the relay and in case of electrical spikes, it can damages my esp32. so how to overcome this?

    Reply
    • Hi.
      You can remove the jumper cap and power the electromagnet of the relay (JD-VCC) pin with an independent power supply.
      Regards,
      Sara

      Reply
      • Is it safe to then use a 12Volt supply on the JD-VCC pin if you have 12Volt relays ? Or should this still only be a 5V Supply and I have the wrong relay board ?

        Reply
  15. Hello Sara,

    also thanks from my side for this great tutorial.
    My ESP32 works with the relay in general.

    The ESP32+realy are some meters away from my wifi and it seems sometimes (after some hours) it disconnects from it.
    Any suggestions?
    Might there be something I can add to the loop() to check the wifi connections and in case of a lost to reconnect?

    Thanks
    Norbert

    Reply
      • Sara, thanks for this suggestion.
        It improved the situation but the ESP still lost the wifi connection after several ours.
        I added now a counter in the loop to count the reconnects and show this on the web page. By this I saw that it needs some reconnects.
        It’s outside, so I can’t use the serial to my PC to monitor the status. Therefor I added a LED and switch this in the loop like a sign of life. In normal mode with low frequency (on/off for 10sec) and higher during the reconnect with 1sec.

        It also seems at startup that a wifi connect works immediately or not – so waiting does not help. In the worst case it was better to reboot instead of waiting.
        Is this normal?
        If the above does not help I plan to try a restart if a reconnect does work after short time (10s).

        Additional info: I’m using a ESP32 DevKitC v4 wroom32u board with external antenna. Stable power supply with 5v and 2A.

        And one more question:
        How is the loop function internal developed? Especially related to the “emtpy” loop. Does it “spin” or is there a kind of logic like “empty => do nothing”.
        Or further: empty => sleep (low power mode).

        Reply
        • sorry I mean:

          If the above does not help I plan to try a restart if a reconnect does NOT work after short time (10s).

          Reply
  16. Hello Sara,

    Thank you for this great tutorial. I want to control ceiling fan speed with ESP32 Board could you plese guide me.

    Thanks & Regards,
    Mahe

    Reply
  17. I face this issue – ” Error compiling for board NodeMCU 1.0 (ESP-12E Module). ” what should I do for this?
    Thanks!

    Reply
      • How do I take this sketch and the sketch you have for temperature alarms with a high and low threshold. I’ve tried to combine the two and I get error after error and can’t figure it out. Could you help . Thank you

        Reply
  18. Hi, can use ESP8266 or other ESP module instead of ESP32?
    I have NodeMCU board and ESP8266-01 and 12F. I wanna use one f these modules instead of ESP32. Is that ok and can I do that?

    Reply
  19. after adding
    string relayNames [NUM_RELAYS] = {
    as Norbert says and
    Jørgen B.’s 3d dark mod
    has become beautiful,
    I even found on taobao a small esp32 card with 12 mosfets which fits on the card with 16 relays.
    I added this to tile the buttons which I think is more beautiful on the phone.
    css

    div {
    background: black;
    margin: 10px 10px 10px 10px;
    float:left;
    position:relative;
    }

    and html i have added div

    if(var == “BUTTONPLACEHOLDER”){
    String buttons =””;
    for(int i=1; i<=NUM_RELAYS; i++){
    String relayStateValue = relayState(i);
    buttons+= ”

    ” + relayNames[i-1] + ”

    “;
    }

    thank you

    Reply
  20. I can do little with c, I would like it if someone wrote a modification, to make a button of my choice become with the settable action time.
    in other words, I would like when I press the button, it stays on for a while, then automatically turns off.

    Reply
  21. Hola buen tutorial, me preguntaba si se puede además de tener un botón en el servidor web, que se pueda tener otro físicamente por si se queda sin conexión wifi.

    Reply
  22. Super tutorial! Almost exactly what I was looking for!

    I am planning a control to control our 8 electric shutters via a 16 channel relay card with the ESP web server.
    For this I need the signals but not as a switch with toggle, but as a button.

    So as long as the button is pressed “virtually” on the web page, the output on the ESP should be active. If the pushbutton is released, the output should also go off immediately!

    That would be per shutter one button for open, and one button for close.
    The final control of the shutters is done by a Siemens PLC.

    Is it possible to change this from “switch” to “pushbutton” function in your code or is this something totally different?

    Thanks in advance!
    Kind regards
    Frank

    Translated with http://www.DeepL.com/Translator (free version)

    Reply
  23. Hello
    my question is how is it possible to have an other esp in the same wifi to control this esp remotely
    (i would like to use a wifi remote using esp and nextion but the problem is communication between two esps)

    Reply
  24. Hi,

    First of all, thank you for this great tutorial. I have a beginner question, I want to control a 16 channel relay with a single esp32 is that possible without a pin expander? If yes can I use all pins which are as “OK” marked in “INPUT” and “OUTPUT” field at this pinout reference –> https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
    If I can’t is there a pin expander which you can recommend or maybe another tutorial about pin expanders? Thank you in advance.

    Reply
    • Hi.
      You can use all the pins marked as OK and that don’t output a PWM signal when the ESP32 first starts.
      Regards,
      Sara

      Reply
  25. Hallo, nice Job. I love it. I have write 1 relativ an gpio 26. It work super. But vor my Pjoket i nee no switch. I need an Tip switch. I dont know the Word in english. I tip on the Button an in this time ist clone the relay and when i leave the Button the relay opens. Can you help me please? Thanks

    Reply
  26. Relay WebServer
    I’m getting an error on Line 68
    String relayStateValue = relayState(i);

    error says – ‘relayState’ was not declared in this scope

    I copy/pasted the code from the website (raw code), made one change, I changed GPIO 2 to 32 on line 20.

    Reply
        • I am using VS Code, made suggested change and the sketch uploaded without error. Had one little issue (mine), I thought the terminal and serial monitor were the same and was not able to find the local IP address. I finally discovered the serial monitor icon and was able to access the website. Thanks.

          Reply
  27. Hi.

    This is a nice project. Thank you so much.
    I successfully repeated the project. It worked perfectly.

    Could do you please improve it by making accessible from anywhere over the internet?

    It could help me since it is a part of my academic project.
    Thanks in advance.

    Reply
  28. hi nice job
    i have a rely with 12vdc and its can power with esp8266 i need to connect 12 volts sure. i think i must conecte it with gnd and JD- Vcc but its don’t work can you help me how to connect the pin

    Reply
  29. Hi nice tut, however , every time it turn off the esp32 and power it back on, it activate the relay and have to press the reset button to connect back to network.

    Reply
  30. Hi, I’m heating the house by wood. Hydraulics are good. But I would do the “handiwork” by ESP32-S3. Can i use the 18 DO’s on the ESP32 to control the “computer” (by the tractor), 50 meters away the control?? Control by Samsung S10 (by hand)?? Good info by you !!
    Thanks You
    Mikael

    Reply
  31. If there are two web clients connected and one of them toggles the switch, the switch state will not be updated for the other. A slight bug on web page 🙂

    Reply
  32. Hi Sara!
    thankyou so much for the tutorial and the code.
    it help me a lot!

    But I just a beginner and have to use a high trigger relay for my project.
    could you please show me what should I change on the code?
    Thankyou:)

    Reply
  33. Hello,
    Im making a relay system from /ESP32/ESP8266 Relay Module – Control AC Appliances (Web Server)/. Base i use ESP32 ProS3. I use 18 D0 for control of hydraulics.
    The software is ok, but when Im doing “upload and save” I get: “Error, check bord is available”.
    Is the board ProS3 not ready in Arduino?? Can I use someting else, I want to use the S3.
    Thanks

    Reply
  34. Hi Sara,
    This is very good project and i am using it to connect my ESP32 installed in 3dprinter to turn ON and OFF remotely but when my router ssid and password changed I have to remove my esp32 from 3dprinter and connect it to desktop in order to update ssid and password. Is it possible that when ever ESP32 is not able to connect to router it activate access point so I can change ssid and password remotely without removing it from 3dprinter and control the 3d printer ON and OFF?
    Thank you and i really appreciate your help

    Reply
    • Hi.
      Yes. Take a look online at some “WiFiManager” examples.
      I think that’s exactly what you’re looking for.
      Regards,
      Sara

      Reply
  35. Hi Sara, Is there a way to activate 2 gpio at the same time? example the gpio 27 + 28 or 29 + 28? always repeating one. Tanks!

    Reply
  36. I am wanting to use this to control my grandson’s ride-on ATV like a powerwheels. My reason is so that he can’t get too far away before I can catch him since I don’t move as fast as I used to. If he gets too far away from me and I lose the wifi connection I want it to turn off the relay(s) and kill the ATV and remain off until I catch up with him and can turn it back on.
    So basically I want it to disable (turn off) all relays unless it has a valid connection to my phone AND I press the “Enable” button on my phone. I know it might not have the actual status displayed on my phone (i.e. it might say Enabled but it won’t be connected so it is actually disabled at that time) but I can easily refresh or press the button twice if needed.
    How do I create a default state or fallback state so it kills the relay(s) when it loses wifi connection?

    Reply
      • I’m not sure if that is what I’m looking for. I am using the esp32 as the wifi server and accessing it with my phone. It is serving a very basic page that has an Enable/Disable button and if my phone (or rather the client in my case) isn’t connected to the esp32 server or loses connection the status of the button or more importantly the relay(s) revert to their default Off state. The functions you mention seem to be events for when the esp32 is a client rather than a server. I am wanting to shut down the relay(s) if no client is connected to the esp32 server.

        Reply
  37. GOOD job for that tuto.
    I would need for 1 output to have a pulse signal, does it possible on your code ?
    I tried to add in the void loop something like that:
    void loop() {
    pinMode(relayGPIOs[4], OUTPUT);
    if (relayGPIOs[4], LOW);
    delay (5000);
    digitalWrite (relayGPIOs[4], HIGH);
    }
    thnaks

    Reply
  38. perfect and clear tutorial.
    will you make another tutorial about how to write a code to does the same job, but using the goolgle assistant and such?
    thanks alot.

    Reply
  39. Hi,

    I installed this on a premade board with an ESP32-WROOM-32E. Relay#3 is connected to GPIO25, but doesn’t switch when I switch the button. It actually switches every few seconds. I don’t have any idea why, so is that normal behavior?

    Thanks!

    Reply
  40. Hello, very good job.
    I would like to know if it will be possible to have the code with a different function, let me explain;
    It is for a watering need with 6 sectors manually.
    Here I need 7 relays, one to turn on my pump and the other 6 for each watering sector (1 per sector).
    When I want to switch on the 1st sector I would like the pump relay to switch on with the relay of sector 1; when I want zone 2 I would like the sector 2 relay to switch on with the pump relay and so on for the other relays (6 sector).
    Would it be possible to make this complete code, I thank you in advance.

    Reply
  41. Thank you for the tutorial, it has been of great help, but when I write the code on my ESP32 board this error occurs:
    A fatal error occurred: MD5 of file does not match data in flash!
    can you help me?

    Reply
  42. hi all after pressing rest button i got this massage:
    23:00:35.365 -> Connecting to WiFi..
    can not get ip address .
    any one can help ?
    thanks

    Reply
  43. Can I connect a relay module with a weighing scale circuit using ESP32, and whenever I get 3 reading constant the relay should turn off automatically?

    Reply
  44. Hi Sara, first thank you so much for the tutorial.

    I’ve bought a 16 relay board with optocouplers, powered on by a 12v separated alimentation.
    Then I’ve uploaded your code on my esp32.
    My issue is that despite having connected the esp32 nodemcu with a microusb cable to 5v and the vin pin and ground to the relay board pins (vcc and gnd), it doesn’t work at all. The webserver is online, but the relay board seems not to have the right power to work properly.

    Have you some suggestions for me please?

    Reply
  45. Hello all!

    I’ve created a very customisable easy-2-use firmware for ESP32-based relay boards. It has WEB interface, supports MQTT and Home Assistant integration.
    You can either use all-in-one relay board (means that MCU and relays are on the same board) or you can connect relays to any board chosen (e.g., ESP32-DevKit).

    Check it out here: github.com/rpavlyuk/ESPRelayBoard

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.