Skip to content

Getting a Raspberry Pi ready for NodeBots

Bryan Hughes edited this page May 8, 2020 · 39 revisions

Using a Raspberry Pi for robotics can take a fair amount of work to get set up properly. This document will walk you through installing and configuring everything you need to use node-serialport or Raspi IO with Johnny-Five. I recently gave a talk that runs through these steps, plus a few more, if you prefer to watch a video.

Video walkthrough of setting up a Raspberry Pi

Installing the OS

There are a variety of Operating System's to choose from for the Raspberry Pi, but Raspbian is the only OS that is officially supported by Raspi IO. Other OS's have been made to work but be forewarned that you may have to work through a lot of issues on your own first. For more information on other OSes, take a look at issue #24.

Pi Bakery used to be the recommended method for writing Raspbian to the SD card, but it hasn't been receiving many updates lately and has been rather flakey.

The currently recommended way is to download the image from the official Raspberry Pi website. You can choose between two version of Raspbian: Raspbian Full and Raspbian Lite. I prefer Raspbian Lite myself, as NodeBots are not typically connected to a monitor and so you don't need the GUI. However, if you need the GUI, then install Raspbian Full.

Once you have downloaded the image of your choice, follow the official instructions for your operating system to write the image to your SD card.

After the image has been written, you will need to make one modification to the image to enable SSH before removing the SD card from your computer.

Assuming you are on a *NIX compatible computer (macOS, Linux, Ubuntu on Windows, etc), open a terminal, navigate to the root of the SD card (/Volumes/boot on macOS) and then type:

touch ssh

Now you are ready to insert the SD card into your Raspberry Pi.

Connecting to the Raspberry Pi for the first time

Most of the time, we want to run the Raspberry Pi "headless," aka not connected to a monitor, mouse, and keyboard. There is some initial setup work that needs to be done, and it is usually recommended to connect to a monitor, mouse, and keyboard for the first boot to do this work. It can be done without a monitor, mouse, and keyboard though, and this document will describe both approaches.

Method 1, using a monitor

Note: the default username for Raspbian is "pi", and the default password is "raspberry".

Connect the following to your Raspberry Pi:

  • Connect a monitor using an HDMI cable
    • If you're monitor does not support HDMI, you may be able to buy an adapter
  • Connect a USB keyboard
  • Connect an Ethernet cable that is connected to the Internet if you do not have a WiFi enabled Raspberry Pi

Once everything is connected, connect power to the Raspberry Pi to turn it on.

Method 2, using SSH

If you don't have easy access to an external monitor and keyboard, it is possible to set the Raspberry Pi by connecting using SSH the first time.

If your laptop supports mDNS, then you can connect to the raspberry pi with ssh pi@raspberrypi.local. If you are on macOS, you already have built in support. If you are on Windows, you can add support for mDNS by installing Apple's Bonjour Print Services for Windows. I believe that Linux has support out of the box, but I've never tested it.

Using Internet Sharing in macOS

If you are unable to connect using the above method, perhaps due to your laptop not being able to resolve the mDNS name of the Raspberry Pi, here's a more manual method that is more reliable.

Connect power to the Raspberry Pi to turn it on (don't connect Ethernet just yet). Watch the ACT LED (aka activity light). Once this stops flashing, that means the Raspberry Pi has finished booting up.

Go into System Preferences->Sharing and configure your computer to share Internet from WiFi to your Ethernet adapter, and then click the check box next to Internet Sharing on the left to turn it on.

Now connect the Ethernet cable between your Raspberry Pi and Laptop. If you have a new Macbook, Macbook Air, or newer Macbook Pro, you will need to get a USB/USB C/Thunderbolt to Ethernet adapter (Apple sells these).

The Rapsberry Pi should now have an IP address obtained from your computer. To find out what address it obtained, run

cat /var/db/dhcpd_leases

This will print out all IP addresses your computer has given out. Note that deleting this file will cause all devices to be issued new IP addresses. The output should look like this:

{
	name=my-rpi
	ip_address=192.168.2.2
	hw_address=1,b8:27:eb:ca:58:ee
	identifier=1,b8:27:eb:ca:58:ee
	lease=0x56f61490
}

The IP address should always be either 192.168.2.2 or 192.168.3.2, unless you have used Internet Sharing for other devices. Now you can connect to the Raspberry Pi by running:

ssh pi@<IP address from above>

Linux and Windows

The steps for Linux and Windows should be similar to the macOS instructions, but replacing the macOS specific steps with equivalent steps for your OS. If you figure out how to do it, let me know by filing an issue so I can add it to the wiki!

Installing Node.js

Now that we are connected to the device, it's time to install Node.js!

Warning: It is technically possible to install Node.js using nvm as well, but this method is not recommended for NodeBots because Raspi IO requires installing as non-root, but running as root. This confuses nvm, which modifies the path and symlinks things in a user specific way. This means you have to do a fair amount of manual work to get everything linked correctly. As such, nvm is not supported by Raspi IO.

Raspberry Pi 2/3/4

We are going to use the NodeSource Ubuntu packages to install Node.js. You will need to choose which release of Node.js to install. For details on Node.js releases and version numbering, check out the Node.js LTS documentation. Generally speaking, you can choose between a Long Term Support (LTS) release, or a non-LTS release. LTS versions are more stable and recommended for production use, and is recommended for NodeBots.

As of this writing, the current LTS version is version 12.x, so we will use that in this section. The first step is to tell Raspbian about NodeSource' packages for version 12.x of Node.js

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -

Note the 12 in the URL. If you wish to use a different version, see the NodeSource installation instructions.

Next, install Node.js with:

sudo apt-get install -y nodejs

Raspberry Pi Zero/1

The NodeSource PPA for Node.js no longer supports ARMv6 CPUs unfortunately, which the Raspberry Pi 1 and Zero models all ship with. In this case, you'll need to download binaries directly from the Node.js website and install them manually.

Go to https://unofficial-builds.nodejs.org/download/release/ and copy the link to the latest LTS ARMv6 Node.js binary you wish to use. Then, run the following commands on your Raspberry Pi, replacing X.X.X with the version in the link you copied:

wget https://unofficial-builds.nodejs.org/download/release/vX.X.X/node-vX.X.X-linux-armv6l.tar.gz
tar -xf node-vX.X.X-linux-armv6l.tar.gz
sudo mv node-vX.X.X-linux-armv6l /usr/local/node
cd /usr/bin
sudo ln -s /usr/local/node/bin/node node
sudo ln -s /usr/local/node/bin/npm npm
node -v  # Verifying that the Node.js install worked
npm -v   # Verifying that the npm install worked

WARNING: Because we installed this manually, sudo apt-get upgrade will not upgrade Node.js! To upgrade your version of Node.js, you should run these steps periodically.

Installing node-serialport only

If you are using node-serialport independent of Johnny-Five and Raspi IO, the final step is to install it with npm. In a project folder somewhere (e.g. ~/documents/hello_world), run

npm install serialport

After this step, you're done and can stop reading here!

Installing Johnny-Five and Raspi IO for the first time

Now it's time to install Johnny-Five and Raspi IO for the first time! In a project folder somewhere (e.g. ~/documents/hello_world), run

npm install johnny-five raspi-io

This will download the modules, compile all native modules (there are several), and modify a few of Raspbian's configuration files. If there are any issues, please file an issue and let us know.

IMPORTANT: Once you are done installing Raspi IO for the first time, make sure you reboot before you run any code! This reboot is not necessary for subsequent installs of Raspi IO

Blinking an LED

Whew, now that all that's done, it's time to run some code! Paste the following code into a file called index.js in the project folder.

const { RaspiIO } = require('raspi-io');
const five = require('johnny-five');
const board = new five.Board({
  io: new RaspiIO()
});

board.on('ready', () => {
  // Create an Led on pin 7 on header P1 (GPIO4) and strobe it on/off
  const led = new five.Led('P1-7');
  led.strobe(500);
});

Now, run sudo node index.js and you should see the ACT LED flashing twice a second! Note that sudo is always required when running Raspi IO code.

Debugging your code

You can get pretty far with console.log statements, but eventually there comes a time when you need a full debugger. Fortunately you can debug your app using Visual Studio Code running on your laptop or desktop.

First, we need to configure VS Code. If it does not exist already, create a file called .vscode/launch.json. Inside of your launch.json file, add the following information:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Debug RPi",
      "address": "ip.add.re.ss",
      "port": 9229,
      "localRoot": "${workspaceRoot}",
      "remoteRoot": "/home/pi/repo",
      "sourceMaps": true,
      "outFiles": [
        "${workspaceRoot}/dist/**/*.js"
      ]
    }
  ]
}

You can change the name property to whatever you would like. VS Code uses this property to give it a name in the debugging drop-down menu. This is useful if you have multiple debugging targets in your project.

The address section should contain the IP address of your Raspberry Pi. The port section should contain the port that the Node.js debugger is listening on, which defaults to 9229.

localRoot identifies where your local source code is on your laptop/desktop, and remoteRoot identifies where your remote source code is on the Raspberry Pi. VS Code uses this information to correlate the files together so that you can set breakpoints in VS Code and have them get lined up with the code executing on your Raspberry Pi.

Only add the sourceMaps and outFiles entries if you are compiling your code using, e.g. babel or TypeScript. If you are running the code you write directly, then leave these two entries out.

Once you've configured VS Code properly, start your application on the Raspberry Pi by running the following command on the Raspberry Pi (not your laptop/desktop):

node --inspect-brk=ip.add.re.ss:9229 index.js

Replace index.js with the path to your app's entry file as appropriate.

Be sure to read VS Code's debugging user guide and Node.js debugging guide for more details.

Configuring your app to start on startup

There are a variety of ways to configure your app to start when the Raspberry Pi boots up. I prefer to use systemd the built-in process manager for Debian/Ubuntu/Raspbian.

Create a file at /etc/systemd/system/my-node-service.service, replacing my-node-service with any friendly name that describes your app. Inside this app, add the following:

[Unit]
Requires=systemd-networkd.socket
After=systemd-networkd.socket

[Service]
# Only add this first line if you need wifi for your app to function
ExecStartPre=/lib/systemd/systemd-networkd-wait-online --interface=wlan0
# Replace path as appropriate
ExecStart=/usr/bin/node /path/to/project/main.js
Restart=always
StandardOutput=syslog
StandardError=syslog
# Replace name as appropriate
SyslogIdentifier=my-node-service
Environment=NODE_ENV=production
User=root
Group=root

[Install]
WantedBy=multi-user.target

If your app depends on a network being available, then run this command:

sudo systemctl enable systemd-networkd-wait-online.service

Then finally, enable your application with:

sudo systemctl enable my-node-service

Next time your reboot your application, it should be running! You can check the status of your service by running systemctl status my-node-app.service, check the console output of your service by running journalctl -u my-node-app.service, and restart your service by running sudo systemctl restart my-node-app.service.