Difficulty: Intermediate | Time: 45 Minutes | Cost: ~$18 USD

The ubiquitous blue "Arduino relay module" found in every beginner kit is almost always built around the Songle SRD-05VDC-SL-C electromechanical relay. While it is the cheapest way to switch mains voltage or high-current DC loads, it is also the number one cause of microcontroller brownouts, silent resets, and fried GPIO pins on the bench. The direct answer to "how do I power this?" is: never power more than one relay channel directly from the Arduino Uno's onboard 5V pin. A single relay coil draws roughly 70mA; four channels draw 280mA, which will sag the Uno's linear regulator and trigger a reset.

This guide covers the exact hardware specifications, the critical JD-VCC jumper modification for true optical isolation, non-blocking control code, and the specific debugging paths for when the hardware inevitably misbehaves.

Spec Sheet & Pin Mapping

Before wiring anything, you need to know the exact electrical boundaries of the module. The data below is pulled directly from the Songle SRD-05VDC-SL-C datasheet and standard module schematic measurements. For a deeper look at the internal schematic, refer to the Components101 Relay Module Breakdown.

Table 1: SRD-05VDC-SL-C Module Specifications
Parameter Value / Rating Bench Notes & Edge Cases
Coil Voltage (Nominal) 5.0V DC Will reliably pull in at 3.75V, but optocoupler LED needs ~1.2V forward voltage.
Coil Resistance ~70 Ω Results in ~71mA steady-state current per channel.
Contact Rating (AC) 10A @ 250VAC Derate to 5A for inductive loads (motors, transformers) without a snubber.
Contact Rating (DC) 10A @ 30VDC DC arcs are persistent. Do not switch >30VDC without an arc-suppression circuit.
Optocoupler Isolation ~2500V RMS Only valid if the JD-VCC jumper is removed and separate supplies are used.
Flyback Diode 1N4148 (SMD) Protects the switching transistor, but does not protect the external power supply rails.

The following pin mapping assumes you are using an Arduino Uno R3 and a 4-channel module. We are using digital pins 8-11 to avoid conflicts with the hardware SPI and I2C pins (10, 11, 12, 13 on Uno) in case you add sensors later.

Table 2: Arduino Uno R3 to 4-Channel Relay Module Pinout
Module Pin Arduino / Power Connection Wire Color (Recommended)
JD-VCC External 5V Power Supply (+) Red
VCC Arduino Uno 5V Pin Orange
GND External 5V GND AND Arduino GND Black (use a common ground bus)
IN1 Digital Pin 8 Yellow
IN2 Digital Pin 9 Yellow
IN3 Digital Pin 10 Yellow
IN4 Digital Pin 11 Yellow

Parts List & Wiring Steps

Pro-Tip: The JD-VCC Jumper
Most modules ship with a jumper cap connecting JD-VCC and VCC. Remove this jumper. Leaving it in place defeats the optocoupler isolation, feeding relay coil noise and back-EMF directly into your microcontroller's 5V rail. This is the root cause of 90% of "my Arduino keeps resetting" complaints.

Required Materials:

  • 1x Arduino Uno R3 (or compatible ATmega328P board)
  • 1x 4-Channel 5V Relay Module (Songle SRD-05VDC-SL-C based)
  • 1x External 5V Power Supply (e.g., Mean Well RS-15-5 5V 3A enclosed supply)
  • 1x 120V AC Load (e.g., standard desk lamp with a cut cord for testing)
  • Jumper wires (22 AWG solid core for breadboard, 18 AWG stranded for mains connections)

Wiring Procedure:

  1. De-energize and Verify: Ensure the external 5V supply is unplugged and the Arduino is disconnected from USB. If wiring a mains AC load, ensure the mains breaker is OFF and verify dead with a non-contact voltage tester.
  2. Prepare the Module: Use tweezers to pull the jumper cap off the JD-VCC and VCC pins on the relay module. Set it aside.
  3. Wire the Coil Power: Connect the external 5V supply's positive terminal to the module's JD-VCC pin. Connect the external supply's negative (GND) terminal to the module's GND pin.
  4. Wire the Logic: Connect the Arduino's 5V pin to the module's VCC pin. This powers the optocoupler LEDs.
  5. Establish Common Ground: Connect the Arduino's GND pin to the module's GND pin. Note: The external 5V GND and Arduino GND must be tied together for the optocoupler circuit to complete.
  6. Wire the Control Pins: Connect IN1 through IN4 to Arduino digital pins 8, 9, 10, and 11 respectively.
  7. Wire the Load (Mains): Cut the hot (black/brown) wire of your AC lamp. Connect the incoming hot wire to the relay's COM (Common) terminal. Connect the outgoing hot wire to the NO (Normally Open) terminal. Leave the neutral wire uninterrupted and wire it directly to the lamp.

Complete Control Code (Arduino Uno R3)

This code targets the Arduino Uno R3 (ATmega328P). It uses a non-blocking millis() timer to toggle the relays, avoiding the delay() function which blocks sensor reading. It also includes a GPIO readback verification step to catch hardware shorts or dead pins.


// Pin Definitions
#define RELAY_1 8
#define RELAY_2 9
#define RELAY_3 10
#define RELAY_4 11

// Timing and State
unsigned long previousMillis = 0;
const long interval = 5000; // Toggle every 5 seconds
bool relayState = false;

const int relayPins[] = {RELAY_1, RELAY_2, RELAY_3, RELAY_4};
const int numRelays = 4;

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; } // Wait for serial port (native USB boards)
  
  Serial.println(F("[BOOT] Initializing Relay Control..."));
  
  // Initialize pins as outputs and set to HIGH (Relays are Active LOW)
  for (int i = 0; i < numRelays; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], HIGH); // HIGH = Relay OFF
  }
  
  Serial.println(F("[BOOT] All relays set to OFF (Safe State)."));
}

void loop() {
  unsigned long currentMillis = millis();
  
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    relayState = !relayState; // Toggle state
    
    for (int i = 0; i < numRelays; i++) {
      // Write the state (Active LOW: LOW = ON, HIGH = OFF)
      int writeVal = relayState ? LOW : HIGH;
      digitalWrite(relayPins[i], writeVal);
      
      // Error Handling: Readback verification
      int readVal = digitalRead(relayPins[i]);
      if (readVal != writeVal) {
        Serial.print(F("[ERROR] GPIO Pin " ));
        Serial.print(relayPins[i]);
        Serial.println(F(" failed to set state! Check for short circuit."));
      }
    }
    
    Serial.print(F("[STATE] Relays toggled to: "));
    Serial.println(relayState ? F("ON") : F("OFF"));
  }
}

Debugging: First Three Things to Check When It Fails

When a relay circuit fails, it rarely fails quietly. Here is the diagnostic decision tree for the three most common bench failures.

1. Symptom: The Arduino Resets Silently When the Relay Clicks

Cause: Voltage sag on the 5V rail or back-EMF spike coupling into the reset pin. When the relay coil de-energizes, it generates a massive voltage spike. While the module's 1N4148 diode clamps most of it, long wires act as antennas, injecting noise into the ATmega328P's reset line.
Fix: Add a 100µF electrolytic capacitor across the external 5V supply terminals (JD-VCC and GND) to act as a bulk reservoir. Ensure your jumper wires between the Arduino and the module are under 6 inches long.

2. Symptom: Relay Clicks, but the AC Load Doesn't Turn On

Cause: Wiring the load to the NC (Normally Closed) terminal instead of NO (Normally Open), or a loose screw terminal biting into the wire insulation instead of the copper.
Fix: With the power OFF, use your multimeter in continuity mode. Probe COM and NO. It should read "OL" (Open Loop). Energize the relay manually by applying 5V to JD-VCC and grounding IN1. The meter should beep (read < 1 ohm). If it reads OL when energized, you have a dead relay contact or a wiring error.

3. Symptom: The Optocoupler LED is Dim and the Relay Chatters

Cause: Insufficient trigger current. The PC817 optocoupler on the module requires about 5mA to 10mA of forward current to switch the internal phototransistor. If your Arduino's 5V pin is sagging, or if you are using a 3.3V board (like an ESP8266) without a level shifter, the LED won't fully illuminate.
Fix: Verify the voltage at the module's VCC pin with a multimeter while the relay is trying to engage. If it's below 4.5V, your logic supply is inadequate.

Cross-Platform Error String: ESP32 Brownouts
If you port this exact hardware setup to an ESP32 DevKit v1 (a very common upgrade path), you will inevitably hit this exact error string in the Serial Monitor:
Brownout detector was triggered
Ranked Causes for this ESP32 Error:
1. JD-VCC Jumper Error: You left the jumper in place and are trying to power the 280mA relay coils from the ESP32's onboard AMS1117 3.3V regulator, which instantly overloads and sags.
2. Missing Bulk Capacitance: The external 5V supply lacks a decoupling capacitor, and the inrush current of the coil pulling in drops the ESP32's 5V VIN pin below the brownout threshold.
3. USB Cable Voltage Drop: You are powering the ESP32 via a cheap, thin USB cable that drops 0.7V over a 3-foot run, starving the board when the relay engages.

Extending and Simplifying the Build

Electromechanical relays are great for universal AC/DC switching, but they are the wrong tool for many modern embedded projects. Use the comparison matrix below to decide if you should stick with the SRD-05VDC module or pivot to a different switching topology.

Table 3: Switching Topology Comparison
Feature Electromechanical Relay (SRD-05VDC) Logic-Level MOSFET Module (IRLZ44N) Solid State Relay (SSR-25DA)
Best For 120V/240V AC Mains, Universal Loads 12V/24V DC Motors, LED Strips, Heaters High-frequency AC switching, Silent operation
Switching Speed Slow (~10ms), bounces on make/break Extremely Fast (nanoseconds), PWM capable Fast (zero-crossing or random fire)
Control Current ~70mA (Requires external 5V supply) < 1mA (Can drive directly from GPIO) ~15mA (Can drive from GPIO)
Failure Mode Contacts pit/weld over time (mechanical wear) Thermal runaway if under-sinked (heat) Short-circuit failure (fails ON)
Cost (per channel) ~$1.50 USD ~$2.00 USD ~$6.00 USD

How to Simplify

If you are only switching DC loads under 30V (like a 12V water pump or a 24V solenoid valve), ditch the relay module entirely. Buy a MOSFET driver module based on the IRLZ44N or STP16NF06L. They draw virtually zero current from your Arduino GPIO, support PWM for motor speed control, and don't suffer from contact arcing. For a reliable, pre-wired option, the Adafruit Perma-Proto board with a single TO-220 MOSFET and a flyback diode is a bench staple.

How to Extend

To make this build a true "smart" controller, add an ACS712-20A current sensor module in series with the AC load's hot wire. By reading the analog voltage from the ACS712, your Arduino can verify that the load actually turned on. If the relay clicks but the ACS712 reads 0A, you know the relay contacts are pitted open or the load's fuse has blown, allowing you to trigger a maintenance alert over MQTT or serial.

For further reading on safe mains switching practices and isolation requirements, consult the Arduino Official Relay Guide and always defer to your local electrical codes when wiring permanent AC loads.