DEV Community

張旭豐
張旭豐

Posted on

5 Relay Module Projects That Automate Your Home

5 Relay Module Projects That Automate Your Home

Build home automation systems: smart light switch, coffee maker timer, garage door controller, aquarium feeder, and Christmas light timer

Relay Module Home Automation Hero

The 5V relay module is the bridge between your Arduino's low-voltage logic and high-voltage AC appliances. It lets you turn lights, fans, pumps, and heaters on and off automatically. In this guide, we'll build five home automation projects that make everyday devices smarter.

Topics covered: Relay logic (NO/NC), optocoupler isolation, inductive load protection, timer logic, ESP8266 WiFi control, human machine interface design.


What You'll Need

  • 5V relay module (1-channel or 2-channel)
  • Arduino Nano or ESP8266 (×1)
  • Jumper wires
  • High-voltage appliances to control (lamp, coffee maker, pump)
  • DS3231 RTC module (for timer projects)

How the Relay Module Works

A relay is an electrically-operated switch. When the Arduino sends a HIGH signal to the relay's IN pin, the electromagnet pulls the contact closed, completing the AC circuit. The optocoupler provides electrical isolation between Arduino and AC side.

Arduino          Relay Module
  Pin 7  ──────  IN
  5V     ──────  VCC
  GND    ──────  GND

Relay COM   ────  AC Live wire
Relay NO    ────  Device Live wire
AC Neutral  ────  Device Neutral
Enter fullscreen mode Exit fullscreen mode

Safety: Always work with AC power disconnected. Use proper enclosures. Never touch relay contacts when powered.

// WF1 Run #041 - Basic Relay Control
#define RELAY_PIN  7

void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Relay starts OFF (NC=closed when powered)
}

void loop() {
  digitalWrite(RELAY_PIN, HIGH);  // Turns device ON
  delay(5000);
  digitalWrite(RELAY_PIN, LOW);   // Turns device OFF
  delay(5000);
}
Enter fullscreen mode Exit fullscreen mode

Project 1: Smart Light Switch

Goal: Control a room lamp with a manual button and automatic schedule using an ESP8266 WiFi relay.

Smart Light Switch

Hardware

  • ESP8266 (Wemos D1 Mini)
  • 5V 1-channel relay
  • Push button
  • USB 5V power supply

Code

// WF1 Run #041 - Project 1: Smart Light Switch (ESP8266)
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

#define RELAY_PIN    D1
#define BUTTON_PIN   D3

#define WIFI_SSID    "YourSSID"
#define WIFI_PASS    "YourPassword"

bool lightState = false;
bool scheduleOn = false;
bool scheduleOff = false;

ESP8266WebServer server(80);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000);

const char page[] PROGMEM = R"=====(
<html><body><h1>Smart Light</h1>
<button onclick='fetch(\"/toggle\")'>Toggle</button>
<p>Current time: <span id='time'></span></p>
<script>setInterval(()=>fetch('/time').then(r=>r.text()).then(t=>document.getElementById('time').innerText=t),1000);</script>
</body></html>
)=====";

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  digitalWrite(RELAY_PIN, LOW);

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);

  timeClient.begin();

  server.on("/", [](){ server.send(200, "text/html", page); });
  server.on("/toggle", [](){ lightState = !lightState; digitalWrite(RELAY_PIN, lightState ? HIGH : LOW); server.send(200, "text/plain", lightState?"ON":"OFF"); });
  server.on("/time", [](){ server.send(200, "text/plain", String(timeClient.getHours())+":"+String(timeClient.getMinutes())); });
  server.begin();
}

void loop() {
  server.handleClient();
  timeClient.update();

  int hour = timeClient.getHours();
  if (hour == 7 && !scheduleOn) { digitalWrite(RELAY_PIN, HIGH); lightState = true; scheduleOn = true; }
  if (hour == 8 && scheduleOn) scheduleOn = false;
  if (hour == 22 && !scheduleOff) { digitalWrite(RELAY_PIN, LOW); lightState = false; scheduleOff = true; }
  if (hour == 23 && scheduleOff) scheduleOff = false;

  if (digitalRead(BUTTON_PIN) == LOW) {
    lightState = !lightState;
    digitalWrite(RELAY_PIN, lightState ? HIGH : LOW);
    delay(500);
  }
}
Enter fullscreen mode Exit fullscreen mode

Project 2: Coffee Maker Morning Timer

Goal: Have your coffee maker turn on automatically before you wake up, so fresh coffee is ready when you come to the kitchen.

Coffee Maker Timer

Hardware

  • Arduino Nano
  • DS3231 RTC module
  • 5V 2-channel relay (one for coffee maker, one for mug warmer)
  • 16×2 LCD I2C display

Code

// WF1 Run #041 - Project 2: Coffee Maker Timer
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

#define COFFEE_RELAY   7
#define WARMER_RELAY   8
#define LCD_ADDR       0x27

#define BREW_HOUR      6
#define BREW_MINUTE    30
#define WARMER_OFF_H   7
#define WARMER_OFF_M   30

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2);
bool brewed = false;
bool warmerOff = false;

void setup() {
  lcd.begin();
  lcd.backlight();
  pinMode(COFFEE_RELAY, OUTPUT);
  pinMode(WARMER_RELAY, OUTPUT);
  digitalWrite(COFFEE_RELAY, LOW);
  digitalWrite(WARMER_RELAY, LOW);

  if (!rtc.begin()) lcd.print("RTC Error");
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  DateTime now = rtc.now();

  lcd.clear();
  lcd.setCursor(0, 0);
  char buf[9];
  sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  lcd.print(buf);
  lcd.setCursor(0, 1);
  lcd.print(brewed ? "Coffee Ready!" : "Waiting...");

  // Brew time
  if (now.hour() == BREW_HOUR && now.minute() == BREW_MINUTE && !brewed) {
    digitalWrite(COFFEE_RELAY, HIGH);
    digitalWrite(WARMER_RELAY, HIGH);
    brewed = true;
    lcd.setCursor(0, 1);
    lcd.print("Brewing...     ");
  }

  // Auto-off warmer
  if (now.hour() == WARMER_OFF_H && now.minute() == WARMER_OFF_M) {
    digitalWrite(WARMER_RELAY, LOW);
    warmerOff = true;
  }

  // Reset flags at midnight
  if (now.hour() == 0) {
    brewed = false;
    warmerOff = false;
  }

  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Project 3: Garage Door Controller

Goal: Open and close your garage door from a button or via WiFi, with safety logic to stop if obstructed.

Garage Door Controller

Hardware

  • ESP8266
  • 5V relay module
  • Door sensor (magnetic reed switch)
  • Current sensor (ACS712) for obstruction detection
  • Status LED

Code

// WF1 Run #041 - Project 3: Garage Door Controller
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

#define RELAY_PIN       D1
#define SENSOR_PIN      D2
#define CURRENT_PIN     A0

#define WIFI_SSID "YourSSID"
#define WIFI_PASS "YourPassword"

bool doorOpen = false;
float baselineCurrent = 0;

ESP8266WebServer server(80);

void toggleDoor() {
  digitalWrite(RELAY_PIN, HIGH);
  delay(500);
  digitalWrite(RELAY_PIN, LOW);

  delay(1000);  // Wait for door to finish moving

  doorOpen = digitalRead(SENSOR_PIN) == HIGH;
}

float measureCurrent() {
  int samples = 100;
  long sum = 0;
  for (int i = 0; i < samples; i++) sum += analogRead(CURRENT_PIN);
  return (sum / samples) * (3.3 / 1024.0) / 0.185;  // ACS712 5A sensitivity
}

void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(SENSOR_PIN, INPUT_PULLUP);
  digitalWrite(RELAY_PIN, LOW);

  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);

  baselineCurrent = measureCurrent();

  server.on("/", [](){
    String s = doorOpen ? "OPEN" : "CLOSED";
    s += "<br><button onclick='fetch(\"/toggle\")'>Toggle</button>";
    server.send(200, "text/html", s);
  });
  server.on("/toggle", [](){ toggleDoor(); server.send(200, "text/plain", "OK"); });
  server.begin();
}

void loop() {
  server.handleClient();
  doorOpen = digitalRead(SENSOR_PIN) == HIGH;

  // Obstruction detection
  float current = measureCurrent();
  if (current > baselineCurrent + 1.5) {  // Motor stalling
    digitalWrite(RELAY_PIN, LOW);  // Stop
    Serial.println("OBSTRUCTION DETECTED");
  }
}
Enter fullscreen mode Exit fullscreen mode

Project 4: Aquarium Auto Feeder

Goal: Dispense fish food automatically twice per day, with manual feed button and LCD status display.

Aquarium Feeder

Hardware

  • Arduino Nano
  • DS3231 RTC
  • 5V relay
  • Small DC feeder motor or servo
  • 16×2 LCD I2C
  • Push button

Code

// WF1 Run #041 - Project 4: Aquarium Feeder
#include <Servo.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

#define SERVO_PIN   9
#define BUTTON_PIN  7
#define LCD_ADDR    0x27

#define FEED_1_H    8
#define FEED_2_H    19
#define SERVO_OPEN  90
#define SERVO_CLOSE 0

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2);
Servo feederServo;
bool fed1 = false, fed2 = false;

void feedFish() {
  feederServo.attach(SERVO_PIN);
  feederServo.write(SERVO_OPEN);
  delay(2000);
  feederServo.write(SERVO_CLOSE);
  delay(200);
  feederServo.detach();
}

void setup() {
  lcd.begin();
  lcd.backlight();
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  feederServo.write(SERVO_CLOSE);

  if (!rtc.begin()) lcd.print("RTC Error");
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  DateTime now = rtc.now();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Aquarium ");
  lcd.print(fed1 && fed2 ? "Fed!" : "Waiting");
  lcd.setCursor(0, 1);
  char buf[9];
  sprintf(buf, "%02d:%02d", now.hour(), now.minute());
  lcd.print(buf);

  if (now.hour() == FEED_1_H && !fed1) { feedFish(); fed1 = true; }
  if (now.hour() == FEED_2_H && !fed2) { feedFish(); fed2 = true; }
  if (now.hour() == 0) { fed1 = false; fed2 = false; }
  if (digitalRead(BUTTON_PIN) == LOW) { feedFish(); }

  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Project 5: Christmas Light Timer

Goal: Control Christmas tree lights with an automatic sunset-to-midnight schedule, adjustable by season.

Christmas Light Timer

Hardware

  • Arduino Nano
  • DS3231 RTC
  • 5V relay
  • LDR sensor (optional — for sunset detection)
  • LED indicator

Code

// WF1 Run #041 - Project 5: Christmas Light Timer
#include <Wire.h>
#include <RTCliv2.h>
#include <LiquidCrystal_I2C.h>

#define RELAY_PIN   7
#define LDR_PIN     A0
#define LED_PIN     13
#define LCD_ADDR    0x27

#define ON_HOUR     16   // 4 PM
#define OFF_HOUR    23   // 11 PM
#define LDR_THRESHOLD 300  // Below this = dark enough to turn on

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2);
bool lightsOn = false;

void setup() {
  lcd.begin();
  lcd.backlight();
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  if (!rtc.begin()) lcd.print("RTC Error");
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  DateTime now = rtc.now();
  int ldr = analogRead(LDR_PIN);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Xmas Lights");
  lcd.setCursor(0, 1);
  lcd.print(lightsOn ? "ON " : "OFF");
  lcd.setCursor(5, 1);
  lcd.print("LDR:");
  lcd.print(ldr);

  // Auto on between ON_HOUR and OFF_HOUR if dark enough
  if (now.hour() >= ON_HOUR && now.hour() < OFF_HOUR) {
    if (ldr < LDR_THRESHOLD && !lightsOn) {
      digitalWrite(RELAY_PIN, HIGH);
      digitalWrite(LED_PIN, HIGH);
      lightsOn = true;
    } else if (now.hour() == OFF_HOUR && lightsOn) {
      digitalWrite(RELAY_PIN, LOW);
      digitalWrite(LED_PIN, LOW);
      lightsOn = false;
    }
  } else {
    if (lightsOn) {
      digitalWrite(RELAY_PIN, LOW);
      digitalWrite(LED_PIN, LOW);
      lightsOn = false;
    }
  }

  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Problem Cause Fix
Relay clicks but device doesn't turn on NO/NC confusion Verify: NO = closed when energized; NC = closed when de-energized
Relay sticks or welds Inductive load surge (motor/pump) Add flyback diode (1N4007) across coil; add MOV varistor across AC contacts
Arduino resets when relay triggers Insufficient power Use separate 5V supply for relay; add 100µF capacitor across relay VCC/GND
False triggers Loose wiring Use screw terminals; add pull-down resistor (10K) on relay IN pin
ESP8266 relay won't work GPIO logic level Use a logic-level MOSFET or relay board with optocoupler; ESP8266 is 3.3V

Start Here

Affiliate disclosure: As an Amazon Associate, I earn from qualifying purchases.

The right parts make the difference:

5V Relay Module 2-Channel — Optocoupler isolated, great for home automation.

ESP8266 Wemos D1 Mini — WiFi built-in, perfect for smart home projects.

DS3231 RTC Module — Accurate real-time clock with battery backup.

ACS712 Current Sensor — For obstruction detection in motor projects.


Next Step: From Scene to Sensor, Without Writing Code

If this guide gave you ideas for your own setup — but you're not sure which sensors and outputs work best for your specific space — I can help you map that out.

I offer a personalized interactive device design guide at Fiverr:

👉 https://www.fiverr.com/phd_hfchang/generate-an-arduino-interactive-prototypef

What you get:

  • A custom guide based on your actual scene (not generic recommendations)
  • Sensor selection matched to user behavior and physical constraints
  • Interaction logic without needing to write code from scratch
  • Testing methodology with pass/fail criteria for each output

Tags: Arduino Relay Home Automation ESP8266 Smart Home IoT WiFi

Top comments (0)