Sunday 24 April 2016

Build a solderless Big Red Button using Raspberry Pi and Node.js

The Big Red Button

This is a simple tutorial for building your own Big Red Button, used to do whatever you come up with. Here, I use Node.js to make the button active at a set interval. If pressed while active, it fetches cat clips from Youtube and posts it on Twitter.


You can of course do whatever. If you can reach something through an API, it's easy to work with. Or, maybe use Selenium Webdriver and trigger something by visiting a website? At work, we use the button to listen to our deploy system Octopus and trigger deploys to production when they're available.

What you need:

  • Raspberry Pi with built in wifi/wifi dongle
  • Formatted microSD-card
  • Adafruit Large Arcade button with built in resistor
  • 4 jumper cables, female to whatever
  • 2 faston connectors 4,8 mm
  • 2 faston connectors 6,3 mm
  • Power supply with MicroUSB cable
  • Cardboard or other type of box, minimum 6 cm high (enough to house the button and the pi)
  • Tool to make holes in the box for the button and cable
  • Cable peeler and crimping tool
  • 5mm LED
  • LED holder for attaching to box
  • 3 jumper wires female to female
  • 1 resistor, 330 Ohm

Let's start by setting up the Raspberry Pi

  • Download the latest release of Noobs from https://www.raspberrypi.org/downloads/.
  • Extract the files and copy them onto the formatted SD-card.
  • Connect the Pi to a screen/TV using HDMI. Plug in a keyboard and a mouse.

Follow along with the installation instruction and install Raspbian. When that is done, click Menu > Preferences > Raspberry Pi Configuration and configure the Pi according to your own locale. Set up the Wifi, either the built in or the dongle. Also make sure you tick the checkbox for boot option "Wait for network".

When you're connected to the network, find your Pi's ip number by opening the console and running the command ip addr. Make a note of it, you'll need that later.

All Pis come with the default user 'Pi' and password 'raspberry'. It might be a good idea to change this if you expose the Pi on the internet. When I write piuser in the instruction, I mean the username you use, whether it's 'pi' or something else. :)

Using SSH to access Pi

When you need to write something in the console on your Pi, you can either do it on the Pi, or you can use SSH from another computer. If you're using Windows, you have to install an SSH-client. Install Cygwin with the OpenSSH-package to get access to SSH as well as SCP, which is needed to copy files to the Pi.

Log in to your Pi by opening a console on your computer and write SSH piuser@pi-ipnumber. For Windows, you use Cygwin. You will be prompted to input the password and then you'll be connected. Using SSH you can perform the same commands as if you were looking at the Pi's console. When the instruction here says Pi-console, you can use either SSH on your computer or the console on Pi.

Using remote desktop connection to access Pi

If you want to be able to connect remotely to the Pi and share screens with your PC/Mac, you can install TightVNCServer on the Pi. This is nice if you, like me, only have a laptop at home. I don't want to go over to the TV just to see the Pi desktop.

Follow the instructions here to set TightVNC up on Pi and your computer, and get it to autostart on the Pi: https://www.raspberrypi.org/documentation/remote-access/vnc/

Once installed, the Pi is accessible on port 5901.

Install Node.js on Pi

Depending on which model of the Pi you have, download and install the correct version of Node.js by opening up a Pi-console and writing:

Pi, Model A:
>wget https://nodejs.org/dist/v4.4.3/node-v4.4.3-linux-armv6l.tar.gz 
>tar -xvf node-v4.4.3-linux-armv6l.tar.gz 
>cd node-v4.4.3-linux-armv6l

Pi2 and Pi3, Model B:
>wget https://nodejs.org/dist/v4.4.3/node-v4.4.3-linux-armv7l.tar.xz
>tar -xvf node-v4.4.3-linux-armv7l.tar.xz 
>cd node-v4.4.3-linux-armv7l

Then copy the files to usr/local to make them accessible on the path:
>sudo cp -R * /usr/local/

You can remove the downloaded packages if you want to save space on your SD-card. Make sure everything installed correctly by writing node -v in your Pi-console. You should get back the version number, 4.4.3 in this case.

First hardware test: Connect a LED

Let's start with something really simple that explains the concept of the Raspberry Pi. The Pi has 40 pins: https://www.element14.com/community/servlet/JiveServlet/previewBody/73950-102-9-339300/pi3_gpio.png. There are pins for ground and power, and then there are the GPIO-pins (General Purpose Input/Output). In short, and without the gritty details, when you connect something that should be turned on, you want a circuit going through it from power to ground. But you also need a resistor somewhere in that circuit, because otherwise the current flowing through the circuit back to the Raspberry might be too high and fry your Pi.

So for the first test, you need a LED, three jumper wires F/F and a 330 Ohm resistor. Resistors are tricky, use the excellent help at http://www.hobby-hour.com/electronics/resistorcalculator.php to make sure you find the correct one. With a 5-band resistor, 330 Ohm has the code orange, orange, black, black, brown.

If you look at the LED, one leg is longer. This is the anode that should be connected to power. Start with pressing the anode leg into one end of a jumper wire. The other leg should be connected to ground, but with a resistor in between. Connect the ground leg to a jumper wire, insert a resistor in the other end of it and then another jumper wire after the resistor.


Now connect the anode jumper wire to a 3,3 volt pin on your Pi, and the ground jumper wire to a ground pin. Connect your Pi to power and Voila! Light!

So how do the GPIO pins work? Well, move the jumper wire you connected to power to one of the GPIO-pins instead. You might see that it's still on, but weaker. If so, it's in a state called 'floating'. The GPIO-pins can be in three states:
  • Low, which means it's outputting no current.
  • High, which means it's outputting 3,3v, just like a normal power pin.
  • Floating, which means it's in a random state, affected by electromagnetic fields and whatnot.
After this first test, I'm sure you can see what our programming will actually do. Set GPIO-pins to high or low! Turn things on or off.

First software test: turn the LED on programmatically

For this, we need to get our Node environment up and running. If you don't have Nodejs on your computer, follow the instructions here: https://nodejs.org/en/.

Download the PiNodeStarterProject from http://github.com/asalilje/PiNodeStarterProject. The project contains a package.json setting up the dependencies for manipulating the GPIO-pins, and a deployment file that makes it easy to move all your files to your Pi and start the app. The code is written using ES2015, which demands you have the line "use strict" at the beginning of each file.

Open the app.js file. You should see the following lines:
"use strict";
const GPIO = require('onoff').Gpio;

function exit() {
    process.exit();
}

process.on('SIGINT', exit);

What we do here is just importing the dependency to the excellent onoff-package and setting up an exitfunction that's run when the Nodeprocess ends, that is, when you press Ctrl + C.

To set a pin high or low, you need to first define the pin and the data direction. If you want to listen to a button it's 'in', but here, it's 'out'. Make sure your led is connected to ground and a GPIO-pin on the anode side. Check the number of the pin on the chart.

At the line after requiring the onoff-package, insert the code, (with your correct GPIO if it's not GPIO21):
const led = new GPIO(21, 'out');
led.writeSync(1);

Also, you want to turn off the light and kill the GPIO-definition when the process exits. Do this by modifying the exit function to look like this:
function exit() {
    led.writeSync(0);
    led.unexport();
    process.exit();
}

That's it. Now our program should turn on the LED properly with a full 3,3v!

To deploy this program to your Pi, go into gulpfile.js and change the hostname, user and password to reflect your Pi's setup. Save the file and in a console, cd to the project directory and write npm install to install the packages needed to develop the app. Don't worry if the Gpio-modules onoff and epoll won't install.

Move files to Pi
If you're on a Mac, running npm run deploy will create a directory on the Pi and copy files to it using SCP. Sadly, I haven't gotten the copy part to work on Windows yet, here you must run the script inside Cygwin and you will get a permission denied. After doing this, the directory is created and it's possible to handle the file copy by running the actual copy command directly in cygwin: scp app.jss package.json piuser@pi-ipnumber:/home/piuser/PiNodeStarterProject. You should be prompted for the user's password and the files are copied onto the raspberry. Now run npm run modules to install the node modules. When that is done, run npm run app to start the app on the Pi. Hopefully, everything is connected A-OK and the LED lights up.

Note, that this app can't be run locally on your computer when the onoff-package is required and called, since it needs access to the pins. If you want to test other logic in your program locally you have to work around that by triggering actions in other ways.

Time to connect the button!

The arcade button has 4 connectors. The ones on the side are for the LED inside the button. The other two are for the input. To connect the button, you need four jumper wires with one female end. That end is connected to the Pi. The other end needs to be cut and peeled to crimp on a faston connector.


Two 4,8 mm and two 6,3 mm connectors are needed. Since the jumper wires are very thin, it might help to peel off 2 centimetres of the shell so you can fold the copper thread and make it a bit thicker. Make sure you have a good crimping tool (or strong hands).


Connect the button LED
Let's try out the button LED first. Just connect the wider two flaton connectors to the connectors on the side of the button. Connect the one on the red side to a 3,3v power pin, and the other to ground. The LED shines! So all we need to do here is the same as we did with the other LED, connect it to a GPIO pin instead of a power pin. The LED has a built in resistor, so you don't have to add any to the circuit.


Connect the button switch
Output pins are easy to configure, but there's a bit more to an input pin. If an input pin is in a floating state, it could behave very randomly. We need a pin that has a pulldown or pullup resistor. Simply put, the pulldown resistor sets the default state of the pin as low and the pullup resistor sets the default state to high. Here, we don't care whether it's high or low, since we only want to listen to the button being pushed and not use the actual state of the button.

The GPIO pins on a Pi can be configured to use pulldown or pullup resistors, but let's just use one of the I2C ones, GPIO2 or GPIO3 since they have built in resistors. Connect the two remaining connectors on the button to the Pi, the lower one to ground and the higher one to GPIO2.


Let's try that out with some Node.js-coding. When we press the button, we want to light the button LED for 1 second. Insert the following code in your app.js file:
const buttonLed = new GPIO(4, 'out');
const buttonPush = new GPIO(2, 'in', 'falling');

buttonLed.writeSync(0);

buttonPush.watch(function(state) {
 console.log("Button pushed, state ", state);
 buttonLed.writeSync(1);
 setTimeout(function() {
  buttonLed.writeSync(0); 
 }, 1000);
});

Run npm run deploy to copy the files to your Pi. But instead of doing npm run app, use SSH to connect to your Pi and run your application from there. This will make it possible for you to see the output from the app. CD into /home/piuser/PiNodeStarterProject and write node app.js to start the application. Now push the button and see the LED turn on.

What you also will see is that each push of the button triggers several calls to the button.watch-function. One way to deal with this is to set the button as inactive the first time it's triggered and then activate it again as soon as your button action has been performed.

And that's basically it. Now you have a button with a built in LED, an extra LED to turn on when the app is running and a function watching for button pushes. What's left to do is decide what you actually want to do with your Big Red Button. And of course assemble the box. If you want to look at a project for inspiration, check out the CatBot that plays around with all these features and connects to Youtube and Twitter. Code is available on http://github.com/asalilje/catbot.

Last step - set up your app to start automatically on the Pi

Once you have your dream app up and running, I'm sure you want to be able to pull the plug on the Pi and get it to start your app automatically when booting next time. Here's how.

Go into your Pi-console and write sudo nano /etc/rc.local. Before the exit-statement, insert:
PATH=$PATH:/usr/local/bin
cd /home/PiUser/YourProject #path to your app
/usr/local/bin/node app.js < /dev/null >/var/tmp/startup.log 2>/var/tmp/startup.err &

This code snippet starts your node-app and logs errors so you can see if anything goes wrong during the startup. Restart your Pi to make sure the app starts.

Good luck, have fun!