
Hardware | |||
---|---|---|---|
1 | CM3+/LITE | $ 25 | |
DA-70814 | |||
1 | 0603ZD105KAT2A | $ 0.19 | |
1 | LV8746V-TLM-E | $ 6.73 |
Wouldn't it be cool to have a Raspberry Pi robot with a camera on board? For this project, I created a Raspberry Pi rover robot that can be controlled using a smartphone with video streaming! Sound interesting? Here's how:

Raspberry Pi Rover Robot Concept
A rover is basically a remote-controlled vehicle used to access areas that are inaccessible by humans. NASA's Curiosity is a well-known rover robot. I decided to build my own simple rover using a Raspberry Pi board and a web camera. The USB webcam acts as the controller's eyes, which is typical of rovers (they are not autonomous). We can then control the movements of the robot using buttons on a locally hosted web page where the same video stream from the camera is embedded. I made the robot control more secure by making the Raspberry Pi a Wi-Fi access point. This means only users that know the Wi-Fi ID and password of the robot can view the video stream and control it.Raspberry Pi Rover Hardware Assembly
I attached the gearbox and wheels assembly to the edge of the first platform and the ball wheel to the other edge:
On that same platform, I attached the battery pack using a velcro strap. I mounted the motor driver here as well:

Here's the motor driver connection (not seen in the schematic: a 1uF capacitor from VCC to GND):

Using plastic posts, I attached the second platform and then attached the Raspberry Pi board (with the Wi-Fi dongle plugged).

Here's the robot with the USB webcam attached:

Configuring the Software
This is one of those projects where the software configuration is much more difficult than the hardware.Warning: this stuff might be too complex for beginners.
Installing mjpg-streamer and JPEG Library
First, access your Raspberry Pi via SSH. Then paste the following commands:sudo apt-get update sudo apt-get upgrade
sudo apt-get install cmake libjpeg8-dev
git clone https://github.com/jacksonliam/mjpg-streamer.git
Go to the extracted mjpg-streamer library then run make:
cd mjpg-streamer/mjpg-streamer/mjpg-streamer-experimental
make
sudo make install
Go one folder above then copy the mjpg-streamer folder to /usr/local/bin. Do the same for the plugins output_http.so and input_uvc.so.
sudo cp mjpg_streamer /usr/local/bin sudo cp output_http.so input_uvc.so /usr/local/lib/
This enables us to stream the video captured by the webcam. But where can we view it? We need a web page hosted by a server for that. To create a server for the Raspberry Pi, download Apache:
sudo apt-get install apache2 -y
This will create a webpage that can be accessible via a browser. To test the video stream:
export LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i "input_uvc.so -f 10 -r 320x240 -d /dev/video0 -y" -o "output_http.so -w /var/www/html -p 8080"
Open a browser from a computer or smartphone with the same network as your RPi. To view the stream, just go to your Pi's address. For example, my pi is at http://192.168.1.6. I was able to see the video stream on that address.
Configuring the RPi as an Access Point
Now we want to control the robot only when we are connected to it and not anyone else within the network. To do that, we want the RPi to be the access point.
The first step is to give the RPi a static IP address. To do that, edit /etc/dhcpcd.conf and add the following lines:
#static ip address for eth0 interface eth0 static ip_address=192.168.1.6/24 static routers=192.168.1.1 static domain_name_servers=192.168.1.1
#static ip address for wlan0 interface wlan0 static ip_address=192.168.0.1/24
This will give the RPi a static IP address of 192.168.1.6 when accessed from the ethernet port (for SSH) and 192.168.0.1 from Wi-Fi (which we'll be our access point to control the robot).
Next, we need to install a DHCP server.
sudo apt-get install isc-dhcp-server
Then edit /etc/dhcp/dhcpd.conf:
sudo nano /etc/dhcp/dhcdp.conf
Comment all lines with "option domain-name" on it by adding "#", for example:
#option domain-name "example.org"; #option domain-name-servers ns1.example.org, ns2.example.org;
Also, remove the "#" sign in front of the "authoritative;" statement like this:
# If this DHCP server is the official DHCP server for the local # network, the authoritative directive should be uncommented. authoritative;
Then add the following lines at the bottom:
subnet 192.168.0.0 netmask 255.255.255.0 { range 192.168.0.21 192.168.0.50; option broadcast-address 192.168.0.255; option domain-name "local"; option domain-name-servers 8.8.8.8, 8.8.4.4; }
Exit from nano using CTRL+X and choose "Y".
You may need to restart the DHCP server:
sudo service isc-dhcp-server restart
Next, we need to install the access point daemon:
sudo apt-get install hostapd
Edit the config file of hostapd:
sudo nano /etc/hostapd/hostapd.conf
And add the following lines at the bottom of the file:
interface=wlan0 driver=nl80211 ssid=rover-wifi hw_mode=g channel=1 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=12345678 wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP
Again, close nano and save the file.
This will create an SSID rover-wifi which we can access using the passcode 12345678.
Lastly, we need to tell hostapd the default configuration file. To do that, edit hostapd:
sudo nano /etc/default/hostapd
And remove the # infront of DAEMON_CONF = "/etc/hostapd/hostapd.conf"
Close nano and save the file.
Creating Control Scripts
Alright, now that we've got the camera stream going and made the RPi an access point, we need to have some sort of control mechanism for the robot. We can edit the index.html file where we embed the video stream and add buttons to it to move or stop the robot.
Create a folder in the home directory:
mkdir rover
Next, create a shell script named init.sh with these contents:
#!/bin/sh echo 17 > /sys/class/gpio/export echo 27 > /sys/class/gpio/export echo 22 > /sys/class/gpio/export echo 23 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio17/direction echo out > /sys/class/gpio/gpio27/direction echo out > /sys/class/gpio/gpio22/direction echo out > /sys/class/gpio/gpio23/direction
These will reserve the pins 17, 27, 22, and 23 for motor control.
Then we need four scripts to make the robot go forward, turn left, turn right, and stop:
fwd.sh:
#!/bin/sh echo 1 > /sys/class/gpio/gpio17/value echo 0 > /sys/class/gpio/gpio27/value echo 1 > /sys/class/gpio/gpio22/value echo 0 > /sys/class/gpio/gpio23/value
rwd.sh:
#!/bin/sh echo 0 > /sys/class/gpio/gpio17/value echo 1 > /sys/class/gpio/gpio27/value echo 0 > /sys/class/gpio/gpio22/value echo 1 > /sys/class/gpio/gpio23/value
ll.sh:
#!/bin/sh echo 0 > /sys/class/gpio/gpio17/value echo 1 > /sys/class/gpio/gpio27/value echo 1 > /sys/class/gpio/gpio22/value echo 0 > /sys/class/gpio/gpio23/value
rr.sh:
#!/bin/sh echo 1 > /sys/class/gpio/gpio17/value echo 0 > /sys/class/gpio/gpio27/value echo 0 > /sys/class/gpio/gpio22/value echo 1 > /sys/class/gpio/gpio23/value
stop.sh:
#!/bin/sh echo 0 > /sys/class/gpio/gpio17/value echo 0 > /sys/class/gpio/gpio27/value echo 0 > /sys/class/gpio/gpio22/value echo 0 > /sys/class/gpio/gpio23/value
Editing the Web Page
We're not done yet! Delete the index.html page where the video was streamed earlier:sudo rm /var/www/html/index.htmlThen create a new index.html file:
sudo nano /var/www/html/index.htmlWith this as content:
<html> <head> <meta charset="UTF-8"> <title>RaspberryPi Camera Robot</title> <script type="text/javascript"> function button(value) { var request = false; if(window.XMLHttpRequest){ request = new XMLHttpRequest(); }else if(window.ActiveXObject){ try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { request = new ActiveXObject("Msxml.XMLHTTP"); } } //XMLHttpRequest failed if(!request){ alert("XMLHttpRequest failed..."); return false; } //query var send = 'code=' + value; request.open('POST','/rover.php',true); //HTML header request.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); request.setRequestHeader('Content-Length',send.length); request.setRequestHeader('Connection','close'); request.send(send); } </script> </head> <body> <img src="http://192.168.0.1:8080/?action=stream" /> <br> <input type="button" value="right" onClick="button('right')"> <input type="button" value="front" onClick="button('front');"> <input type="button" value="back" onClick="button('back');"> <input type="button" value="left" onClick="button('left');"> <input type="button" value="stop" onClick="button('stop');"> </body> </html>
Close nano and save the file.
We also need a rover.php file that will allow us to issue shell commands from the web page:
<?php $code = $_POST['code']; switch($code){ case "right": system("sudo /home/pi/rover/rr.sh"); break; case "front": system("sudo /home/pi/rover/fwd.sh"); break; case "back": system("sudo /home/pi/rover/rwd.sh"); break; case "left": system("sudo /home/pi/rover/ll.sh"); break; case "stop": system("sudo /home/pi/rover/stop.sh"); break; default: } ?>
Writing the Stream Script
We need to make a script for the video stream. On the same folder rover we created, create a stream.sh script:sudo nano stream.sh
Paste this:
#!/bin/sh PORT="8080" ID="rover" PW="1234" SIZE="320x240" FRAMERATE="10" export LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i "input_uvc.so -f $FRAMERATE -r $SIZE -d /dev/video0 -y" -o "output_http.so -w /var/www/html -p $PORT"
And save it.
Making the Scripts Load on Boot
Finally, to make these scripts run as the Raspberry Pi is opened, edit rc.local.sudo nano /etc/rc.local
Add the following lines below the file:
#RPi Rover sleep 2 /home/pi/rover/stream.sh & /home/pi/rover/init.sh
This will run stream.sh and init.sh when the RPi boots up.
All the needed shell scripts, as well as the webpages, are found on my Raspberry Pi rover robot repository. That's it for the software part!
Finished Robot
To start controlling the robot, use a smartphone or laptop and connect to the robot Wi-Fi access point rover-wifi with password 12345678.
Use your favorite browser and open the page http://192.168.0.1. You should see something like this:
Press the buttons and watch the robot move!
Here's the Raspberry Pi rover robot in action: