IoT hardware is great, but without software to bend it to your will, it’s not of much use. In Part 1, I showed you how to set up the IoT hardware for our home automation system. In Part 2, I’ll show you the software that I used to build the home automation system: how it works, how to set it up, build it, and how to run it to control the 433-MHz devices that you set up in Part 1.
When you’re finished with Part 2, you won’t have a complete, working home automation system yet, but you will definitely see it begin to take shape. In short, Part 2 is where the hardware devices from Part 1 meet the software that controls them.
Directories are like spare bedrooms: they are easily cluttered. To prevent this clutter as you work through the rest of this series, create a directory somewhere on your computer, and store all of the code for this tutorial in that directory.
For example, I’ll go to the home directory on my Mac, then create a directory called
HomeAutomation, immediately subordinate to the home directory. Then, before I work with the IoT software, I go to that directory, like this:
cd mkdir HomeAutomation cd HomeAutomation
HomeAutomation directory will be the root folder for all of the source code that I’ll show you in this tutorial. Unless I tell you otherwise, any unqualified directory references will be relative to the
What you will learn in Part 2
In Part 1, you set up your Raspberry Pi and all of your 433-MHz hardware. In Part 2 (this part), you will set up the software components that communicate with the 433-MHz hardware. The software components listed above form a software stack that looks like this:
Figure 1. The architecture of the local IoT solution
At the bottom of the software stack is the 433-Mhz hardware that communicates through the Pi’s General-Purpose Input/Output (GPIO) pins to the software that is running on the Pi. At the top of the software stack is the application code, which makes calls into the middle stack, which is made up of these three components (from the bottom up):
I’ll introduce the IoT application code in Part 3, so don’t worry about it for now.
For Part 2, I want to focus on the middle of the stack from , which is composed of the components listed above. I’ll describe each of these components in detail throughout the remainder of this tutorial series.
The purpose of is to show you the overall architecture of the home automation solution that you’ll be building so you can see how the different components fit together as I introduce them here in Part 2.
By the time you’re finished with this part of the tutorial, you will know all about WiringPi, how to build it, and how to run the gpio utility.
You’ll also learn about rc-switch, which 433Utils uses to talk with WiringPi, and how to run 433Utils to talk with the receiver module that you set up in Part 1 to capture encoded signals from 433-MHz remote controls.
Finally, you’ll learn how to control IoT devices that use the 433 MHz band by sending encoded signals — identical to those signals that you captured with the receiver — through the transmitter you set up in Part 1.
Set up WiringPi
WiringPi is a C-language open source library written by Gordon Henderson that is used to access the GPIO pins on the Raspberry Pi.
I’ll show you how to download the source code and build WiringPi on your Raspberry Pi.
WiringPi also includes a command-line utility called gpio that you can use to manipulate the signals to and from the pins on the Pi. I’ll show you how to use gpio later in the tutorial to make a simple LED circuit blink.
To set up WiringPi, you need to download it build it. In the video below, I’ll show you how to download and build both WiringPi and 433Utils.
After you watch the video, make sure to work through the sections that follow to download and build Wiring Pi on your Raspberry Pi.
Download WiringPi from GitHub
Open a Terminal on your Pi, go to the
~/HomeAutomation folder, and enter the following command:
git clone git://git.drogon.net/wiringPi
You should see output like this:
$ git clone git://git.drogon.net/wiringPi Cloning into 'WiringPi'... remote: Counting objects: 1151, done. remote: Total 1151 (delta 0), reused 0 (delta 0), pack‑reused 1151 Receiving objects: 100% (1151/1151), 674.92 KiB | 1.63 MiB/s, done. Resolving deltas: 100% (804/804), done.
Now you have the source code for WiringPi on your computer, and you’re ready to build it from source.
Go to the
HomeAutomation/wiringPi directory and run the build:
The build is super fast (it takes around 10 – 15 seconds on my Raspberry Pi 3). When it runs, there are a couple of things that happen that you should know about.
A symbolic link is created in
/usr/local/bin that links to the gpio program that was just built. Since
/usr/local/bin is ahead of
/usr/bin in the
PATH environment variable (in the Stretch installation on my Pi, anyway), this is the version of the gpio utility that will run if you type
gpio at the command line.
Should that matter? Most of the time, probably not. I just wanted you to be aware that WiringPi’s build was doing this.
Set up 433Utils
As you can see from , 433Utils is called by your application to interact with the 433-MHz IoT devices. 433Utils, in turn, calls a lower-level library called rc-switch.
rc-switch calls the WiringPi library, which then communicates with the device through the Pi’s GPIO pins.
WiringPi provides the low-level interface to the Pi, and thus the most control. However, this control comes at a price. The code is not very noob-friendly. rc-switch sits atop WiringPi and makes using it much easier. And, last but not least, 433Utils sits atop rc-switch and allows communication with your 433-MHz devices with just a few function calls.
The ease of use that you enjoy from 433Utils also comes at a price: you don’t have as much control. But this is okay because you need only a few features of WiringPi and using the libraries in this manner provides the simplest possible interface.
Download 433Utils from GitHub
Open a Terminal on your Pi, go to the ~/HomeAutomation folder, and enter the following command:
--recursive https://github.com/jstevenperry/433Utils. You should see output like this:
$ git clone ‑‑recursive https://github.com/jstevenperry/433Utils Cloning into '433Utils'... remote: Counting objects: 225, done. remote: Compressing objects: 100% (2/2), done. remote: Total 225 (delta 0), reused 1 (delta 0), pack‑reused 223 Receiving objects: 100% (225/225), 46.04 KiB | 799.00 KiB/s, done. Resolving deltas: 100% (98/98), done. Submodule 'rc‑switch' (https://github.com/sui77/rc‑switch.git) registered for path 'rc‑switch' Cloning into '/Users/sperry/home/development/projects/HomeAutomation/433Utils/rc‑switch'... remote: Counting objects: 663, done. remote: Total 663 (delta 0), reused 0 (delta 0), pack‑reused 663 Receiving objects: 100% (663/663), 160.83 KiB | 1.59 MiB/s, done. Resolving deltas: 100% (354/354), done. Submodule path 'rc‑switch': checked out 'a9da9c36820b02fc5613dfe2437e1187bcf5b402'
433Utils includes utilities for other single board computer systems like Arduino, in addition to the Raspberry Pi. In this tutorial, you will work with only the Raspberry Pi utilities, which are located in the
Now that you have the source code for 433Utils and rc-switch on your computer, you’re ready to build 433Utils from source.
Go to the
433Utils/RPi_utils directory and run the
make command. The output looks like this:
$ make g++ ‑DRPI ‑c ‑o ../rc‑switch/RCSwitch.o ../rc‑switch/RCSwitch.cpp g++ ‑DRPI ‑c ‑o send.o send.cpp g++ ‑DRPI ../rc‑switch/RCSwitch.o send.o ‑o send ‑lwiringPi g++ ‑DRPI ‑c ‑o codesend.o codesend.cpp g++ ‑DRPI ../rc‑switch/RCSwitch.o codesend.o ‑o codesend ‑lwiringPi g++ ‑DRPI ‑c ‑o RFSniffer.o RFSniffer.cpp g++ ‑DRPI ../rc‑switch/RCSwitch.o RFSniffer.o ‑o RFSniffer ‑lwiringPi
make utility runs the GNU C++ compiler (
g++) and builds three programs: send, codesend, and RFSniffer. You will use only the last two in this tutorial.
The build takes only a few seconds, and when it’s finished, you’re ready to run the RFSniffer program.
Check out the gpio utility
An entire tutorial series could be dedicated to the gpio utility. It does so many different things that I cannot come close to describing it in the limited space I have here. Instead, check out this page written by the author himself. Also, make sure to read the manpage (type
man gpio at the command line of your Pi).
In this tutorial, I just want to introduce you to the gpio utility and get you used to running it when you’re working with software that you’re writing for, and running on, the Pi. To do that, I’ll show you two options, which you supply as arguments to the
gpio program when you run it from the command line:
The first argument —
readall— tells gpio to read all of the GPIO pins and report their state. The output looks like this:
$ gpio readall +‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑‑+‑‑‑+‑‑‑Pi 3‑‑‑+‑‑‑+‑‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑‑+‑‑‑+‑‑‑‑++‑‑‑‑+‑‑‑+‑‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5v | | | | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 0 | IN | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | IN | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | +‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑‑+‑‑‑+‑‑‑‑++‑‑‑‑+‑‑‑+‑‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑‑+‑‑‑+‑‑‑Pi 3‑‑‑+‑‑‑+‑‑‑‑‑‑+‑‑‑‑‑‑‑‑‑+‑‑‑‑‑+‑‑‑‑‑+
There is a lot going on here, and I won’t be able to cover it all, so I’ll hit the high points. Notice the headings, starting in the upper left corner.
BCM corresponds to the pin number on the internal pin number on the Broadcomm BCM2837 SoC (system-on-a-chip). By the way, the BCM pin is also the pin as marked on the expansion board you set up in Part 1.
wPi refers to the WiringPi pin number and is the pin number that you’ll reference in all of the software that uses WiringPi for this project, and it also corresponds to the GPIO pin number.
Name is just a helpful description. For example, “5v” indicates that pin provides +5V output, “0V” is ground, and “GPIO.21” indicates that the pin is GPIO pin number 21.
Mode indicates whether the pin is currently set to receive input (IN) from outside the Pi or to send output (OUT) from the Pi to the outside.
V tells you whether the pin is High (1) or Low (0).
Physical refers to the actual physical pin that you see when you look at the Pi’s GPIO header pins. The physical numbering starts at 1 with the pin closest to the micro SD slot. Odd-numbered pins are on the same 20-pin header row (ditto for even-numbered pins). Pin 40 is near the USB ports and on the opposite header row as pin 1.
Got all that? If you’re new to the Raspberry Pi, it might take a little while to get comfortable with these concepts. In addition to Gordon’s great gpio reference, and the gpio manpage, check out this simple guide to Raspberry Pi 3’s pin layout or this Wikipedia article.
For now, just follow along with me, and I’ll walk you through it. I’ve got you covered, don’t worry!
Remember the LED circuit from the video in Part 1? I’m going to show you how to wire it to the Pi and use the gpio blink command to make the LED blink. below shows the breadboarded circuit that I’ll demonstrate.
Figure 2. LED circuit for gpio blink
If you feel confident in your breadboarding skills, feel free to follow along with me.
The only difference between this circuit and the one from the video in Part 1 is that the circuit is powered from BCM pin #25 instead of the positive rail.
I’m going to supply gpio with the
blink argument, which alternates between HI (1) and LO (0), which makes the LED turn on (1) and off (0).
blink also takes an argument, which is the GPIO pin number to blink on and off.
Open two Terminal windows on the Pi (or two separate SSH sessions). In one, enter this command:
gpio blink 6
This command tells gpio to blink wiringPi (wPi) pin 6 (BCM #25) on and off. The interval is around 1 second per cycle (1/2 second ON, 1/2 second OFF, and so forth), and it will repeat until I press
In the other Terminal window, run this command:
watch ‑n 0.5 'gpio readall'
This command will execute the
gpio readall command every 0.5 seconds and display the output, which will let you see the Mode switch to
OUT and the
V go from
1 and back again after you run the
gpio blink command.
If you have followed along and the LED is ON when you pressed
gpio toggle 6, and it will toggle wPi pin 6 from ON to OFF (and vice versa).
How cool is that? Trust me, gpio is a very handy utility!
To stop it, I’ll type
Ctrl+c in the window where the
gpio blink command is running to stop the program.
Check out this video, where I take you on a tour of the gpio utility.
Capture the signals by using the receiver
RFSniffer lets you capture the signals that are sent by the RF Outlet’s remote control. The sequence goes like this:
- Start the RFSniffer program in a Terminal window.
- Press the remote control’s “on” button for one of the RF outlets (make a note of which outlet).
- The ASK/OOK encoding will be displayed in the Terminal window.
- Make a note of the encoding, which consists of two numbers: the encoding sequence, and the length of time (in microseconds) between each signal.
- Make a note of which outlet and which function (on in this case) corresponds to that encoding signal.
- Repeat steps 2-5 for the “off” button.
First, start the RFSniffer program in a Terminal window. The program displays a startup sequence that tells you that it has started and entered its “sniffing” loop:
pi@raspberrypi:~/HomeAutomation/433Utils/RPi_utils $ ./RFSniffer Starting program Starting sniffer loop...
Now press the remote control’s “on” button. The remote will send a signal, which is captured by RFSniffer, and displayed in the Terminal window. Then, press the “off” button to capture that signal. The output looks like this:
pi@raspberrypi:~/HomeAutomation/433Utils/RPi_utils $ ./RFSniffer Starting program Starting sniffer loop... Value/Delay/Length: 1119539/174/24 Value/Delay/Length: 1119539/174/24 Value/Delay/Length: 1119539/174/24 Value/Delay/Length: 1119548/173/24 Value/Delay/Length: 1119548/174/24 Value/Delay/Length: 1119548/174/24
Wait. I pressed the “on” button, then the “off” button. I would expect only two lines of output, right?
Not exactly. A couple of different things might be happening. First, 433-MHz devices (and in particular ASK encoding) are notoriously noisy, so lots of remote controls will send the same signal multiple times, even though I only pressed the button once (and quickly). Another possibility is that what I think of as “quickly” in machine time is a very long time indeed, so I might have held the remote button a bit long, which caused the transmitter inside the remote to send the signal multiple times.
At any rate, notice that there are only two unique
Value numbers: 1119539 and 1119548, which correspond to
off, respectively, and they are the decimal representations of the binary encoded values.
The second number is the delay (in microseconds) between on and off values (pulses), as well as the length of a pulse, called the pulse length. As you can see, in one case the delay is 173 and the other cases it is 174. Hardware timings are very precise, so the value shown might not always be exactly the same, but for any particular remote, the values will be very close. Just pick one and stick with it. I’ll use 174 microseconds as the delay for the transmitter demo in the next section.
Write both sets of numbers down that you get from RFSniffer (they will be different for your RF outlets) because you’re going to need them in the next section.
The last number is the length (in bits) of the encoded signal, 24 in this case. As I said, the
Value shown above is the decimal representation of the 24-bit binary value sent by the remote, which is
One of the programs that was built when you ran
make in the
433Utils/RPi_utils directory earlier is called
codesend, and it is used to send encoded signals through the 433-MHz transmitter module.
Now that you’ve captured the encoding for your RF outlet, you can use
codesend to instruct the transmitter module to send that code to the outlet.
Plug the RF outlet into a wall socket, and plug a device (such as a lamp or radio) into the outlet to give you immediate visual or auditory feedback when the outlet goes from on to off, and vice versa.
Go to a Terminal window on the Pi and run the
codesend program. It takes two arguments:
- encoded value (in decimal form)
- pulse length (in microseconds)
To instruct my RF outlet to turn on and then off, I’ll run
codesend like this:
pi@raspberrypi:~/HomeAutomation/433Utils/RPi_utils $ ./codesend 1119539 174 sending code1119539 pi@raspberrypi:~/HomeAutomation/433Utils/RPi_utils $ ./codesend 1119548 174 sending code1119548 pi@raspberrypi:~/HomeAutomation/433Utils/RPi_utils $
And voila! The device plugged into the RF outlet turns on and off. In my case, that’s a lamp.
That’s a lot to absorb. How about a video? In the video below, I’ll show you everything that I just described. So press play and enjoy!
Conclusion to Part 2
In this part, you learned how to set up and build the system software that controls the IoT hardware that you set up in Part 1.
Don’t stop now! Jump on in to Part 3, where you write the IoT apps that make your home automation system complete!