Skip to content
Snippets Groups Projects
user avatar
Charles JAVERLIAT authored
89a2fe7f

Raspberry Pi Setup Guide

Table of contents

Prerequisites

OS installation

We recommend to install the Raspbian OS. You can put it on a USB stick or an SD card. We will do the latter one. Install the Raspberry Pi imager from the official website. Click on 'Choose OS', in 'Raspberry Pi OS (other)', select 'Raspberry Pi OS Lite'. Then choose the SD card and start writing the OS on it.

Enable SSH

If you want to access the Raspberry Pi from your computer via an SSH connection, you should first enable it. To do so, open the SD card 'rootfs' partition from your computer and create an empty file called ssh in the root of boot partition.

You can now put the SD card back into the Raspberry Pi. Plug it to your computer using an ethernet cable set your wired connection IPv4 method to 'Shared to other computers' to share your WiFi connection with the Raspberry Pi.

You can now power up the Raspberry Pi. In a terminal, connect to the Raspberry Pi using ssh:

ssh pi@raspberrypi.local

The default password is raspberry. You can change it later using:

passwd

It is possible to encounter an issue where SSH is very slow... One possible fix is to disable reverse DNS lookup using this fix. Just uncomment UseDNS no in /etc/ssh/sshd_config.

Change locale

echo "
export LANGUAGE=en_GB.UTF-8
export LANG=en_GB.UTF-8
export LC_ALL=en_GB.UTF-8
" >> ~/.bashrc

source ~/.bashrc

sudo locale-gen en_GB.UTF-8

sudo dpkg-reconfigure locales

Then select en_GB.UTF-8 in the list. Then choose 'en_GB.UTF-8' as the default locale. and you are done.

Required packages

You have to install a few packages to follow this guide smoothly.

sudo apt-get update && sudo apt-get full-upgrade -y
sudo apt-get install -y python3 python3-pip cmake build-essential git gcc g++

# Use python3 and pip3 as default
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 10

Change the hostname

You might want to change the hostname of your Raspberry Pi to differentiate it with others on the same network.

The simplest way to change it is to use the raspi-config program:

sudo raspi-config

Go to 'System Options'> 'Hostname' and enter the new hostname you want to use. This will modify the /etc/hostname and /etc/hosts files.

Reboot your Raspberry Pi for the avahi mDNS daemon to apply the changes. You should now be able to ping your-hostname.local from your computer if it is on the same network as the Raspberry Pi.

Allows control of the GPIOs

For the Raspberry Pi to be able to use its GPIOs, we will install pigpio.

sudo apt-get install -y pigpio
# Run the pigpio daemon on boot
sudo systemctl enable pigpiod
sudo systemctl start pigpiod
sudo service pigpiod status

Enable I2C and/or SPI

The simplest way to enable the I2C and/or SPI is to use the raspi-config program:

sudo raspi-config

Go to 'Interfacing Options' > 'I2C' / 'SPI' and enable the interface.

Disable services you don't use

To reduce boot time of the Raspberry Pi, you can disable some services of systemd. Firsly, you can run the following command to see which service is making the boot slower:

sudo systemd-analyze time

We can disable several modules we don't need, such as ModemManager (for 2G/3G/4G), Bluetooth, ...

Disable ModemManager

sudo systemctl disable ModemManager.service
sudo systemctl stop ModemManager.service

Disable bluetooth

sudo nano /boot/config.txt

Add the following line:

# Disable Bluetooth
dtoverlay=disable-bt

Then, disable the systemd services, and remove the unnecessary packages:

sudo systemctl disable hciuart.service
sudo systemctl disable bluealsa.service
sudo systemctl disable bluetooth.service
sudo apt-get purge bluez -y
sudo apt-get autoremove -y

As a side effect, this will restore UART0/ttyAMA0 over GPIOs 14 (pin 8) & 15 (pin10).

Install ROS Noetic

The Raspberry Pi will be the host for the roscore which is used to manage the connections between the nodes. Thus, we need to install ROS on the Raspberry Pi.

Install from Debian repositories

As of today (February 2021), there are no directly built package available for ros-noetic-ros-base for Debian 10 supporting armhf architecture. However, if this tutorial becomes outdated when you read it, give it a try by executing:

sudo apt-get update && sudo apt-get install -y ros-noetic-ros-base

Build from sources

If the previous command doesn't work (no package found), then you should execute the following commands to build ROS Noetic from sources:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-noetic.list'

sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

sudo apt-get update

sudo apt-get install -y python3-rosdep python3-rosinstall-generator python3-vcstool python3-rosinstall build-essential cmake

sudo rosdep init
rosdep update

mkdir -p /tmp/ros_catkin_ws/src
cd /tmp/ros_catkin_ws

rosinstall_generator ros_comm --rosdistro noetic --deps --wet-only --tar > noetic-ros_comm-wet.rosinstall
vcs import src < noetic-ros_comm-wet.rosinstall
rosdep install -y --from-paths src --ignore-src --rosdistro noetic -r --os=debian:buster

# Increase swap size for compilation
sudo dphys-swapfile swapoff
sudo sh -c 'echo "CONF_SWAPSIZE=1024" > /etc/dphys-swapfile'
sudo dphys-swapfile setup
sudo dphys-swapfile swapon

# Install ROS Noetic in the folder /opt/ros/noetic
sudo src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --install-space /opt/ros/noetic -j1 -DPYTHON_EXECUTABLE=/usr/bin/python3

# You can restore previous swap size if you want. By experience, this is needed on the Pi 3B+ to compile heavy packages, so we'll leave it as it is.
#sudo dphys-swapfile swapoff
#sudo sh -c 'echo "CONF_SWAPSIZE=100" > /etc/dphys-swapfile'
#sudo dphys-swapfile setup
#sudo dphys-swapfile swapon

sudo rm -rf /tmp/ros_catkin_ws/

echo "export ROS_MASTER_URI=http://$(hostname).local:11311" >> ~/.profile
echo "export ROS_IP=$(hostname).local" >> ~/.profile

You can now execute the following command to have access to all of ROS' commands:

source /opt/ros/noetic/setup.bash

#or (if using zsh)

source /opt/ros/noetic/setup.zsh

Install ROS common_msgs

common_msgs contains a set of defaults messages that we may use during ROS development. Such as sensor_msgs, diagnostic_msgs, ...

Install from Debian repositories

As of today (February 2021), there are no directly built package available for ros-noetic-common-msgs for Debian 10 supporting armhf architecture. If you installed ROS Noetic from Debian repositories, then the package might already be installed. If not, run the following command:

sudo apt-get update && sudo apt-get install -y ros-noetic-common-msgs

Install from sources

If the previous command doesn't work (no package found), then you should execute the following commands to build common_msgs from sources:

mkdir -p /tmp/ros_common_msgs_ws/src
cd /tmp//ros_common_msgs_ws/

git clone https://github.com/ros/common_msgs /tmp/ros_common_msgs_ws/src/common_msgs

# Install directly in /opt/ros/noetic folder
sudo su <<HERE
source /opt/ros/noetic/setup.bash
catkin_make -DCMAKE_INSTALL_PREFIX=/opt/ros/noetic install
HERE

sudo rm -rf /tmp/ros_common_msgs_ws/

Install rosserial_python

rosserial_python will be used as a connection between a rosserial node running on a microcontroller (arduino, stm, ...) and the ROS network.

Install from Debian repositories

As of today (February 2021), there are no directly built package available for rosserial_python for Debian 10 supporting armhf architecture. However, if this tutorial becomes outdated when you read it, give it a try by executing:

sudo apt-get update && sudo apt-get install ros-noetic-rosserial-python

Build from sources

mkdir -p /tmp/rosserial_catkin_ws/src/rosserial
cd /tmp/rosserial_catkin_ws/src/rosserial

git init
git remote add -f origin https://github.com/ros-drivers/rosserial.git

# We only want to clone specific packages that interest us, so we do a sparse checkout
git config core.sparseCheckout true
echo "rosserial" >> .git/info/sparse-checkout
echo "rosserial_client" >> .git/info/sparse-checkout
echo "rosserial_msgs" >> .git/info/sparse-checkout
echo "rosserial_python" >> .git/info/sparse-checkout
git pull origin noetic-devel

cd /tmp/rosserial_catkin_ws

# Install directly in /opt/ros/noetic folder
sudo su <<HERE
source /opt/ros/noetic/setup.bash
catkin_make -DCMAKE_INSTALL_PREFIX=/opt/ros/noetic install
HERE

sudo rm -rf /tmp/rosserial_catkin_ws

Launch the roscore on boot

As we want the ROS master to be launched on the Raspberry Pi when it boots up, we will create a systemd service.

To do so, we created a script call install-roscore-service.sh that will create the environment file along with the service unit for systemd.

# Export environment variables for the systemd service
sudo sh -c 'cat > /etc/default/roscore-env <<EOF
ROS_DISTRO=noetic
ROS_ROOT=/opt/ros/noetic
ROS_PACKAGE_PATH=/opt/ros/noetic/share
ROS_MASTER_URI=http://$(hostname).local:11311
ROS_IP=$(hostname).local
CMAKE_PREFIX_PATH=/opt/ros/noetic/
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/ros/noetic/bin
LD_LIBRARY_PATH=/opt/ros/noetic/lib
PYTHONPATH=/opt/ros/noetic/lib/python3/dist-packages
EOF
'

# Create the service, it will be launched after 
sudo sh -c 'cat > /etc/systemd/system/roscore.service <<EOF
[Unit]
Description=roscore service
Wants=network-online.target
After=network.target network-online.target

[Service]
User=pi
EnvironmentFile=/etc/default/roscore-env
ExecStart=/opt/ros/noetic/bin/roscore -p 11311
Restart=on-abort

[Install]
WantedBy=multi-user.target
EOF'

sudo systemctl enable roscore.service
sudo systemctl start roscore.service
sudo systemctl status roscore.service

Network

We install network-manager and get rid of dhcpcd5 and openresolv, we will not need them anymore.

sudo apt-get update && apt-get install network-manager -y
sudo apt-get purge openresolv dhcpcd5 -y

Network manager will provide a default configuration for the ethernet interface, so you can plug your Raspberry Pi on the ethernet directly to your computer. If you want the Raspberry Pi to have access to internet from your computer through the ethernet, you can change the configuration of your ethernet interface on your computer. Just change the IPv4 method to "Shared with other computers".

Setup access point

We might want the Raspberry Pi to create its own access point for other devices to connect directly to it.

We start by unblocking the WiFi interface from rfkill

sudo rfkill unblock wlan

We add the country code in wpa_supplicant for Wireless LAN frequencies reglementations.

sudo echo "country=FR" >> /etc/wpa_supplicant/wpa_supplicant.conf

We create the access point configuration file for network-manager. Note that it will not be loaded if the permissions are not set to 0600 and file is not owned by root. You might also want to change the name, password, and WiFi band and channel.

sudo touch /etc/NetworkManager/system-connections/AccessPoint.nmconnection

sudo chmod 0600 /etc/NetworkManager/system-connections/AccessPoint.nmconnection

sudo bash -c 'cat << EOF > /etc/NetworkManager/system-connections/AccessPoint.nmconnection
[connection]
id=AccessPoint
uuid=4fe1d21b-ab87-4cc9-93ba-5096803d6e88
type=wifi
interface-name=wlan0
permissions=
[wifi]
# This is configured to use 2.4GHz WiFi, you can change this to use 5GHz if needed
band=bg
channel=7
mac-address-blacklist=
mode=ap
# Name of the Access Point
ssid=AwesomeBenoitNetwork
[wifi-security]
key-mgmt=wpa-psk
# Password of the Access Point, you should probably change this
psk=test12345
[ipv4]
# Addresses that will be given to devices connecting to this access point
address1=192.168.2.50/24,192.168.2.1
dns-search=
method=shared
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto
EOF'

Finally, we reload the connection configurations.

sudo nmcli c reload

We can check that everything is working fine by running the following command:

sudo nmcli

You should get something like this:

eth0: connected to Wired connection 1
        "Standard SMSC9512/9514"
        ethernet (smsc95xx), B8:27:EB:1C:17:5F, hw, mtu 1500
        ip4 default
        inet4 10.42.0.113/24
        route4 0.0.0.0/0
        route4 10.42.0.0/24
        inet6 fe80::5041:9dee:d32e:ecb7/64
        route6 fe80::/64

wlan0: connected to AccessPoint
        "Broadcom BCM43438 combo and Bluetooth Low Energy"
        wifi (brcmfmac), B8:27:EB:49:42:0A, hw, mtu 1500
        inet4 192.168.2.50/24
        route4 192.168.2.0/24
        route4 0.0.0.0/0
        inet6 fe80::f560:40c7:c453:a66e/64
        route6 fe80::/64

You should see that the wlan0 is now connected to AccessPoint.

SSH connection

You can connect via SSH to the Raspberry in two different ways:

  • via its Access Point
  • via ethernet, plus if you set your IPv4 to be "Shared to other computers" the Raspberry will have access to the network and propagate it to any device connected to it.

In both case, you can use ssh to connect like so:

ssh pi@raspberrypi.local

If you are connect via ethernet to the Raspberry, but you want to access directly a device connected on its access point, you can pass through it as a gateway as described in this article.

For example, you can connect to a device with the IP 192.168.2.51 on the WiFi network of the Raspberry directly from your computer by doing:

ssh -J pi@raspberrypi.local 192.168.2.51

It is possible to encounter an issue where SSH is very slow... One possible fix is to disable reverse DNS lookup using this fix. Just uncomment UseDNS no in /etc/ssh/sshd_config.

Install PlatformIO

PlatformIO will be necessary if we want to flash program to microcontrollers connected to the Raspberry Pi. Note that we do not recommend building directly microcontrollers programs on the Raspberry Pi, as it can be pretty slow compared to a regular computer. To tackle this issue, you can use the pio remote agent to build locally on your computer, and just delegate the work of flashing the program on the microcontrollers to the Raspberry Pi.

yes | pip install platformio

# Install udev rules
sudo curl -s https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules -o /etc/udev/rules.d/99-platformio-udev.rules
sudo service udev restart
sudo usermod -a -G dialout $USER
sudo usermod -a -G plugdev $USER

echo "export PATH=$PATH:~/.platformio/penv/bin" >> ~/.profile

You should log out and log back to the Raspberry Pi at this point for the group changes to be effective.

Install PlatformIO Remote agent

As mentionned in the last section, the PIO remote agent is really useful to save some time on the compilation of microcontrollers' programs. To install it, just do the following:

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install pio remote agent
pio remote agent

You can then start the agent on the Raspberry Pi. But first you will need to be logged in to a Platform IO agent:

pio account login # -> login into your account
pio remote agent start

From your computer, run pio remote agent list when on the same network as the Raspberry Pi's, you should see it in the list of usable agents.

Launch pio remote agent on boot

To run the pio remote agent on boot, we will create a systemd service. First you should get your connection token:

pio account login
pio account token # -> copy the token somewhere

Note that the token will expire after 2 weeks, so you will have to update it in your service file when this happens.

Then we will create a new service file. Create a file named /etc/systemd/system/pio-remote.service with the following content.

[Unit]
Description=Run platformio remote agent
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
Environment="PLATFORMIO_AUTH_TOKEN=<insert your token here>"
WorkingDirectory=/home/pi/.platformio/penv
ExecStart=/home/pi/.platformio/penv/bin/pio remote agent start --serve-in-foreground
User=pi
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Then enable the service:

sudo systemctl enable pio-remote.service
sudo systemctl start pio-remote.service
sudo systemctl status pio-remote.service

Create an image of the system

It is a good idea to create an image of your system to flash it back on a fresh SD card if needed. In fact, corruption of cards can happen, so it is recommended to keep an image ready to be transferred to economize some time. On a Linux system, plug the SD card and run the following command to create a raw copy:

sudo dd bs=4M if=/dev/mmcblk0 of=~/Documents/raspios-armhf.img conv=fsync

With /dev/mmcblk0 the name of the SD card. Feel free to change the name of the image.

By default, dd will make a bit-by-bit image of the SD card, even if a major part is filled with zeroes. To reduce the image size, we can use PiShrink to reduce its size:

wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
# Install the scripts in the list of binaries to run it directly from cmd-line
sudo mv pishrink.sh /usr/local/bin

sudo pishrink.sh -az ~/Documents/raspios-armhf.img