# Pi Zero W Rover Setup
The raspberry pi zero w has just been released and I managed to get my hands on one before they sold out. This has sparked me to restart one of my old project ideas of creating a wireless programmable rover platform. In this first post I will talk about how to setup the pi and hook it up to the servos, in particular how to configure the usb serial and enable and control the hardware pwm pins.
This post will be based off archlinux arm rather than raspbian as my distro of choice but with some tweaks should work equally well on both distros. For those that want to follow along with arch you should first follow my archlinuxarm setup guide we will be adding a few steps to the end of the customisation stage. You can also follow along from a running pi if you have raspbian.
# The hardware
The only required components are a couple of continuous rotation servo, ie servos that have been modified to run continuously rather then to a fixed angle, some wheels , a 5v battery and something to hold it all together. And of course the raspberry pi zero w.
The wiring is straight forward, connect both grounds of the servos to one of the ground pins on the pi and both the power pins to one of the 5V pins. Then connect one of the signal wires to GPIO12 and the other to GPIO13.
You should note that the servos can draw quite quite allot of power when running, the pi is fine with this as long as your power supply is able to supply enough power for both the pi and the servos, usually more then about 1.5A.
As for the chassis I simple reused one from an old project, but it is little more then the servos bolted back to back with the pi and a caster wheel bluetacked on. I plan to design and 3d print a better case at a later date once I have a better idea of all the components/sensors I want to add to it.
# Configuring the pi
Once you are in the chroot
of the image or logged into a running pi then its
time to configure our system. We need to enable two extra bits of functionally,
specifically enabling the usb serial interface, the hardware pwm pins and set up the
wireless network.
The usb serial is optional but makes connecting to and debugging the pi zero much easier. All you need is a usb cable connected to your computer to gain access to a full shell and it is simple to setup a wireless network or find out the ip that has been assigned to the pi.
To enable the usb serial interface we need to add the dwc2
overlay to the
config.txt and ensure the g_serial
module is loaded during boot. Then ensure a
getty is listening to the serial port. All of which can be done by running the
following commands.
grep 'dtoverlay=dwc2' /boot/config.txt >/dev/null || echo 'dtoverlay=dwc2' >> /boot/config.txt
grep 'modules-load=dwc2,g_serial' /boot/config.txt >/dev/null || sed 's/.*/& modules-load=dwc2,g_serial' >> /boot/config.txt
ln -sf /usr/lib/systemd/system/getty@ttyGS0.service /etc/systemd/system/multi-user.target.wants/getty@ttyGS0.service
To connect to the pi zero over use serial you will need a program such as
picocom
, minicom
, screen
, putty
, or even the Arduino IDE. There are many
guides out there about how to do this so I will leave out the details in this
post. You can find out more about the other otg functionality of the pi
here.
We want to be able to control two servos from the pi, luckily the pi contains two hardware pwm pins which makes this much simpler. All we need to do is enable them with the following.
grep 'dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4' /boot/config.txt >/dev/null || echo 'dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4' >> /boot/config.txt
Note that you can configure each pwm channel on one of 2 different pins. For
pwm0 you can use GPIO12
or GPIO18
and for pwm1 you can use GPIO13
or
GPIO19
. The command above configures our pi to use pins 12 and 13. You can
read more about the hardware pwms
here.
Lastly we want to configure the wireless so we dont need a cable attached in order to interact with our robot.
# Enable wireless, actual connection details will be configured by the user, likely over usb-serial
ln -sf /usr/lib/systemd/system/wpa_supplicant@.service /etc/systemd/system/multi-user.target.wants/wpa_supplicant@wlan0.service
cat >/etc/systemd/network/wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
DHCP=yes
EOF
cat <<EOF > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1
fast_reauth=1
ap_scan=1
EOF
wpa_passphrase "SSID" "PASSPHRASE" >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
You can install/configure anything else you might find useful at this point.
Now you can finish of and flash the image to an sd card, or simply reboot if your pi if you configure it while it was running.
# Moving the robot
After you have gotten the pi up and running and connected to a wifi network or otherwise have a shell running on it we can start to get it moving.
The hardware pwm pins are controlled by the sys filesystem located at
/sys/class/pwm/pwmchip0
. Before we can do anything we must enable the pwm
channels, this can be done by writing the channel we want to enable to the
export
file. Enable both channels with
echo 0 > /sys/class/pwm/pwmchip0/export
echo 1 > /sys/class/pwm/pwmchip0/export
This should create a couple of directories that will allow us to control each
servo independently, /sys/class/pwm/pwmchip0/pwm0
and
/sys/class/pwm/pwmchip0/pwm1
. Inside these directories we should have at least
three files, period
, duty_cycle
and enable
.
The period is how often we send a pulse in nano seconds. A servo typically expects a pulse every 20ms so we set the period to 20000000ns.
echo 20000000 > /sys/class/pwm/pwmchip0/pwm0/period
echo 20000000 > /sys/class/pwm/pwmchip0/pwm1/period
Servos move to their neutral point, stopped for continuous servos, when they receive a pulse of 1.5ms, so we can set the duty cycle to this.
echo 1500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1500000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
Finally we can enable the servos.
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable
At this point the servos should be enable, and not moving. So lets make it drive forward by setting one servo to go full forward and the other to go full reverse.
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 2000000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
sleep 1
echo 1500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1500000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
This will make the rover drive forward for 1 second then stop. If it drives backwards then simply swap the servos around or reverse the numbers above. If one or both servos do not move double check your wiring.
Try experimenting with different values, but values above 2000000
or below
1000000
will just make the servo go in full forward or full reverse. Values
between these will make the servo move at various speeds between full reverse
and full forward.
Below is a simple script that encapsulates all of this and allows you you program the rover to move in a set path, not much else but enough to get started.
# rover-test.sh
#!/bin/bash
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
IFS=$'\n\t'
chip0=/sys/class/pwm/pwmchip0
pwm0=$chip0/pwm0
pwm1=$chip0/pwm1
pi_disable() {
echo 0 > $pwm0/enable
echo 0 > $pwm1/enable
echo 0 > $chip0/unexport
echo 1 > $chip0/unexport
}
trap pi_disable EXIT
pi_enable() {
echo 0 > $chip0/export
echo 1 > $chip0/export
echo 20000000 > $pwm0/period
echo 20000000 > $pwm1/period
echo 1 > $pwm0/enable
echo 1 > $pwm1/enable
}
pi_forward() {
echo 1000000 > $pwm0/duty_cycle
echo 2000000 > $pwm1/duty_cycle
}
pi_backward() {
echo 2000000 > $pwm0/duty_cycle
echo 1000000 > $pwm1/duty_cycle
}
pi_stop() {
echo 1500000 > $pwm0/duty_cycle
echo 1500000 > $pwm1/duty_cycle
}
pi_right() {
echo 1000000 > $pwm0/duty_cycle
echo 1000000 > $pwm1/duty_cycle
}
pi_left() {
echo 2000000 > $pwm0/duty_cycle
echo 2000000 > $pwm1/duty_cycle
}
pi_enable
while true; do
pi_forward
sleep 1
pi_backward
sleep 1
pi_left
sleep 1
pi_right
sleep 1
pi_stop
sleep 1
done
Save it to rover-test.sh
then run it with
chmod +x rover-test.sh
sudo ./rover-test.sh
Press ctrl+c
to stop it.
# Conclusion
You now have the start of a robotics platform, you can download a reconfigured image here so that all you need to do is give it the wireless credentials for your network. This is only the foundation for a larger project: build a web controlled rover but is necessary to get out the way before solving more intreating problems. In my next few posts I hope to look at writing a rust webserver to run on the pi that is able to control the rover then getting it to interact with the environment in some way before looking into using the pi camera for vision recognition.