An Arduino relay setup uses a low-voltage GPIO signal to trigger an electromagnetic switch, safely isolating your 5V microcontroller from high-voltage AC or high-current DC loads. The direct answer for safe 120V AC switching is to use an opto-isolated relay module (like the ubiquitous SRD-05VDC-SL-C based boards), wire the AC load through the Common (COM) and Normally Open (NO) terminals, and initialize the GPIO pin to its inactive state in your setup() function to prevent the relay from triggering during the Arduino boot sequence.
Relay Module Specifications and Load Limits
Before wiring any mains voltage, you must understand the physical limits of the relay on your module. Most standard blue 1-channel and 4-channel relay modules use the Songle SRD-05VDC-SL-C. While the datasheet claims a 10A resistive load rating, real-world inductive loads (like motors or transformers) will pit the contacts and cause premature failure if you do not derate them.
| Parameter | Datasheet Value | Practical Bench Limit (Derated) |
|---|---|---|
| Coil Voltage | 5V DC (Nominal) | 4.5V - 5.5V (Must supply adequate current) |
| Coil Current Draw | ~71 mA | Ensure GPIO/Optocoupler can sink this; do not drive coil directly from MCU pin |
| Contact Rating (Resistive) | 10A @ 120VAC / 24VDC | 8A continuous (Heaters, incandescent bulbs) |
| Contact Rating (Inductive) | 5A @ 120VAC | 2A - 3A (Motors, solenoids, LED drivers with high inrush) |
| Dielectric Strength | 4000 Vrms (Coil to Contact) | Relies on intact optocoupler; never bridge module grounds |
| Switching Time | 10 ms (Operate) / 5 ms (Release) | Do not use for high-frequency PWM; stick to <5 Hz switching |
For a deeper look into how electromagnetic relays function and why contact derating is necessary for inductive loads, refer to the comprehensive breakdown on Electronics Club's relay guide.
Parts List and Pin Mapping
This guide targets the Arduino Uno R3 (ATmega328P) or the Arduino Nano v3. Both operate at 5V logic, which perfectly matches the input requirements of standard 5V relay modules without needing logic-level shifters.
Required Materials:
- Arduino Uno R3 or Nano v3
- 5V 1-Channel Relay Module (Optocoupler isolated, e.g., Elegoo or HiLetgo)
- 120V AC Lamp with standard plug and cord
- 18 AWG stranded wire (for mains connections)
- Digital Multimeter (for continuity and AC voltage verification)
- Heat shrink tubing and wire nuts
| Relay Module Pin | Arduino Uno R3 Pin | Wire Color (Recommended) | Function |
|---|---|---|---|
| VCC | 5V | Red | Powers the relay coil and optocoupler LED |
| GND | GND | Black | Common ground reference |
| IN | Digital Pin 8 | Yellow | Logic trigger signal (Active LOW on most modules) |
Step-by-Step Mains Wiring Procedure
WARNING: You are working with 120V AC mains voltage. Lethal shock hazard exists. Always de-energize the circuit, unplug the device from the wall, and verify dead with a tested multimeter before touching any bare wire. Local electrical codes may require a licensed electrician for permanent in-wall wiring; this guide is for bench-testing and temporary cord-and-plug setups only.
- De-energize and Prep: Unplug the lamp cord from the wall. Cut the Hot (usually black or the narrower prong side) wire in half. Leave the Neutral (white) and Ground (green/bare) wires completely intact and uninterrupted.
- Strip and Terminate: Strip 1/4 inch of insulation from the two cut ends of the Hot wire. Crimp spade connectors onto these ends to prevent stray strands from shorting against the relay module PCB.
- Connect to Screw Terminals: Insert one spade connector into the COM (Common) terminal and tighten the screw. Insert the second spade connector into the NO (Normally Open) terminal. Never use the NC (Normally Closed) terminal for safety-critical loads; if the Arduino loses power, an NC wiring scheme will turn the load ON.
- Verify Continuity: Set your multimeter to continuity mode. Place probes on COM and NO. It should read open (OL). Briefly jumper the IN pin to GND on the module; you should hear a click and the meter should beep (read < 1 ohm).
- Insulate: Ensure no bare copper is exposed outside the screw terminals. Wrap the terminal block in electrical tape or use a 3D-printed enclosure to prevent accidental contact.
Complete Arduino Code with Error Handling
The most common point of failure in Arduino relay projects is the boot sequence. When the Uno R3 powers on or resets, GPIO pins float and may briefly go HIGH, triggering the relay and turning on your 120V load unexpectedly. The code below mitigates this by initializing the pin state before setting it to an output, and uses non-blocking millis() timing to prevent watchdog or serial buffer issues.
/*
* Arduino Relay Safe Switching Code
* Target Board: Arduino Uno R3 / Nano v3
* Module: 5V Optocoupler Relay (Active LOW)
*/
// Pin Definitions
#define RELAY_PIN 8
#define LED_PIN 13 // Onboard LED for visual confirmation
// Relay Logic Configuration
// Most blue modules are Active LOW (LOW = Energized, HIGH = De-energized)
#define RELAY_ON LOW
#define RELAY_OFF HIGH
// Timing Variables (unsigned long prevents rollover errors at 49 days)
unsigned long previousMillis = 0;
const long interval = 5000; // Toggle every 5 seconds
bool relayState = false;
void setup() {
Serial.begin(9600);
// CRITICAL SAFETY STEP: Set the output state BEFORE setting pinMode.
// This prevents the pin from floating or defaulting HIGH during the
// microsecond it takes to execute the next line.
digitalWrite(RELAY_PIN, RELAY_OFF);
pinMode(RELAY_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.println("System Initialized. Relay is safely OFF.");
}
void loop() {
unsigned long currentMillis = millis();
// Non-blocking timer check
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Toggle state
relayState = !relayState;
// Apply state to pins
if (relayState) {
digitalWrite(RELAY_PIN, RELAY_ON);
digitalWrite(LED_PIN, HIGH);
Serial.println("RELAY ENGAGED");
} else {
digitalWrite(RELAY_PIN, RELAY_OFF);
digitalWrite(LED_PIN, LOW);
Serial.println("RELAY DISENGAGED");
}
// Error Handling / Verification: Read back the pin to ensure hardware matches software
int actualPinState = digitalRead(RELAY_PIN);
int expectedState = relayState ? RELAY_ON : RELAY_OFF;
if (actualPinState != expectedState) {
Serial.println("ERROR: GPIO state mismatch! Check for short circuit on Pin 8.");
// Failsafe: Force relay off if hardware is misbehaving
digitalWrite(RELAY_PIN, RELAY_OFF);
relayState = false;
}
}
}
For more details on the ATmega328P GPIO behavior during boot, consult the official Arduino Uno R3 documentation.
Debugging: Relay Clicks but Load Won't Turn On
You upload the code, you hear the mechanical "click" of the Songle relay, the red LED on the module illuminates, but your 120V lamp stays dark. Here are the first three things to check, ranked by likelihood.
1. COM vs NC/NO Wiring Error (80% of cases)
The screw terminals are often mislabeled on cheap clone modules, or the builder mistakenly wired the Neutral wire through the relay instead of the Hot wire. The Fix: Unplug the mains cord. Set your multimeter to continuity. Place probes on the two wires entering the relay. With the Arduino powered and the relay energized (click heard), you should read < 1 ohm. If it reads OL (Open Line), you have wired into the NC terminal or the neutral line.
2. Active LOW vs Active HIGH Logic Mismatch (15% of cases)
Some relay modules (especially green or red ones, or solid-state relays) are Active HIGH. If your module is Active HIGH, sending a LOW signal will energize the optocoupler LED (lighting the module's indicator), but the internal transistor won't pull the relay coil low enough to engage the contactor.
The Fix: Swap #define RELAY_ON LOW to HIGH and RELAY_OFF to LOW in the code. If the module LED turns off but the relay clicks and the lamp turns on, you had a logic inversion issue.
3. Pitted Contacts / Voltage Drop Under Load (5% of cases)
If the relay previously switched an inductive load (like a vacuum or a large fan) without a snubber diode, the AC arcing may have pitted the internal copper contacts. They will pass continuity on a multimeter (which uses milliamps), but will fail to pass the amps required by the lamp. The Fix: With the circuit energized and the lamp plugged in (careful: live voltage), measure the AC voltage directly across the COM and NO screw terminals. You should read < 2V AC. If you read 40V, 80V, or full line voltage across the terminals while the relay is clicked, the internal contacts are destroyed. Discard the module.
Extending and Simplifying the Build
Once you have a single relay working, you will inevitably want to scale the project. Here is how to extend the build for more channels, or simplify it if you realize a relay is the wrong tool for the job.
How to Extend: Adding More Relays
If you need to control 8 or 16 relays, do not wire them directly to the Arduino's GPIO pins. The ATmega328P can only source/sink about 20mA per pin and 200mA total across the VCC/GND rails. The Solution: Use a 74HC595 Shift Register. This allows you to control 8 relays using only 3 Arduino pins (Data, Clock, Latch). Daisy-chain multiple 74HC595 chips to control 16, 24, or 32 relays while keeping the wiring clean and the current draw within the Arduino's limits.
How to Simplify: Relay vs. Logic-Level MOSFET
Relays are mechanical, loud, slow, and wear out. If you are switching a DC load under 5A (like a 12V LED strip or a small water pump), ditch the relay entirely and use a logic-level MOSFET like the IRLZ44N. It switches silently, handles PWM for dimming, and lasts indefinitely. However, MOSFETs cannot switch AC mains voltage safely without complex triac circuitry.
| Feature | Electromagnetic Relay (SRD-05VDC) | Logic-Level MOSFET (IRLZ44N) |
|---|---|---|
| Load Type | AC or DC (Galvanic Isolation) | DC Only (Common Ground Required) |
| Switching Speed | Slow (~10ms), no PWM | Nanoseconds, excellent for high-freq PWM |
| Lifespan | ~100,000 mechanical cycles | Solid-state, effectively infinite |
| Noise | Audible mechanical click | Silent |
| Flyback Protection | Required across coil, and snubber across contacts for AC | Required across inductive DC loads (reverse-biased diode) |
For an excellent deep dive into why flyback and snubber diodes are mandatory when dealing with relay coils and inductive loads, review the application notes on All About Circuits' relay tutorial. Understanding the physics of the collapsing magnetic field will save your optocouplers from catastrophic voltage spikes.






