Home / Tutorials / ESP8266 Tutorial / How To Use an ESP8266 WiFi Relay Board
pcbway
ESP8266 Relay Module

How To Use an ESP8266 WiFi Relay Board

If you’re looking for a simple but powerful way to control AC or DC devices over Wi‑Fi, the ESP8266 relay board is one of the best places to start. I’ve used ESP8266‑based boards in many hobby and semi‑professional projects, and relay boards are usually the first real‑world application people build.

In this tutorial, I’ll walk you through exactly how I use an ESP8266 relay board, from understanding the hardware to writing the firmware and controlling a relay over Wi‑Fi. This is written as if I’m personally guiding you through the process.


What Is an ESP8266 Relay Board?

An ESP8266 relay board combines two things on one PCB:

  • ESP8266 Wi‑Fi microcontroller (usually ESP‑12 / ESP‑12F)
  • One or more mechanical relays for switching higher‑voltage or higher‑current loads

Because the ESP8266 has built‑in Wi‑Fi, the relay can be controlled:

  • From a web browser
  • From a phone app
  • From another server or IoT platform

This makes it perfect for:

  • Home automation
  • Smart switches
  • Remote power control
  • IoT experiments

Typical ESP8266 1-Channel Relay Board Features

This guide is specifically written for a 1-channel ESP8266 relay board, which is the most common and beginner-friendly version.esp8266-relay-module-top-with-labels

  • A: 7-30V+ DC power supply
  • B: Power supply ground
  • C: ESP8266 Serial Port (Used to program the ESP8266)
  • D: ESP8266 Boot Select
  • E: Normally closed (NC) relay contact
  • F: Common (COM) relay contact
  • G: Normally open (NO) relay contact
  • H: 5V+ out
  • I: ESP8266 GPIO5 Optocoupler Input
  • J: Ground (isolated optocoupler input)

⚠️ Important: Even though the ESP8266 runs at 3.3V, the relay side may switch 110V / 220V AC.


Understanding the Relay Terminals (Very Important)

Each relay has three main terminals:

  • COM (Common) – the moving contact
  • NO (Normally Open) – disconnected when relay is OFF
  • NC (Normally Closed) – connected when relay is OFF

How I usually wire it

  • For devices that should be OFF by default → I use COM + NO
  • For devices that should be ON by default → I use COM + NC

Powering the ESP8266 Relay Board

This is where many beginners make mistakes.

Common power options

  1. 5V via Micro‑USB (recommended if available)
  2. 5V to VIN pin
  3. External regulated 5V supply

The onboard regulator converts 5V → 3.3V for the ESP8266.

⚠️ I avoid powering relays from weak USB ports. Relays draw surge current when switching.


ESP8266 GPIO Pin Used for a 1-Channel Relay

On a 1-channel relay board, only one GPIO is used to control the relay.

Before coding, I always:

  • Check the board schematic or silkscreen
  • Test the relay manually with a simple sketch

My board uses GPIO4 to control the relay. This is shown in the schematic:

WiFi ESP8266 Relay

⚠️ Some GPIOs affect boot mode (GPIO0, GPIO2, GPIO15). Using the wrong pin can prevent booting.


Programming the ESP8266 Relay Board

What I use

  • Arduino IDE
  • ESP8266 Board Package
  • USB‑to‑Serial driver (CH340 or CP2102)

Adding ESP8266 to Arduino IDE

  1. Open Arduino IDE
  2. Go to Preferences
  3. Add this URL to Additional Boards Manager URLs: https://arduino.esp8266.com/stable/package_esp8266com_index.json
  4. Install ESP8266 Boards from Boards Manager

Simple Relay Control Code (My Go‑To Test Sketch)

This is the first sketch I upload to confirm the hardware works.

#define RELAY_PIN 4  // change based on your board

void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // relay OFF (some boards are inverted)
}

void loop() {
  digitalWrite(RELAY_PIN, HIGH); // relay ON
  delay(2000);
  digitalWrite(RELAY_PIN, LOW);  // relay OFF
  delay(2000);
}

If the relay clicks every 2 seconds, your board is working.


Relay Logic: Normal vs Inverted

Many ESP8266 relay boards are active‑LOW, meaning:

  • LOW → Relay ON
  • HIGH → Relay OFF

If your relay behaves backward, simply invert the logic in software.


Controlling the Relay via Wi‑Fi (Web Server Example)

This is where the ESP8266 really shines.

What I usually do

  • Run a small HTTP server
  • Add /on and /off endpoints
  • Control the relay from any browser
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid     = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";

ESP8266WebServer server(80);

// Pin definitions
#define RELAY_PIN 4   // Relay control (active LOW)
#define OPTO_PIN  5   // Optocoupler input (INPUT_PULLUP)

// State tracking
volatile bool relayState = false;
volatile bool optoState  = false;

// -------------------- Relay handlers --------------------

void handleOn() {
  relayState = true;
  digitalWrite(RELAY_PIN, LOW);   // active LOW
  server.send(200, "text/plain", "Relay ON");
}

void handleOff() {
  relayState = false;
  digitalWrite(RELAY_PIN, HIGH);
  server.send(200, "text/plain", "Relay OFF");
}

// -------------------- Optocoupler handler --------------------

bool readOptoDebounced() {
  // Read optocoupler (normally HIGH, pulled LOW when active)
  if (digitalRead(OPTO_PIN) == LOW) {
    delay(20); // debounce
    if (digitalRead(OPTO_PIN) == LOW) {
      return true;   // opto active
    }
  }
  return false;      // opto inactive
}

void handleInput() {
  optoState = readOptoDebounced();

  if (optoState) {
    server.send(200, "text/plain", "Opto INPUT: ON");
  } else {
    server.send(200, "text/plain", "Opto INPUT: OFF");
  }
}

// -------------------- Setup --------------------

void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(OPTO_PIN, INPUT_PULLUP);

  // Relay OFF at boot (safe default)
  digitalWrite(RELAY_PIN, HIGH);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  // HTTP endpoints
  server.on("/on", handleOn);
  server.on("/off", handleOff);
  server.on("/input", handleInput);

  server.begin();
}

// -------------------- Main loop --------------------

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

Now I can control the relay by opening:

  • http://ESP_IP/on
  • http://ESP_IP/off

Additional Notes:

  1. You must connect a separate and appropriate power supply independent of the USB‑to‑Serial programmer when programming. The USB‑to‑Serial programmer probably has insufficient power.
  2. P5 connector (labeled D in the guide image above) is meant to be jumped together only during programming. When programming is complete, remove the jumper and reboot.
  3. Connect your USB‑to‑Serial RX to P6 (labeled C) TX, and USB‑to‑Serial TX to P6 RX, and USB‑to‑Serial ground to the ground.

Common Problems 

Relay clicks randomly

  • Power supply is weak
  • Add bulk capacitor (470µF–1000µF)

ESP8266 keeps rebooting

  • Relay coil noise
  • Poor grounding
  • Use opto‑isolated relay board

Board won’t boot

  • Wrong GPIO used
  • GPIO0 or GPIO2 held LOW at boot

Safety Notes 

When switching AC mains:

  • Never touch the board while powered
  • Use proper enclosures
  • Keep high‑voltage and low‑voltage sides separated
  • If unsure, test with low‑voltage DC first

I always prototype with a 12V load before moving to AC.


Home Assistant via REST (HTTP)

Relay as a Home Assistant switch

Add this to configuration.yaml:

switch:
  - platform: rest
    name: ESP8266 Relay
    resource: http://ESP_IP/on
    method: GET
    body_on: ""
    body_off: ""
    state_resource: http://ESP_IP/input
    is_on_template: "{{ value == 'Relay ON' }}"

⚠️ Limitation:

  • REST switch does not automatically know the relay state
  • Home Assistant assumes success if HTTP 200 is returned

When this is OK

  • Manual switching
  • Simple dashboards
  • No complex automations

Optocoupler input as a binary sensor

Add this:


binary_sensor:
  - platform: rest
    name: ESP8266 Opto Input
    resource: http://ESP_IP/input
    scan_interval: 1
    value_template: >
      {{ 'ON' in value }}

Now Home Assistant sees the optocoupler as:

  • Door sensor
  • Button
  • External trigger
  • Dry contact

This is very powerful.


Automation example (opto → relay)

automation:
  - alias: "Opto turns relay ON"
    trigger:
      - platform: state
        entity_id: binary_sensor.esp8266_opto_input
        to: "on"
    action:
      - service: switch.turn_on
        target:
          entity_id: switch.esp8266_relay

REST drawbacks 

❌ No guaranteed state
❌ No retain
❌ Polling overhead
❌ Hard to scale

That’s why MQTT exists.


Home Assistant via MQTT (recommended)

This is how commercial IoT devices do it.


MQTT concept (simple view)


Home Assistant ──▶ MQTT ──▶ ESP8266
Home Assistant ◀─ MQTT ◀── ESP8266
  • Commands and state are decoupled
  • Works even if HA restarts
  • Instant updates (no polling)

MQTT topics for your device

I recommend this structure:

Purpose Topic
Relay command home/relay1/set
Relay state home/relay1/state
Opto state home/relay1/opto

Home Assistant MQTT config

mqtt:
  switch:
    - name: "ESP8266 Relay"
      command_topic: "home/relay1/set"
      state_topic: "home/relay1/state"
      payload_on: "ON"
      payload_off: "OFF"
      state_on: "ON"
      state_off: "OFF"
      retain: true

  binary_sensor:
    - name: "ESP8266 Opto Input"
      state_topic: "home/relay1/opto"
      payload_on: "ON"
      payload_off: "OFF"

Now:

  • Relay state is authoritative
  • Opto input is event-driven

ESP8266 MQTT behavior (logic summary)

Your ESP8266 should:

On boot
  • Publish relay state
  • Publish opto state
On relay change
  • Publish
    home/relay1/state
On opto change
  • Publish
    home/relay1/opto

This eliminates guesswork.


ESPHome (cleanest long-term option)

If you’re OK reflashing firmware, ESPHome is unbeatable.


ESPHome YAML for your board


esphome:
  name: esp8266_relay

esp8266:
  board: esp12e

wifi:
  ssid: "YOUR_WIFI"
  password: "YOUR_PASSWORD"

switch:
  - platform: gpio
    pin:
      number: GPIO4
      inverted: true
    name: "Relay"

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO5
      mode: INPUT_PULLUP
      inverted: true
    name: "Opto Input"

✔ Automatic HA discovery
✔ Proper state handling
✔ OTA updates
✔ Debouncing support


Final Thoughts

For a 1-channel ESP8266 relay board, the workflow is simple:

  1. Verify relay GPIO and logic
  2. Test with a basic blink sketch
  3. Add Wi-Fi control
  4. Integrate with Home Assistant

This setup scales well, and I’ve used the same pattern for lights, pumps, fans, and power control.

The ESP8266 relay board is one of the fastest ways I know to go from code to real‑world control. With just a few lines of code, you can switch devices from anywhere on your network.

Check Also

L298N Motor Controller Tutorial

How to Use L298N Motor Driver with ESP8266

Updated: November 9, 2024Controlling a DC motor with an ESP8266, L298N motor driver module, and …

Index