Pan and Tilt control for the Raspberry Pi Camera

I was fortunate enough to get access to a prototype of Pi-Pan from www.mindsensors.com during their kickstarter.
The kickstarter has finished and they reached their goal.   However they will be selling Pi-Pan from www.mindsensors.com at a future date.


Pi-Pan provides Pan and tilt movements for your Raspberry Pi Camera.
Pi-Pan can pan 180 degrees (from left to right) and tilt 110 degrees (top to bottom).

Pi-Pan comes with two servos, a controller board, screws, a mount and instructions.  It also comes with some python code that shows how the device can be operated.

(The controller board in the image below is a prototype and the production board will be a lot smaller.)

pipan-opt pipan2-opt pipanparts-opt

 

Pi-pan is well made and and feels solid once assembled, which only takes 5 minutes. There is also a mount which can be used to mount Pi-Pan on a case or other objects. I mounted mine directly on the Pi-Pan controller board for now.

PWM is required to drive the servos and the sample code uses Servoblaster which works very well. I also used Servoblaster in my code below.

OpenElectronics also has a light module (Pi-Light) which can be mounted on the front of the Pi camera to improve lighting and there is also a case in the works.

 

PiPan Case PiPan Light

The code below is what I used to control Pi-pan

/*
##########################################################################################
A program to control Pi-pan.
Pi-Pan details;
www.kickstarter.com/projects/1842571016/pi-pan-a-pan-tilt-for-raspberry-pi-camera
www.openelectrons.com
Copyright (C) 2013 Mark Williams
www.ozzmaker.com
Reqires Serverblaster
If the servos do not move, check that they have been defined correctly below.
##########################################################################################
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <termios.h>
#include <stdlib.h>
#include <signal.h>
#define TILT_SERVO 5
#define PAN_SERVO 6
static struct termios g_old_kbd_mode;
FILE *fp;
// detect key press
static int kbhit(void){
struct timeval timeout;
fd_set read_handles;
int status;
// check stdin (fd 0) for activity
FD_ZERO(&read_handles);
FD_SET(0, &read_handles);
timeout.tv_sec = timeout.tv_usec = 0;
status = select(0 + 1, &read_handles, NULL, NULL, &timeout);
return status;
}
// put the things as they were befor leave..!!!
static void old_attr(void){
tcsetattr(0, TCSANOW, &g_old_kbd_mode);
}
void  INThandler(int sig)
{
fclose(fp);
signal(sig, SIG_IGN);
exit(0);
}
void servoblaster(int server, int  pulseWidth){
fprintf(fp, "%i=%i\n",server,pulseWidth);
fflush(fp);
}
// main function
int main( void ){
char ch;
static char init;
struct termios new_kbd_mode;
int tilt=150;
int pan=150;
fp = fopen("/dev/servoblaster", "w");
if (fp == NULL) {
printf("Error opening file\n");
exit(0);
}
if(init)
return;
// put keyboard (stdin, actually) in raw, unbuffered mode
tcgetattr(0, &g_old_kbd_mode);
memcpy(&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios));
new_kbd_mode.c_lflag &= ~(ICANON | ECHO);
new_kbd_mode.c_cc[VTIME] = 0;
new_kbd_mode.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &new_kbd_mode);
atexit(old_attr);
// stat Pi-pan in its neutral position
servoblaster(TILT_SERVO,150);
servoblaster(PAN_SERVO,150);
printf("\n\n\nUse 'w','s','a' and 'd' keys to conrol the movement of Pi-pan.\n");
printf("The spacebar will reset Pi-pan to its  neutral position.\n");
printf("\n\n");
while (!kbhit()){
// getting the pressed key...
ch = getchar();
switch (ch){
case 's':
printf("Down\n");
tilt++;
if (tilt>180)tilt=180;
servoblaster(TILT_SERVO,tilt);
break;
case 'w':
printf("Up\n");
tilt--;
if (tilt<80)tilt=80; 		servoblaster(TILT_SERVO,tilt); 		break; 	case 'a': 		printf("Left\n"); 		pan++; 		if (pan>200)pan=200;
servoblaster(PAN_SERVO,pan);
break;
case 'd':
printf("Right\n");
pan--;
if (pan<50)pan=50;
servoblaster(PAN_SERVO,pan);
break;
case ' ':
printf("Reset\n");
tilt=150;
pan=150;
servoblaster(TILT_SERVO,tilt);
servoblaster(PAN_SERVO,pan);
break;
}
}
}