This tutorial is a step-by-step guide that covers how to build a standalone ESP32 or ESP8266 NodeMCU Web Server that controls any relay module using MicroPython firmware. We’ll create an ESP32/ESP8266 Web Server that is mobile responsive and it can be accessed with any device with a browser in your local network.
If you want to learn how a relay module works, read our MicroPython Guide: Relay Module with ESP32/ESP8266.
We have similar guides using Arduino IDE:
- Guide for ESP32 Relay Module with Arduino IDE – Control AC Appliances + Web Server
- Guide for ESP8266 NodeMCU Relay Module with Arduino IDE – Control AC Appliances + Web Server
Prerequisites
To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:
- Thonny IDE:
- uPyCraft IDE:
- Getting Started with uPyCraft IDE
- Install uPyCraft IDE (Windows, Mac OS X, Linux)
- Flash/Upload MicroPython Firmware to ESP32 and ESP8266
Learn more about MicroPython: MicroPython Programming with ESP32 and ESP8266 eBook.
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/ESP8266 GPIOs and allows us to control high voltages like 12V, 24V or mains voltage (230V in Europe and 120V in the US).
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 you can control.
Get a relay module:
- 5V 2-channel relay module (with optocoupler)
- 5V 1-channel relay module (with optocoupler)
- 5V 8-channel relay module (with optocoupler)
- 5V 16-channel relay module (with optocoupler)
- 3.3V 1-channel relay module (with optocoupler)
Wiring a Relay Module to the ESP32/ESP8266
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.
ESP32 Schematic Diagram
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.
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.
ESP8266 NodeMCU Schematic Diagram
Follow the next schematic diagram if you’re using an ESP8266 NodeMCU.
We’re connecting the IN1 pin to GPIO 5, you can use any other suitable GPIO. See ESP8266 NodeMCU GPIO Reference Guide.
The best ESP8266 pins to use with relays are: GPIO 5, GPIO 4, GPIO 14, GPIO 12 and GPIO 13.
MicroPython Relay Web Server Code (Script)
The code to control a relay with the ESP32 or ESP8266 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.
Copy the following code to the main.py file and upload it to your board. It lights up your lamp for 10 seconds and turn it off for another 10 seconds.
# Complete project details at https://RandomNerdTutorials.com
from machine import Pin
from time import sleep
# ESP32 GPIO 26
relay = Pin(26, Pin.OUT)
# ESP8266 GPIO 5
#relay = Pin(5, Pin.OUT)
while True:
# RELAY ON
relay.value(0)
sleep(10)
# RELAY OFF
relay.value(1)
sleep(10)
How the code works
Import the Pin class from the machine module to interact with the GPIOs. We also import the sleep() method from the time module to add delays.
from machine import Pin
from time import sleep
Then, we define a Pin object called relay on 26 (if you’re using an ESP32) and define it as an output.
# ESP32 GPIO 26
relay = Pin(26, Pin.OUT)
In case you’re using an ESP8266, use GPIO 5 instead. Comment the previous line and uncomment the following.
# ESP8266 GPIO 5
#relay = Pin(5, Pin.OUT)
In the while loop, send a LOW signal to light up the lamp for 10 seconds.
# RELAY ON
relay.value(0)
sleep(10)
If you’re using a normally closed configuration, send a HIGH signal to light up the lamp.
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.
# RELAY OFF
relay.value(1)
sleep(10)
Control Relay Module with MicroPython Web Server
In this section, we’ve created a web server example that allows you to control a relay remotely via web server.
boot.py
Copy the following code to your boot.py file.
# Complete project details at https://RandomNerdTutorials.com
try:
import usocket as socket
except:
import socket
from machine import Pin
import network
import esp
esp.osdebug(None)
import gc
gc.collect()
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
print(station.ifconfig())
# ESP32 GPIO 26
relay = Pin(26, Pin.OUT)
# ESP8266 GPIO 5
#relay = Pin(5, Pin.OUT)
Insert your network credentials in the following variables:
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
Uncomment one of the following lines accordingly to the board you’re using. By default, it’s set to use the ESP32 GPIO.
# ESP32 GPIO 26
relay = Pin(26, Pin.OUT)
# ESP8266 GPIO 5
#relay = Pin(5, Pin.OUT)
main.py
Copy the following to your main.py file.
# Complete project details at https://RandomNerdTutorials.com
def web_page():
if relay.value() == 1:
relay_state = ''
else:
relay_state = 'checked'
html = """<html><head><meta name="viewport" content="width=device-width, initial-scale=1"><style>
body{font-family:Arial; text-align: center; margin: 0px auto; padding-top:30px;}
.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><script>function toggleCheckbox(element) { var xhr = new XMLHttpRequest(); if(element.checked){ xhr.open("GET", "/?relay=on", true); }
else { xhr.open("GET", "/?relay=off", true); } xhr.send(); }</script></head><body>
<h1>ESP Relay Web Server</h1><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" %s><span class="slider">
</span></label></body></html>""" % (relay_state)
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
while True:
try:
if gc.mem_free() < 102000:
gc.collect()
conn, addr = s.accept()
conn.settimeout(3.0)
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
conn.settimeout(None)
request = str(request)
print('Content = %s' % request)
relay_on = request.find('/?relay=on')
relay_off = request.find('/?relay=off')
if relay_on == 6:
print('RELAY ON')
relay.value(0)
if relay_off == 6:
print('RELAY OFF')
relay.value(1)
response = web_page()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)
conn.close()
except OSError as e:
conn.close()
print('Connection closed')
We won’t explain how this code works because we already have a very similar tutorial with detailed explanation of each line of code. Read the next project:
Demonstration
After making the necessary changes, upload the boot.py and main.py files to your board. Press the EN/RST button and in the Shell you should get the ESP IP address.
Then, open a browser in your local network and type the ESP IP address to get access to the web server.
You should get a web page with a toggle button that allows you to control your relay remotely using your smartphone or your computer.
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.
Wrapping Up
Using relays with the ESP is a great way to control AC household appliances remotely. You can also read our complete guides about relay modules:
- [Arduino IDE] Guide to control a Relay Module with the ESP32
- [Arduino IDE] Guide to control a Relay Module with ESP8266 NodeMCU
- [MicroPython] MicroPython: Relay Module with ESP32/ESP8266 (Guide)
- [Arduino IDE] Guide for Relay Module with Arduino Board
Learn more about MicroPython with the ESP32 and ESP8266 with our resources:
Thanks for reading.
Hello
I try this tutorial but have problem
Traceback (most recent call last):
File “main.py”, line 19, in
NameError: name ‘socket’ isn’t defined
MicroPython v1.12 on 2019-12-20; ESP module with ESP8266
Type “help()” for more information.
is the same in your code:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((”, 80))
s.listen(5)
Is Working
thanks
Mauricio
Hi.
You probably didn’t upload the boot.py where we import the libraries.
Regards,
Sara
Can it also control sensors? Like activating and deactivating the DHT11.
When I push EN button, in terminal (console) display that.
<<
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:4540
ho 0 tail 12 room 4
load:0x40078000,len:12344
ho 0 tail 12 room 4
load:0x40080400,len:4124
entry 0x40080680
Hello, I am stuck and I need help
I am trying to add to the html code another check box but I am having an error and I don’t understand what it means
added code:
Type Error:
format string needs more arguments