MJRoBot (Marcelo Rovai)
Published © GPL3+

IoT: Raspberry Pi Robot with Video Streamer and Pan/Tilt

Here we will learn how to streaming video using a PiCam and also remote controlling its position (Pan/Tilt), using servo motors.

IntermediateFull instructions provided24 hours12,481
IoT: Raspberry Pi Robot with Video Streamer and Pan/Tilt

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Raspberry Pi PiCam
×1
Micro Servo Motors
×1
car kit
×1

Story

Read more

Schematics

RPi WiFi controlled Robot

Code

Code snippet #1

Plain text
<xmp>

<iframe src="http://Your IP Adress:9000/javascript_simple.html" frameborder="0" align="middle" width="640" height="480" align="middle" scrolling="no">$


</xmp>

Code snippet #2

Plain text
<xmp>

<html>
<head>
</head>

<style>
body {background-color: lightyellow}
h1 {color:blue}


</style>

<body>

<div style="text-align:center">

<h1> MJRoBot RPi Web Robot Control   <img style="height: 100px"src="/images/robot52.png"> </h1>
<br><br>

<iframe src="http://10.0.1.31:9000/javascript_simple.html" frameborder="0" align="middle" width="640" height="480" align="middle" scrolling="no">$


</body>
</html>

</xmp>

Code snippet #3

Plain text
Board model:                     2
GPIO configuration:            P1 (40 pins)
Using hardware:                PWM
Using DMA channel:              14
Idle timeout:             Disabled
Number of servos:                8
Servo cycle time:            20000us
Pulse increment step size:      10us
Minimum width value:            50 (500us)
Maximum width value:           250 (2500us)
Output levels:              Normal

Using P1 pins:               7,11,12,13,15,16,18,22

Servo mapping:
     0 on P1-7           GPIO-4
     1 on P1-11          GPIO-17
     2 on P1-12          GPIO-18
     3 on P1-13          GPIO-27
     4 on P1-15          GPIO-22
     5 on P1-16          GPIO-23
     6 on P1-18          GPIO-24
     7 on P1-22          GPIO-25

Code snippet #4

Plain text
        ;;        ;;#!/bin/sh
### BEGIN INIT INFO
# Provides:          servoblaster
# Required-Start:    hostname $local_fs
# Required-Stop:
# Should-Start:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/stop servod.
# Description:       This script starts/stops servod.
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
. /lib/init/vars.sh

OPTS="--idle-timeout=2000"

STATUSFILE="/tmp/servoblaster-status"

if [ $( id -u ) != 0 ]; then
        echo "ERROR: Must be run as root"
        exit 1
fi

case "$1" in
  start)
        /usr/local/sbin/servod --p1pins=11,16 $OPTS >/dev/null<br>        ;;
  restart|reload|force-reload)
        killall servod
        /usr/local/sbin/servod $OPTS >/dev/null
        ;;
  stop)
        killall servod
        ;;
  status)
        if [ ! -e /dev/servoblaster ]; then
                echo "ERROR: /dev/servoblaster does not exist"
                exit 2
        fi
        rm -f $STATUSFILE
        echo "status $STATUSFILE" > /dev/servoblaster
        sleep 0.2
        if [ ! -e $STATUSFILE ]; then
                echo "ERROR: servod not responding"
                exit 3
        elif grep -q "^OK" $STATUSFILE; then
                echo "OK"
                exit 0
        elif grep "^ERROR:" $STATUSFILE; then
                exit 4
        else
                echo "ERROR: No status from servod"
                exit 5
        fi
        ;;
  *)
        echo "Usage: servoblaster [start|stop|status]" >&2
        exit 6
        ;;
esac

exit 0

Code snippet #5

Plain text
<xmp>
button {
        color: blue;
        background:lightgrey;
        border: 1px solid #000;
        border-radius: 8px;
        position: center;
}
         ...

<button style="height: 50px; width: 100px; font-size: 25px" onclick="centertilt()">0</button>
         ...
</xmp>

Code snippet #6

Plain text
<xmp>
function centertilt()
{
    xmlhttp.open("GET","cgi-bin/centertilt.cgi",true);
    xmlhttp.send();
}</xmp>

Code snippet #7

Plain text
<xmp>
<html>
<head>
</head>

<style>
body {background-color: lightyellow}
h1 {color:blue}

button {
        color: blue;
        background:lightgrey;
        border: 1px solid #000;
        border-radius: 8px;
        position: center;
}

</style>

<body>

<div style="text-align:center">

<h1> MJRoBot RPi Web Robot Control   <img style="height: 100px"src="/images/robot52.png"> </h1>
<br><br>

<iframe src="http://10.0.1.31:9000/javascript_simple.html" frameborder="0" align="middle" width="640" heigh$
<br><br>

<span style="display:inline-block;padding:5px;border:1px solid #fc0; font-size: 140%;font-weight: bold;">

        <p>Camera Tilt Angle</p>
        <img hspace="18" style="padding-left: 5px">
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="downtilt()">-D</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="downcentertilt()">D</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="centertilt()">0</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="upcentertilt()">U</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="uptilt()">U+</button>
        <img hspace="18" style="padding-left: 5px">
        <br><br>
        <p>Camera Pan Position</p>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="leftpan()">+L</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="leftCenterPan()">L</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="centerpan()">0</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="rightCenterPan()">R</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="rightpan()">R+</button>
        <p></p>
</span>

<script>
var xmlhttp;
xmlhttp=new XMLHttpRequest();


function downtilt()
{
    xmlhttp.open("GET","cgi-bin/downtilt.cgi",true);
    xmlhttp.send();
}
function downcentertilt()
{
    xmlhttp.open("GET","cgi-bin/downcentertilt.cgi",true);
    xmlhttp.send();
}function centertilt()
{
    xmlhttp.open("GET","cgi-bin/centertilt.cgi",true);
    xmlhttp.send();
}
function upcentertilt()
{
    xmlhttp.open("GET","cgi-bin/upcentertilt.cgi",true);
    xmlhttp.send();
}
function uptilt()
{
    xmlhttp.open("GET","cgi-bin/uptilt.cgi",true);
    xmlhttp.send();
}
function leftpan()
{
    xmlhttp.open("GET","cgi-bin/leftpan.cgi",true);
    xmlhttp.send();
}
function leftCenterPan()
{
    xmlhttp.open("GET","cgi-bin/leftCenterPan.cgi",true);
    xmlhttp.send();
}
function centerpan()
{
    xmlhttp.open("GET","cgi-bin/centerpan.cgi",true);
    xmlhttp.send();
}function rightCenterPan()
{
    xmlhttp.open("GET","cgi-bin/rightCenterPan.cgi",true);
    xmlhttp.send();
}
function rightpan()
{
    xmlhttp.open("GET","cgi-bin/rightpan.cgi",true);
    xmlhttp.send();
}

</script>

</body>
</html>
</xmp>

Code snippet #8

Plain text
<xmp>
<html>
<head>
</head>

<style>
body {background-color: lightyellow}
h1 {color:blue}

button {
	color: blue;
	background:lightgrey;
	border: 1px solid #000;
	border-radius: 8px;
	position: center;
}

</style>

<body>

<div style="text-align:center">

<h1> MJRoBot RPi Web Robot Control   <img style="height: 100px"src="/images/robot52.png"> </h1>
<br><br>

<iframe src="http://10.0.1.31:9000/javascript_simple.html" frameborder="0" align="middle" width="640" height="480" align="middle" scrolling="no"></iframe>
<br><br>

<button style="height: 50px; width: 100px" onclick="lighton()"><img style="height: 40px"src="/images/lighton.png"></button>
<img hspace="20" style="padding-left: 200px">
<button style="height: 50px; width: 100px" onclick="lightoff()"><img style="height: 35px"src="/images/lightoff.png"></button>
<br><br>

<span style="display:inline-block;padding:5px;border:1px solid #fc0; font-size: 140%;font-weight: bold;">
	<br>
	<button style="height: 75px; width: 75px" onclick="forward()"><img style="height: 65px"src="/images/forward.png"></button>
	<br><br><br><br>
	<img hspace="10" style="padding-left: 5px">
	<button style="height: 75px; width: 75px" onclick="left()"><img style="height: 65px"src="/images/left.png"></button>
	<img hspace="20" style="padding-left: 10px">
	<button style="height: 75px; width: 75px" onclick="stop()"><img style="height: 63px"src="/images/stop.png"></button>
	<img hspace="20" style="padding-left: 10px">
	<button style="height: 75px; width: 75px" onclick="right()"><img style="height: 65px"src="/images/right.png"></button>
	<img hspace="10" style="padding-left: 5px">
	<br><br><br><br>
	<button style="height: 75px; width: 75px" onclick="reverse()"><img style="height: 65px"src="/images/reverse.png"></button>
	<br><br><br>

	<p>Motor speed control</p>
	<img hspace="30" style="padding-left: 5px">
	<button style="height: 50px; width: 50px; font-size: 18px" onclick="nospeed()">0</button>
	<img hspace="30" style="padding-left: 20px">
	<button style="height: 50px; width: 50px; font-size: 18px" onclick="lowspeed()">--</button>
	<img hspace="30" style="padding-left: 20px">
	<button style="height: 50px; width: 50px; font-size: 18px" onclick="regularspeed()">==</button>
	<img hspace="30" style="padding-left: 20px">
	<button style="height: 50px; width: 50px; font-size: 18px" onclick="highspeed()">++</button>
	<img hspace="30" style="padding-left: 5px">
	<br><br>
</span>
<br><br>

<span style="display:inline-block;padding:5px;border:1px solid #fc0; font-size: 140%;font-weight: bold;">
             
        <p>Camera Tilt Angle</p>
        <img hspace="18" style="padding-left: 5px">
	<button style="height: 50px; width: 100px; font-size: 25px" onclick="downtilt()">-D</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="downcentertilt()">D</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="centertilt()">0</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="upcentertilt()">U</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="uptilt()">U+</button>
        <img hspace="18" style="padding-left: 5px">
	<br><br>
        <p>Camera Pan Position</p>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="leftpan()">+L</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="leftCenterPan()">L</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="centerpan()">0</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="rightCenterPan()">R</button>
        <button style="height: 50px; width: 100px; font-size: 25px" onclick="rightpan()">R+</button>
        <p></p>
</span>

<script>
var xmlhttp;
xmlhttp=new XMLHttpRequest();

function lighton()
    {
        xmlhttp.open("GET","cgi-bin/lighton.cgi",true);
        xmlhttp.send();
    }
function lightoff()
    {
        xmlhttp.open("GET","cgi-bin/lightoff.cgi",true);
        xmlhttp.send();
    }
function forward()
{
	xmlhttp.open("GET","cgi-bin/forward.cgi",true);
	xmlhttp.send();
}
function stop()
{
	xmlhttp.open("GET","cgi-bin/stop.cgi",true);
	xmlhttp.send();
}
function left()
{
	xmlhttp.open("GET","cgi-bin/left.cgi",true);
	xmlhttp.send();
}
function right()
{
	xmlhttp.open("GET","cgi-bin/right.cgi",true);
	xmlhttp.send();
}
function reverse()
{
	xmlhttp.open("GET","cgi-bin/reverse.cgi",true);
	xmlhttp.send();
}

function lowspeed()
{
	xmlhttp.open("GET","cgi-bin/lowspeed.cgi",true);
	xmlhttp.send();
}
function regularspeed()
{
	xmlhttp.open("GET","cgi-bin/regularspeed.cgi",true);
	xmlhttp.send();
}
function highspeed()
{
	xmlhttp.open("GET","cgi-bin/highspeed.cgi",true);
	xmlhttp.send();
}
function nospeed()
{
	xmlhttp.open("GET","cgi-bin/nospeed.cgi",true);
	xmlhttp.send();
}


function downtilt()
{
    xmlhttp.open("GET","cgi-bin/downtilt.cgi",true);
    xmlhttp.send();
}
function downcentertilt()
{
    xmlhttp.open("GET","cgi-bin/downcentertilt.cgi",true);
    xmlhttp.send();
}
function centertilt()
{
    xmlhttp.open("GET","cgi-bin/centertilt.cgi",true);
    xmlhttp.send();
}
function upcentertilt()
{
    xmlhttp.open("GET","cgi-bin/upcentertilt.cgi",true);
    xmlhttp.send();
}
function uptilt()
{
    xmlhttp.open("GET","cgi-bin/uptilt.cgi",true);
    xmlhttp.send();
}
function leftpan()
{
    xmlhttp.open("GET","cgi-bin/leftpan.cgi",true);
    xmlhttp.send();
}
function leftCenterPan()
{
    xmlhttp.open("GET","cgi-bin/leftCenterPan.cgi",true);
    xmlhttp.send();
}
function centerpan()
{
    xmlhttp.open("GET","cgi-bin/centerpan.cgi",true);
    xmlhttp.send();
}
function rightCenterPan()
{
    xmlhttp.open("GET","cgi-bin/rightCenterPan.cgi",true);
    xmlhttp.send();
}
function rightpan()
{
    xmlhttp.open("GET","cgi-bin/rightpan.cgi",true);
    xmlhttp.send();
        }
        
</script>

</body>
</html>
</xmp>

Github

https://github.com/jacksonliam/mjpg-streamer.git

Github

https://github.com/richardghirst/PiBits

Github

https://github.com/Mjrovai/MJRoBot-Web-RPi-Robot

Credits

MJRoBot (Marcelo Rovai)

MJRoBot (Marcelo Rovai)

60 projects • 913 followers
Professor, Engineer, MBA, Master in Data Science. Writes about Electronics with a focus on Physical Computing, IoT, ML, TinyML and Robotics.

Comments