Pan-Tilt Hat with Raspberry Pi - Quick Start Guide

New tutorial Pan-Tilt Hat with Raspberry Pi - Quick Start Guide is complete and all polished up.

Setting up a Pan and Tilt system has never been easier with absolutely no soldering required! The Pimironi Picade Pan-Tilt Hat lets you mount and control a pan-tilt module right on top of your Raspberry Pi palm-sized computer meaning you can always keep the action in frame. The Hat’s onboard microcontroller and cleaver packages let you independently drive the two servos (pan and tilt) very simply, as well as powering up to 24 regular LED or NeoPixel RGB LEDs . There’s also a handy slot through which you can route the servo, LED, and camera cables elegantly through the PCB. Ideal for a mini-CCTV system, or to mount a set of eyes on it to make a friendly robot out of it, this set of horizontal and vertical motion servos will give you movement with a minimum of fuss and is ripe for some creativity.

(And video guide on how to do Face tracking with this Pan-Tilt Hat coming next week!)

Read more


Hi Tim,

Thank you for the great tutorials and example codes. I used your tutorial to assemble my Pimoroni Pan Tilt HAT, and then downloaded your It came up cleanly, but crashes when the edges of the pan/tilt ranges. I put in fixes to the if-tests on the range and fixed the problem. Also put in a few comments here and there. Do you want the modified code? If so, where should I send it?

Vince Stanford


That sounds awesome mate! Very keen to check out your code. I definitely appreciate any improvements to any tutorial scripts :blush:. So long as it is not too much longer than the original you can chuck 3 backticks ( ` ) on either side of the code. The forum should then stick a scrollbar on the code so that it won’t take up the whole thread.

I’ll test it out here then, so long as you’re happy to allow it (and naturally be acknowledged in the code), I’ll make it the main script in the guide.

Kind regards,


Hi Tim,

Absolutely happy to offer the minor bug fixes as unrestricted open source. Thanks for posting it in the first place. Next I am going on to your tutorial on finding faces in the camera images. I’ll let you know if I find anything. I really enjoy your YouTube vids and tutorial docs. All the best.

Vince Stanford

(Attachment is missing)


Hi Vincent,

If you’ve posted here via email, the attachments you post won’t be included (a security thing I believe)

As Tim has said, posting them directly to the forum with backticks (or attaching them on the forum site) would be the way to go.



Here is the code with touch-ups:

# Name:
# Purpose: Control a Pimoroni two degree of freedom Pan-Tilt Hat for the
# Raspberry Pi.  It uses the curses package to catch presses of the left/right
# and up/down arrow key presses and pan and tilt the head in response. 
# Language: Python 3
# Authors:  Code was posted by Core Electronics (Tim) here:
# Updates and bug fixes
#  Dec 9, 2021  Fixes to keep the pan/tilt code from crashing if the
#  arrow keys are used to go outside the +/- 90 degree ranges on pan/tilt.
#  Dec 12, 2021 Minor formatting changes and variable names for readability.
#must be run from Pi's terminal!
#use code "python" after you cd into the correct folder!

#importing required libraries
import curses
import os
import time
import picamera
import pantilthat

# Initialize camera
camera = picamera.PiCamera()
camera.resolution = (1024, 768)
camera.start_preview(fullscreen=False, window = (100,20,640,480))

# flipping the camera for so its not upside down
camera.vflip = True
camera.hflip = True

# Set up key mappings and curses for arrow key responses
screen = curses.initscr() # get the curses screen window
curses.noecho()           # turn off input echoing
curses.cbreak()           # respond to keys immediately (don't wait for enter)
screen.keypad(True)       # map arrow keys to special values

# initialize pan and tilt positions and process increments driven by arrow keys
# set start up serrvo positions
a = 0.0
b = 0.0
# set arrow key delta
picNum = 1  # Initialize picture number

# Process active key presses:
# -- Letter p will take a picture and store file name image[picNum].jpg,
#     where [number] increments over a picture taking session.
# -- Arrow keys will control the Pan Tilt Camera (deltaPan/deltaTilt Degree angles)
# -- Letter q will quit the application, 
    while True:
        char = screen.getch()
        if char == ord('q'):
            #if q is pressed quit
        if char == ord('p'):
            #if p is pressed take a photo!
            camera.capture('image%s.jpg' % picNum)
            picNum = picNum + 1
            screen.addstr(0, 0, 'picture taken! ')
        elif char == curses.KEY_RIGHT:
            screen.addstr(0, 0, 'right ')
            if (b - deltaTilt ) > -90:
                b = b - deltaTilt
        elif char == curses.KEY_LEFT:
            screen.addstr(0, 0, 'left ')
            if (b + deltaTilt) < 90:
                b = b + deltaTilt
        elif char == curses.KEY_DOWN:
            screen.addstr(0, 0, 'down ')
            if (a + deltaPan) < 90:
                a = a + deltaPan
        elif char == curses.KEY_UP:
            screen.addstr(0, 0, 'up ')
            if (a - deltaPan) > -90:    
                a = a - deltaPan
    # shut down cleanly
    curses.nocbreak(); screen.keypad(0); curses.echo()

Hey Vince,

Absolutely brilliant script :slight_smile: just tested it out then! Have updated the guide page and download section with this new script. Very glad you dig the tutorials, hope your adventures with the next ones are just as successful. If you run into any issues just reach out, I’m always more than happy to help.

Kindest regards,


Dude great write up. Was exactly what I had been looking for. You really do need to get credit card transactions working off you site for purchases as PayPal is crap and I reside in NZ.

1 Like

Maybe outside this guide (which works great - thank you) but I also tried connecting an 8 LED Neopixel Strip (not Adafruit) to the pimoroni hat as described and got weird results with the addressing. It would only respond to indexes 0-5 which lit all 8 LEDs in varying adjacent combinations and colours. Same LED strip works perfectly connected to the RPi directly (5v and GPIO18) as per your 2812B LED guide. Doesn’t seem to be a voltage issue as the pimoroni pantilt hat schematic indicates the LED connection is 5v!? Any idea why this doesn’t work as expected??

1 Like

Hey Roger,

Seems a bit weird to me too. Double-check you’re using the same kind of syntax they demonstrate here - pantilt-hat/ at master · pimoroni/pantilt-hat · GitHub.

When referring to WS2812B LEDs they use this kind of syntax in scripts | pantilthat.set_pixel(0, 255, 0, 255) |. The arguments are index, from 0 to 23, followed by the amount of red, green, and blue which range from 0 to 255. Then to make them illuminate you add the line | |

Come pop through your script and a photo of your set up and I’ll best be able to help if that doesn’t sort you out.

Kind regards,

Hi Tim
Oops! I just had another look at this and I found that in my code initialisation I had incorrectly set the light type to an SK66812 option with
… after correctly setting the light mode as WS2812 for my LED strip in the previous line. Everything else was fine.
As soon as I changed the light type to GRB it all runs as expected. I should have picked that up earlier!

Roger W

From “Tim via Core Electronics Forum” <>
Date 8/02/2023 12:01:58 pm
Subject [Core Electronics Forum] [Guides] Pan-Tilt Hat with Raspberry Pi - Quick Start Guide

1 Like