Pan Tilt Hat as a Robot CCTV

A Robot With A Camera ? That You Control via The Internet ?

This is actually something that was completed a short time ago but I’ve only just got around to writing it up.

The idea was to use a Pan / Tilt HAT and a camera to make a home CCTV system, make it accessible / controllable from the Internet and contain it in something unusual looking; something that I wouldn’t mind having on a shelf.

I forgot to capture the initial unassembled pieces so here are:

Already partially assembled

Not shown are:

Added some extra long nylon bolts so that the Pi can be mounted underneath the HAT.

The side view, now fully assembled.

It’s quite a squeeze but it all fits.

The fully assembled top view with the clearly visible NeoPixel Stick.

As the whole thing is to be encased and impossible to adjust or repair, I made sure that the connectors wouldn’t budge.

Did I mention hot glue? Here again making sure that the nylon bolts on the camera module stay in place.

The whole unit in its final resting place, standing tall!

Bit of a close up of the Pan / Tilt unit and camera.

A big thank-you to ScrewedSculpts for his work on the robot, I just did the nerdy bits.

Making it Move and Operating Remotely

There are quite a few guides on how to do this, and I found some of the a bit confusing.

After a few bungled attempts, I distilled them into a few simple commands.

The obvious starting place is to install the Pimoroni libraries:

curl | bash

And check that it’s working:

cd /home/foo/Pimoroni/pantilthat/examples

The RPi-Cam-Web-Interface is also needed:

NOTE - Enabling the Camera

Bullseye OS has replaced the camera stack which stopped the raspimjpeg working.

Legacy camera support should be enabled.

Do this within raspi-config under Interface.

If this shows just “Enable camera” then update raspi-config itself from its menu item.

The interface option should now show enable Legacy camera support.

The Pi will reboot.

The script will detect a Bullseye OS, set the right PHP version and create a missing directory needed by this software to run.

Clone the code from github and enable and run the install script with the following:

git clone
cd RPi_Cam_Web_Interface

Configure accordingly with the cam folder at ‘/html/wherever-you-like’.

OK & Wait for ‘Start’.

Locally, at ‘http://Your-Pi-IP-Address/html/wherever-you-like’ there should be an image.

Also on the Pi, in a browser, at URL ‘’ there should be an image.

Configure the Pan / Tilt HAT for RPi-Cam-Web-Interface

Firstly, rename pipan_off to enable the browser direction arrows (needs a browser refresh):

cd /var/www/html/wherever-you-like
sudo mv  pipan_off pipan_on

Add a FIFO pipe:

cd /var/www/html/wherever-you-like
sudo mknod FIFO_pipan p
sudo chmod 666 FIFO_pipan

Create a on the Pi:


The one I used came from this post:

The important line is this one:

pipein = open("/var/www/html/wherever-you-like/FIFO_pipan", 'r')

Save it somewhere sensible (mine went in my Home folder).

Check that it’s working:

cd /home/foo

Edit /etc/rc.local and add the following line above the exit-command:

(Change the path to the directory where you saved the pipan-file).

sudo nano /etc/rc.local
python /home/foo/ &

If you see this, then put the above line ^^ above it.


It may need a reboot but the Pan / Tilt HAT should now be operable via a browser.

Connecting to the Outside World

As the ‘RPi-Cam-Web-Interface’ comes with a web server, it can serve requests from the internet.

On my router port 80 traffic goes to a web server where it determines where to send that request internally.

An easier route would be to direct port 80* traffic to the Pi where all of the above magic takes place

If it is port 80 that was chosen to serve requests when installing ‘RPi-Cam-Web-Interface’.

NeoPixel Stick Menu

I added a bash menu to control the lights.

At the moment the options link to the Pimoroni examples, all apart from the ‘Sleep’ which turns the pixels off and returns the head back to its starting position.

The menu:


BACKTITLE="robocam Neopixel Lights"
TITLE="Neopixel Stick Examples"
MENU="Choose one of the following options:"

OPTIONS=(1 "360 White"
         2 "360 Rainbow"
         3 "Smooth Sweep"
         4 "Staggered Sweep"
         5 "Sleep")

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

case $CHOICE in
            python ~/Pimoroni/pantilthat/examples/

The ‘Sleep’ bit:

#!/usr/bin/env python

import pantilthat


r, g, b, w = 0, 0, 0, 0

while True:
    for x in range(18):
        pantilthat.set_pixel(x, r, g, b, w)

    p = 0.00
    t = 0.00


I hope that the above helps anyone looking to do something similar.

If anyone finds an error please let me know and I’ll amend it.


These are both excellent reading and flesh out the above a bit more:

1 Like

Nice project, and nice write up. I have two Pan Tilt setups here. Pi 3A+'s, they match up nicely size wise with the Pan Tilt Hat. And I don’t need the extra jacks on a 3B as they run headless. I ditched the headers all together for the servo’s. I removed them from the Pan Tilt hat, shortened (cut) the servo cables and soldered them right to the hat. Pibow cases on the 3A+'s with the tall metal stand offs for the hat. No light bar on mine. They are looking out windows and it just reflects back and messes up the image.
Motion Eye OS here, I setup action buttons for movement. I only ever watch them over my LAN via a web browser so I didn’t have to do anything fancy in that respect. Motion Eye OS does that quite nicely. I just enter the cameras local LAN IP into my web browser.

Thanks Kerry,

You are right, the Pi3A+ does sit perfectly on the HAT and once bolted together feels very secure.

I guess I could have shortened the servo cables and attached them to the HAT but I surmised that doing so could have introduced a point of weakness.

I wanted the finished unit to be as ‘bomb-proof’ as possible so that the chap building the robot didn’t have to stress about breaking anything (hence the copious amounts of hot glue).

I have to admit that I wasn’t aware of Motion Eye OS. It looks quite a bit simpler than the route I took!

I have another camera set up, maybe one wet weekend I’ll have a look at it and compare the two.

Headless with LAN access (and Port Forwarding to the Pi via Apache) is all that I am looking for too.



Motion Eye OS can be a bit of a pain to setup. On the first boot up it looks for an Ethernet connection and just endlessly reboots if it doesn’t find one. Adding a wpa_supplicant file can get around that though so it boots up to WIFI. I then log in and set a static IP. If you connect a monitor it will show you what IP address it gets. That makes logging in the first time easier. I only ever connect a monitor for the first boot up. And if I’m lazy I just plug in a USB Hub I have that has an ethernet jack onboard. I have 6 or so cameras setup with Motion Eye OS. Some I move around a bit. 3A+'s, 3B+'s and a 4B. I found a Pi Zero just wasn’t up to streaming a good reliable video feed.


I always use a ‘wpa_supplicant’ file for first boot, along with an empty ssh file (Raspian didn’t have ssh active back in the olden days).

Then I use the ‘fing’ app on my Android phone to get the IP (it’s free and useful to see whats connected to the network).

Then, like you I set fixed IP (along with hostname and ssh key security).

I’m happy with headless and don’t even own a monitor (HDMI to the TV at a push).



The face tracking might be fun to try on that? Depending on how hard it is to get at the SD Card.
MicroSD extension cable - Pimoroni

Building a Raspberry Pi Pan/Tilt Face Tracker (

My Pi400 has my one spare monitor on it. I also have two Pi’s with the official 7 inch touch screens on them. One is in a SmartiPi case and is nice and portable. The other is an open beam frame setup with a large solderless breadboard attached. I do some prototyping on it now and again. It’s also easily moved from one spot to another. Just about everything else is headless.