I’ve always been fascinated with relays, they’re so absolute, so binary. Anyway, I’ve built a few projects using relays and thought I’d share what I learned to help make it easier for others to use relays in their projects. I’m not an expert, I’m just a coder who likes to play with hardware.

An Introduction to Relays

Relays are basically switches, switches that you control (turn on or off) by applying or removing a specific voltage to the relay device. Relays aren’t needed for most microcontroller-based projects as your microcontroller board (whether it’s an Arduino or a full computer system like a Raspberry Pi) will be able to power external devices directly from its I/O ports. Where you need relays is when you want to open/close an external circuit, or where your circuit needs to control higher voltages than your system can provide.

I used a relay in my microcontroller-controlled garage door opener because I needed my project to mimic pushing a physical button (the garage door button on the wall) which required switching capabilities, not the ability to send an output voltage from the board. I used a relay in my light timer project because the project required switching on and off household electric current (110 Volts AC), which my Raspberry Pi cannot do directly.

There are two common types of relays: mechanical relays and solid-state relays. Mechanical relays use an electromagnetic coil and a physical switch; when you apply a voltage, the switch activates. Solid-state relays deliver the same result, but don’t have the mechanical components; instead, they use electronic components to do the same job.
Later in this article, we’ll start talking about relay boards or modules. Relays, in general, work as I’ve described them above. When you’re working with commercially produced relay modules, they usually operate in two different modes depending on how you wire the connections to the module. The supported modes are Normally Open and Normally Closed.

In Figure 1, you see a depiction of a relay in Normally Open (NO) mode. In this configuration, when there’s no voltage applied to the control circuit (the relay at rest portion of the image), the switched circuit is disconnected and current can’t flow through the connection. When you apply an appropriate voltage to the control circuit, the electromagnetic coil in the relay activates and pulls the switch closed, enabling current to flow through the switched circuit.

Figure 1 – Normally Open relay operation

In Normally Closed (NC) mode the opposite is true (shown in Figure 2). When the relay is at rest (no voltage applied to the control circuit), the switched circuit is closed and current flows through the switched circuit. When you activate the relay by applying an appropriate voltage to the control circuit, the electromagnetic coil in the relay activates and pulls the switch open, stopping any current flowing through the switched circuit. I don’t know how exactly this works internal to the relay.

Figure 2 – Normally Closed relay operation

Relays are like other switches in that there are different configurations available. Two attributes drive switch configurations: Pole and Throw. The pole attribute describes how many individual circuits are controlled by the switch. A Single Pole (SP) switch controls a single circuit. A Double Pole (DP) switch controls two separate circuits; there are essentially two interconnected switches, with each connected to its own circuit; when you toggle the switch, both circuits are affected simultaneously.

The switch’s throw attribute describes the number of circuit paths provided by the switch. A Single Throw (ST) has only one circuit path. With the switch thrown one way, current flows through the circuit, with it thrown the other way, the circuit is broken and no current flows. A Double Throw (DT) switch offers two circuit paths. With the switch thrown one way, current flows through one of the circuit paths, with it thrown the other way, current flows through the other circuit path. A DT switch can also have a center Off position between the two circuit path options.

So, when you’re looking at relays, you’ll see them described as something like SPST, SPDT, DPST, DPDT, etc. which should make sense now after reading the previous paragraphs.

When working with relays, each relay model is different in several ways; the most important differences are in the voltage and current ratings for the relay. There are two sets of numbers you must pay very close attention to, otherwise you’ll damage your relay circuit and possibly let the smoke out of the relay or some other component. The first is the voltage and current ratings for the control circuit, and they’re normally given as ranges. These numbers tell you what voltage and associated current are required to activate the relay. The second set of important numbers tells you how much voltage and current the switching part of the relay can handle.

Let me show you an example; Figure 3 shows the product properties for a random relay from the DigiKey web site. The coil values highlighted in the figure describe how much current the relay consumes and the maximum voltage you can use with the relay. In this case, it’s a 3V relay, so you’ll need to make sure that your project can deliver 3 Volts to trigger the relay, otherwise it’s not going to work.

The second set of numbers highlighted in the figure tells you more about how to work with the relay. The Switching Voltage tells you how many volts you can switch with this relay. In this case, you can connect the switch circuit to circuit delivering up to 250 Volts Alternating Current (AC) or 220 Volts Direct Current (DC). The last two values specify that the relay will turn on when 2.24 Volts DC is applied to the relay. If the relay’s on, it will switch off when the applied voltage falls below 0.3 Volts DC.

Figure 3 – Relay attributes

With this brief introduction out of the way, let’s start talking about how to use relays in your projects.

Hard-wiring Relays

Relays come in several form factors. Basically, a relay will be a rectangular block with at least 4 electrical connectors exposed.

Two of the connectors are for the control circuit, and, wait for it…the remaining two connectors are for the switched circuit. Pretty easy, right? Not exactly. If you’re not an electrical engineer (like me, I’m nothing of the sort), you might think you can just wire the relay into your circuit and you’re all set. Unfortunately, as with most electronic components, nothing is ever that simple.

If you wire the relay into your circuit as I’ve described above, applying voltage, for example, from a Raspberry Pi or Arduino device (you could use any voltage source) across the control circuit should trigger the relay. However, apparently it won’t work reliably, there are latching considerations and other issues that may affect the relay’s operation. Because of this, you need to add some extra components to the circuit to make it work. I discovered this as I worked with my first relay and found a bunch of Stack Overflow posts suggesting different ways to do it. There’s a Make: magazine article about it with a circuit diagram.

Normally I’d figure this all out and write about it here for you, but there’s an easier way to add relays to your projects, actually several ways, which I’ll show you in the following sections. I’ll also show you how to trigger the relay from your project’s code in the following section as well.

Relay Modules

Instead of buying relays and wiring them up with transistors, diodes and resistors, many manufacturers produce relay module boards that include everything you need. You can see an example of one in Figure 4; you can buy these modules with anywhere from 1 to 8 or more relays attached. Figure 5 shows a generic 4-relay module.

Note: Most relay modules I’ve seen don’t include any documentation, so you’ll pretty much have to figure out your module on your own.

Relay Connections

The single relay module typically exposes 6 electrical connections; three connectors for the control circuit and three for the switching circuit. They may also include a few jumper blocks like the one I’ve shown here. In most simple relay circuits, you’ll usually use only five connections, I’ll explain why in a minute.

On the left side of the figure are the control inputs. As you can see from the figure, they’re labeled as follows:
• VCC
• IN1
• GND

In your circuits, you’ll connect an input voltage as required by the relay (for Arduino or Raspberry Pi projects, that’s usually 3 or 5 volts depending on the microcontroller) to the VCC input. It’s the relay that dictates what this voltage should be, not your microcontroller. Most modern Arduino devices provide 3V and the Raspberry Pi can provide 3V or 5V; be sure to pick a relay module that will work with these voltages. Most relay modules like this are designed to work with Arduino’s or Pi’s, so you should be OK. You’ll also connect the GND input to your microcontroller’s Ground connection.

Finally, connect the IN1 pin to one of the output pins on your microcontroller. The output voltage on this pin is what triggers the relay. Using an Analog output is preferred, but since the Raspberry Pi doesn’t provide analog outputs, you can use Digital output as well.

On the switched circuit side of the module, you’ll see the three switched connection points marked with the diagram shown below (the labels NO, Common, and NC are mine).

Figure 6 – Relay connections legend

The figure shows the switched connection configuration for the relay at rest. For this module, a switched connection is made between the first and second connectors or the second and third connectors. When you trigger the relay (by applying the appropriate voltage across the control circuit), the common connection switches to the other side. When you connect your circuit to the NO (normally open) and Common connectors, the circuit remains open until an appropriate voltage is applied to the IN1 connector on the Control circuit. The NO/Common connection closes when voltage is applied to IN1. When you connect your circuit to the NC (normally closed) and Common connectors, remains closed until an appropriate voltage is applied to the IN1 connector on the Control circuit. The NC/Common connection opens when voltage is applied to IN1.

For most circuits, you just need to switch one set of wires, so you’ll switch either the NC or NO connections. For some configurations, you’ll need two states for your circuit; in this case, you’ll use both the NO and NC connections for your circuit. By default, one connection will always be connected and they’ll switch when you apply voltage to IN1.

Figure 7 shows a relay module wired for action, notice the three control connections (on the right side of the figure) with the switching connections on the NO/Common connectors. The Yellow wires in the lower left of the figure are the for the switched connection.

Figure 7 – Relay module in use

For multi-relay modules, the hardware is pretty much the same, just repeated once for every relay on the board. You’ll still have to connect voltage and ground connections, but instead of the single In1 control input, you’ll have one for each relay. So, looking at Figure 5, you’ll see the VCC and GND pins in the lower-right corner of the figure, but also multiple inputs, IN1, IN2, IN3, and IN4 for this 4 relay board. You’ll connect each IN# to a separate output pin on your Arduino or Raspberry Pi device. The switched side of the module has the same NO/Common/NC connectors you saw in the single relay module, only there’s 4 sets of them here, one for each relay.

Triggering the Relay

Remember the jumpers I mentioned earlier? It’s possible that your relay module will have a few jumpers on it. If so, one of the jumpers will likely control whether the relay is triggered using a high voltage or a low voltage. The position of this jumper will dictate how you trigger the relay in your project’s code. Let me give you some examples.

On an Arduino device, with the relay’s IN1 connector wired to the A1 analog output, you can trigger the relay with a single line of code. If the relay module is configured to use a high voltage to trigger the relay, then you would use the following code to turn the relay on:

analogWrite(A1, 255);

This sets the analog output of pin A1 to its highest voltage (likely 3V for the Arduino). To turn it off, you simply turn off the output voltage using the following line of code:

analogWrite(A1, 0);

This sets A1’s output to zero.

If the relay module is configured to use a low voltage to trigger the relay, then you would simply flip the examples, using the following code to turn the relay on:

analogWrite(A1, 0);

and the following code to turn the relay off:

analogWrite(A1, 255);

The Raspberry Pi doesn’t expose Analog outputs, so you’ll have to trick it a little. The Pi does support digital output using PWM (pulse Width Modulation) which is basically an output voltage that repeats itself, well, repeatedly. The result is that it ‘looks’ like a consistent output voltage to the connected device. Using Python on the Pi, the code to toggle the relay every second looks like this:

from gpiozero import LED
 from time import sleep

# the relay is connected to GPIO pin 18 on the Raspberry Pi
 # replace the 18 below with whatever pin is appropriate for your
 # hardware setup
 relay = LED(18)

# the following is an infinite loop in Python, it runs until you
 # kill the application
 while True:
 # turn the relay on
 relay.on()
 # wait a second
 sleep(1)
 # turn the relay off
 relay.off()
 # wait another second
 sleep(1)

In this example, the code uses GPIO Zero, a very capable library for the Pi that enables you to easily control most anything connected to the Pi’s GPIO ports. Here, I’m using the module’s LED library to mimic the voltage output I need for my application. In this case, the relay is connected to the Pi’s GPIO 18 pin. GPIO Zero includes other output types you could use for this as well.

There you have it, a quick and easy way to connect a relay to your IoT projects. But wait, there are even easier options for you to use for your projects, check them out in the next section.

Microcontroller Add-On Boards (Shields, HATs, etc.)

To make it even easier for you to add relays to your microcontroller projects, several manufacturers produce add-on boards for popular microcontroller platforms. These boards stack directly onto the microcontroller using the GPIO port (Raspberry Pi) or the header pins most other boards support. It seems like there’s relay modules for any kind of microcontroller or Single Board Computer (SBC) you can think of.

Adafruit Feather

For one of my projects, I used the Adafruit Feather microcontroller; the feather is an Arduino compatible suite of microcontroller boards that all share a consistent form factor and input/output pin layout. For this particular project, I used the Adafruit Feather M0 WiFi, an Arduino compatible Wi-Fi enabled microcontroller, the Adalogger FeatherWing, a real-time clock add-on board for the Feather, and the Adafruit Power Relay FeatherWing. The Relay FeatherWing gave my project an easy to use relay module I could just slap onto the microcontroller and get to work. You can see the three boards, with their header pins and sockets soldered on, in the following figure.

Figure 8 – Adafruit Feather board and accessories

To use them, you stack the boards on top of each other as shown in the following figure. You’ll connect your switched circuit to the blue terminals on the right side of the figure. As with the other relays, you’ll use two for either the NC or NO connection, or all three if you want to switch the relay two ways as described in an earlier section.

Figure 9 – FeatherWing module stack, including relay module on top

The relay module is wired to multiple output ports on the Feather Board, but to use it, you cut through the metal pad on the back of the board for the output pin you want to use (based on which other pins are being used by other Feather add-on boards).

Figure 10 – Adafruit Feather power relay port selection options

To trigger the relay in your Feather application, you would use something like the following:

//The Analog pin the relay is connected to
 const int outputPin = SELECTED_FEATHER_PIN;
 //For example, if the relay is connected to Analog output A1, you would
 //use the following:
 //const int outputPin = A1;

void setRelay(bool status) {
 //Set the relay to a specific status (on=true/off=false)
 Serial.print("Relay: ");
 if (status) {
 Serial.println("ON");
 analogWrite(outputPin, MAXOUTPUT);
 } else {
 Serial.println("OFF");
 analogWrite(outputPin, MINOUTPUT);
 }
 //Store the status we set, so that toggleRelay will be able
 //to accurately toggle the relay later
 relayStatus = status;
 }

In this example, what I’m showing is a constant definition (describing which analog output pin the relay is connected to) and a function called setRelay that triggers the relay.

The constant outputPin merely gives you an easy way to configure the code for your particular hardware configuration. Instead of making you hunt around for all the parts of the code that trigger the relay, we set the relay output pin in this constant and any part of the application that wants to use it can merely reference the constant. With this approach, if you later change the relay pin, you must only change it in one place, and, once the change is made, all the different parts of the code that reference the constant will be automatically updated.

The setRelay function gives the application a quick and easy way to turn the relay on or off. Instead of making a separate function to turn it on and another to turn it off, I simply used one function and pass whether I want the relay on or off as a Boolean variable passed to the function. Let me show you.

To turn the relay on, any part of the application can simply execute the following code:

setRelay(true);

In this example, the true parameter passed to the function is a Boolean True value that indicates On.

To turn the relay off, you would execute the following code:

setRelay(false);

The function uses a variable called relayStatus to track whether the relay is on or off, enabling a separate function called toggleRelay to toggle the status of the relay (turning the relay on it its off or off if its on). That code is particularly simple, all it does is call setRelay using the opposite of the relay’s current status:

void toggleRelay() {
 //Flips the relay from on to off or off to on
 setRelay(!relayStatus);
 }

The !relayStatus in the code translates to NOT relayStatus, so if relayStatus is true, then false is passed to setRelay. If relayStatus is false, then true is passed to setRelay.

Tessel 2

The Tessel 2 has a relay module, shown in Figure 11. I used it to make a simple garage door controller using a simple web app hosted on the controller; you can find the complete project on Github.

Figure 11 – Tessel 2 board and relay module

The Tessel board runs JavaScript, so it’s easy to write a JavaScript-based server task running on the board and use a desktop or mobile web browser to interact with the board. For this project, the web server hosts a simple web page that contains a button to open the garage door. On the board, the code that triggers the garage door is the toggleRelay function listed below:

function toggleRelay(RELAY_PORT) {
 //Toggle the specified relay, keeping it on for RELAY_DELAY milliseconds
 //first turn on the activity LED
 tessel.led[ACTIVITY_LED].on();
 //next, the relay on
 relay.turnOn(RELAY_PORT, relayResult);
 //sleep for 500 milliseconds (half a second)
 sleep(500).then(() => {
 //Then turn the relay off
 relay.turnOff(RELAY_PORT, relayResult);
 //and turn off the activity LED
 tessel.led[ACTIVITY_LED].off();
 });
 }

As you can see from Figure 11, the relay module sports two relays, so when you call toggleRelay, you must tell it which relay is wired to the garage door button by passing a 1 or 2 to the function through the RELAY_PORT variable. The function turns on an indicator light, triggers the relay, waits a half a second, then turns the relay and the LED indicator off.

Particle Photon

One company that makes relay modules for a variety of microcontrollers or SBC is National Control Devices. The garage door controller I actually use was built using the Particle Photon and a single relay board for the Photon. You can read about the complete project at Github.

For this board, shown in Figure 12, the Photon mounts in a socket on the right side of the board (as shown in the figure). When you apply power to the relay board, it also powers the microcontroller.

Figure 12 – ControlEverything 1-Channel Relay Controller for the Particle Photon

The Photon ‘platform’ is cool in that you can execute code on the board remotely, through a free cloud service. The board is mostly compatible with the Arduino microcontroller, so you code your application using C.

The code to trigger the relay should look similar to what I’ve shown already, in the Photon example code shown below, I define some constants to tell the application which pin the relay is connected to and which pin an indicator light is connected to (its built in to the Photon). The application calls the pushButton function to trigger the relay; the function turns on an indicator light, triggers the relay, waits a half a second, then turns the relay and the LED indicator off.

// Connect the relay to Digital 0
 int relayPin = D0;
 // Connect the activity LED to Digital 1
 int activityLED = D1;

//=================================================================
 // This function pushes the garage door button (through the relay,
 // of course)
 //=================================================================
 int pushButton(String param){
 Serial.println("pushButton function called.");
 //Turn the activity LED on, so we can tell it's working
 digitalWrite(activityLED, HIGH);
 //Turn the relay on
 digitalWrite(relayPin, HIGH);
 //Wait half a second (or however long we determine we need to)
 delay(500);
 //Turn the relay off
 digitalWrite(relayPin, LOW);
 //Turn the activity LED off
 digitalWrite(activityLED, LOW);
 //we must return something, so return a zero (-1 means failure)
 return 0;
 }

Raspberry Pi

I’ve even found a couple of relay modules for the Raspberry Pi. The first one I worked with is the Seeed Studio Raspberry Pi Relay Board v1.0. Try out these tips for how to use the board in your projects too. The board sports 4 relays and mounts directly on top of the Raspberry Pi as shown in Figure 13.

Figure 13 – Seeed Studio Raspberry Pi Relay Board v1.0

Using the board in your projects is easy. The folks at Seeed Studio created a sample Python application that enables you to interact with the board (turning relays on an off by typing commands in a terminal window), I added some functionality to the code and published it as a Python module at https://github.com/johnwargo/Seeed-Studio-Relay-Board. To use the module, copy the library to your project folder then add the following line to the start of your Python application:

from relay_lib_seeed import *

With that in place, you can turn the relay on using the following code:

relay_on(int_value)

where int_value refers to the relay number (1 through 4). So, to turn relay #2 on, use the following:

relay_on(2)

To turn a relay off, use:

relay_off(int_value)

You can also toggle a relay using:

relay_toggle_port(int_value)

Pretty simple, right? If you want a simple app you can use to play around with the board, check out my project on Github.

Another relay board option is the ModMyPi PiOT Relay Board; you can find documentation on Github. Like the Seeed Studio board, the PiOT board mounts on top of the Raspberry Pi, but with this module, you can stack multiple boards on top of each other to deliver 8, 12, or more relays for your project. You can see an example of the board shown in Figure 14.

Figure 14 – ModMyPi PiOT board

A cool feature of the PiOT board is that you can toggle the relays using the push buttons mounted on the board, one for each relay. This enables you to see how the board works and even test out your project’s hardware before you’ve written any code. You’ll also use these buttons to configure the Raspberry Pi GPIO pins used by the board, something that I would honestly prefer to do via jumpers or DIP switches instead.

The board is designed for both the full-size Raspberry Pi models as well as the Pi Zero. Unfortunately, the mounting holes on the board are only suitable for mounting on the Pi Zero. For Pi Zero mounting, the board offers 4 mounting holes, so with the right standoffs and screws, you can mount the PiOT board solidly on top of the Pi Zero. For larger Pi models, for some bizarre reason the ModMyPi folks only expose two mounting holes that align with the Pi, so you can mount it, but I found that for my implementation it was unstable and shorted the relay connections whenever the board moves (which it does easily since its not mounted firmly).

To help you use the board in your projects, I created the Python library at https://github.com/johnwargo/pi-relay-controller-modmypi/blob/master/relay_lib_modmypi.py. To use the library, copy the library to your project folder then add the following line of code to your Python project:

from relay_lib_modmypi import *

Next, you’ll have to configure the application for your board configuration. In your application’s initialization code, add the following lines:

# Update the following list/tuple with the port numbers assigned to your relay board
 PORTS = (7, 8, 10, 11)
 NUM_RELAY_PORTS = 4

# initialize the relay library with the system's port configuration
 if init_relay(PORTS):
 # turn all the relays off, so we're starting with a clean slate.
 relay_all_off()
 else:
 print("Port configuration error")
 # exit the application
 sys.exit(0)

In the PORTS variable, you’ll need to populate the list with the relay port numbers you configured using the board’s buttons. Set the NUM_RELAY_PORTS variable to 4, 8, 12, etc. depending on how many boards you have stacked together. With that in place, you can turn the relay on using the following code:

relay_on(int_value)

where int_value refers to the relay number (1 through 4). So, to turn relay #2 on, use the following:

relay_on(2)

To turn a relay off, use:

relay_off(int_value)

You can also toggle a relay using:

relay_toggle_port(int_value)

Pretty simple, right? If you want a simple app you can use to play around with the board, check out my project.

PowerSwitch Tail

For my garage door opener projects, I was merely using a relay to ‘push’ a button, so the relay merely switched a low voltage circuit. For some projects, you’ll want to use a microcontroller to switch higher voltages, like the 110V (North America) or 220V (pretty much everywhere else) running your house lighting or other commercial appliances. You can switch those voltage levels with the solutions I’ve shown so far as many relays support switching a wide range of voltages (for example, the relays shown in Figures 5 and 6 will switch up to 250V AC or 30V DC), but you’re dealing with higher voltages which can be deadly to work with and dramatically change the wiring solution you’ll use in your project.

For high voltage switching scenarios, there’s a simple solution you can use that isolates you from many of the safety issues that come with higher voltages. The solution is called a PowerSwitch Tail, and an example project I created using one is shown in Figure 15. The PowerSwitch Tail (PT) is the black box with the power cord running through it.

Figure 15 – PowerSwitch Tail project

The PT is basically a box containing a relay with its switched connection wired across one of the conductors in an AC power plug. When you apply a specific voltage (normally between 3V and 5V) to the input connections on the PT (shown with two red wires connected to it in the figure) the relay triggers and AC current passes through the power cord. The PT is normally wired for NO operation, but you can usually configure it for NC operation as well.

For this particular project, I used a Adafruit Feather with a real-time clock (RTC) module to drive the PT relay, enabling me to switch control to a light fixture using logic coded in the Feather application. You can find the complete source code for the project here.

From a coding standpoint, you’ve already seen the code you need to control the relay, it’s in the Adafruit Feather section shown earlier in the document.

Validating Relay Operation

As I worked with many of these relay-based projects, I found myself regularly wiring up a simple LED circuit so I could quickly and easily see whether my project code worked correctly. Most relays make an audible click when triggered, and most relay modules have a LED wired into each relay circuit so you can tell at a glance whether the relay is on or off. However, it’s not always easy to hear the click or see the indicator light clearly. Also, with 4-relay modules, the module’s indicator LEDs are sometimes grouped together, so it’s hard to tell which LED is for which relay.

I do a lot of woodworking in my shop, and as I gained experience, I quickly learned that successful makers use jigs to help them repeat tasks consistently or even perform singular, but complicated, tasks accurately. For my relay work, I created a testing jig I could wire into each of my projects as I worked on them and more easily determine the state of my project’s relays. The jig is basically a series of LEDs connected to a power source (3V DC served by two AA batteries) with each LED exposed through two open leads. When I need to test a relay circuit, I wire a LED’s leads to the NC connection on one of the relays (repeating as necessary depending on how many relays I’m using), put a couple of batteries in the battery holder and start testing my code. When the relay triggers, the LED lights or goes dark depending on the status of the relay.

The following figure shows the wiring diagram for the jig.

Figure 16 – Relay testing jig circuit

For my implementation of this, I used the Adafruit Perma-Proto Half-sized Breadboard as it was just the right size and allowed me to easily assemble the circuit. The coils of black and red wires shown connected to the lower-right corner of the jig are there in case I need to use that 3V power supply (the two AA batteries) for some other aspect of the project.

Conclusion

Hopefully I’ve given you enough of an overview of relays and their practical application (using relay modules, add-on boards, and, of course, code) that you’ll be able to successfully add them to your projects. When working with relays, be sure that your relay is rated for both the voltage and current used in your project; you wouldn’t want to let the smoke out of a relay out of carelessness. Speaking of carelessness, when working with AC circuits or high-voltage DC circuits, be extra careful as a mistake can be deadly, or at least painful.