Built-in project · Arduino Uno R3

Relay board on an Arduino Uno

A four-channel relay board chasing four lamps from pins 2 to 5. Active low, so LOW is on, and the pins are written HIGH before they become outputs. The whole build, an Arduino Uno and 9 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 15 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $36. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Why a pin cannot switch a load directly, but a relay can
  • Active low inputs: LOW is on
  • Writing a pin HIGH before making it an output
  • COM, NO and NC contacts on a relay
  • Hiding hardware details inside a small helper function
  • Difficulty: Intermediate
  • Time: About 15 minutes
  • Board: Arduino Uno R3
  • Parts: 13

How it works

The four-channel relay board has one input pin per channel, IN1 to IN4, wired to Arduino pins 2 to 5. Each relay connects supply to one lamp through a 220 ohm resistor and a yellow LED. When a relay clicks on, its lamp lights.

This board is active low. A channel turns on when its pin goes LOW and off when it goes HIGH. The sketch hides that behind relayOn, so the rest of the code can say true for on.

The sketch chases the lamps. Each one lights for 250 ms in order, then a pause of 600 ms follows. The sketch also toggles pins 6, 7 and 8 for a motor demo, which this circuit leaves unwired.

Parts list

13 parts, plus the jumper wires. They retail for about $36; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Relay board, four channels pin IN4Arduino Uno R3 pin 5
Relay board, four channels pin IN3Arduino Uno R3 pin 4
Relay board, four channels pin IN2Arduino Uno R3 pin 3
Relay board, four channels pin IN1Arduino Uno R3 pin 2
LED, yellow (1) pin CArduino Uno R3 pin GND
LED, yellow (2) pin CArduino Uno R3 pin GND
LED, yellow (3) pin CArduino Uno R3 pin GND
LED, yellow (4) pin CArduino Uno R3 pin GND
Relay board, four channels pin GNDGround
Relay board, four channels pin VCCSupply
Resistor, 220 Ω (4) pin 1Relay board, four channels pin NO1
Relay board, four channels pin COM1Supply
Relay board, four channels pin COM2Supply
Relay board, four channels pin COM3Supply
Relay board, four channels pin COM4Supply
Resistor, 220 Ω (3) pin 1Relay board, four channels pin NO2
Resistor, 220 Ω (2) pin 1Relay board, four channels pin NO3
Resistor, 220 Ω (1) pin 1Relay board, four channels pin NO4
LED, yellow (1) pin AResistor, 220 Ω (1) pin 2
LED, yellow (2) pin AResistor, 220 Ω (2) pin 2
LED, yellow (3) pin AResistor, 220 Ω (3) pin 2
LED, yellow (4) pin AResistor, 220 Ω (4) pin 2

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Relay board: three ways to switch things a pin cannot.
//
//   pins 2 to 5  IN1 to IN4 of the four-channel board: four lamps
//   pins 6, 7    IN1 and IN2 of the two-channel board: motor A both ways
//   pin 8        the DPDT relay's transistor, through 1 k: motor B both ways
//
// Two circuits run this sketch: "Relay board" wires the lamps, and "Relays
// reverse a motor" wires the two motors. Whatever a circuit leaves unwired
// is simply a pin toggling with nothing on it.
//
// # Active low
//
// The relay boards are active low: an optocoupler's LED sits between VCC and
// each IN pin, so a channel is ON when its pin is LOW. relayOn() hides that,
// and setup() writes every pin HIGH *before* making it an output, because the
// other order leaves each pin low for an instant and every relay clicks on at
// power-up.
//
// # Two relays make an H bridge
//
// Motor A sits between the two channels' COMs. Each NC is on ground and each
// NO on 5 V. Both released: both ends on ground, which is a brake. Channel 1
// in: that end goes to 5 V and the motor turns. Channel 2 in instead: the
// other way. Both in: both ends on 5 V, a brake again, and never a short,
// because each COM is only ever on one contact.
//
// # One coil, two poles
//
// The DPDT relay does the same with one coil, because its two poles move
// together: the motor between the COMs, the supply crossed over between the
// NOs and the NCs. It is a bare relay, so its 40 mA coil hangs off 5 V
// through a 2N2222, with a 1N4007 across it for the kick.
//
// Relays are slow: 10 ms to pull in, 5 ms to let go. Nothing here asks more of
// them than a few clicks a second.

const int LAMPS[] = {2, 3, 4, 5};
const int MOTOR_A[] = {6, 7};
const int DPDT = 8;

void relayOn(int pin, bool on) {
  digitalWrite(pin, on ? LOW : HIGH);
}

void setup() {
  for (int pin = 2; pin <= 7; pin++) {
    digitalWrite(pin, HIGH);   // off, before it is even an output
    pinMode(pin, OUTPUT);
  }
  pinMode(DPDT, OUTPUT);
  digitalWrite(DPDT, LOW);
  Serial.begin(115200);
  Serial.println("Mokxi Uno: relays three ways");
}

void chase() {
  for (int i = 0; i < 4; i++) {
    relayOn(LAMPS[i], true);
    delay(250);
    relayOn(LAMPS[i], false);
  }
}

void loop() {
  Serial.println("motor A forward, motor B forward");
  relayOn(MOTOR_A[0], true);
  digitalWrite(DPDT, LOW);
  chase();

  Serial.println("both motors braked");
  relayOn(MOTOR_A[0], false);
  delay(600);

  Serial.println("motor A reverse, motor B reverse");
  relayOn(MOTOR_A[1], true);
  digitalWrite(DPDT, HIGH);
  chase();

  relayOn(MOTOR_A[1], false);
  delay(600);
}

Code walkthrough

The key functions of the sketch, and what each one does.

relayOn sketch.ino

Takes a pin and true or false. It writes LOW to turn a channel on and HIGH to turn it off. Because the board is active low, this one line is the only place that fact lives. If you swap to an active high board, you change it here and nowhere else.

void relayOn(int pin, bool on) {
  digitalWrite(pin, on ? LOW : HIGH);
}

setup sketch.ino

For pins 2 to 7 it writes HIGH first and calls pinMode second. The other order would leave each pin LOW for an instant, and every relay would click on at power up. Writing HIGH first keeps them off from the start. Then it sets pin 8 as an output and starts the Serial Monitor.

void setup() {
  for (int pin = 2; pin <= 7; pin++) {
    digitalWrite(pin, HIGH);   // off, before it is even an output
    pinMode(pin, OUTPUT);
  }
  pinMode(DPDT, OUTPUT);
  digitalWrite(DPDT, LOW);
  Serial.begin(115200);
  Serial.println("Mokxi Uno: relays three ways");
}

chase sketch.ino

Loops through the four lamp pins in LAMPS. Each lamp is switched on, held for 250 ms, then switched off before the next one starts. Only one lamp is on at a time, so you see a light moving along the row.

void chase() {
  for (int i = 0; i < 4; i++) {
    relayOn(LAMPS[i], true);
    delay(250);
    relayOn(LAMPS[i], false);
  }
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • All lamps are on when the sketch starts, or the logic seems backwards This project
    The relay board is active low. LOW turns a channel on. Use relayOn instead of calling digitalWrite with HIGH to mean on.
  • A relay clicks but its lamp stays dark This project
    Check that the lamp wire goes from NO, not NC, through the resistor to the LED anode, and that the LED cathode reaches ground. COM needs the supply.
  • The lamps light in the wrong order This project
    IN1 to IN4 must go to pins 2 to 5 in that order, matching the LAMPS list.
  • The relay clicks on at startup, or does the opposite of what the code says. Relay board
    These boards are active low: LOW turns the relay on and HIGH turns it off. Set the pin HIGH before pinMode OUTPUT so the relay does not pulse on at boot.
  • The board resets or relays chatter when they switch. Relay board
    Power the relay coils from a separate 5 V supply that can handle all four (about 70 mA each), and join the grounds. Mains loads are dangerous, so use low voltage for learning.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The LED does not light, or it lights once and then dies. LED
    LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.