Learn how to make a remotely visible pan-tilt security camera using your Raspberry Pi. This project can be completed in the morning with only the simplest parts. Here is the end result:

What you need
- Raspberry Pi 2 or 3 with Micro SD card
- Arduino UNO or similar
- 2 x micro or mini hobby servos
- USB webcam
- Male and male connecting wires
- Male and female connection wires
- Assorted zippers
Building a security camera
Attach a servo horn (small plastic «figurines») to each servo using the included screw. The specific shape doesn’t really matter, though the bigger the better. Do not overtighten the screw.
Now use the zippers to attach one servo to the other at right angles. One will be pan (left to right) and the other will be tilt (up and down). It doesn’t matter who does what, it can be configured in code.
Finally, attach the webcam to one of the servos. You could use zippers for this, although my webcam came with a clip screwed to the bottom — I removed that and used a screw to attach it to the horn. For stability, you can mount the entire rig on a crate or box. A simple cardboard box does its job quite nicely. You can cut a neat square hole and mount one servo flush with the surface, however a zipper will suffice.
A word about webcams
Not all USB cameras are created equal. Connect your webcam to your Pi’s USB port and run the following command:
lsusb
This command displays information about all USB devices connected to the Pi. If your webcam is not listed, you can try the connected USB hub and repeat the command. If the webcam is still not recognized, you may need to purchase a compatible webcam.
Servo setting
While servos may seem intimidating and complicated, they are actually quite simple to wire up. Servo drives operate with pulse-width modulation (PWM), which allows digital systems to mimic analog signals. PWM signals are essentially a fast on-off signal. An ON or HIGH signal is described using a duty cycle. The duty cycle is expressed as a percentage and describes how long the signal is on. A PWM signal with a duty cycle of 25% will be on for 25% of the time and off for the remaining 75%. The signal does not turn on at the beginning and then turn off forever, it pulses regularly for a very short period of time.
The servos listen to these pulses and act accordingly. Using a duty cycle of 100% would be the same as «regular» 5V, and 0% would be the same as ground. Don’t worry if you don’t fully understand how PWM works, you can still control servos (Extreme Electronics is a good place to learn more).
There are two main ways to use PWM — hardware or software. Hardware PWM often provides lower latency (how long between a servo receiving a command and moving) than software PWM, however the Pi only has one hardware PWM pin. External circuits are available to provide multiple hardware PWM channels, however a simple Arduino can also do the job as they have multiple hardware PWM pins.
Here is the diagram:
Double check your Pi’s pinouts, they vary a bit depending on the model. You have to figure out how your servos are connected. The servos require three wires to drive them, however the colors are slightly different:
- Red positive, connect this to Pi + 5v
- Brown or black negative, connect this to GND on the Pi
- The signal is orange or white, connect it to Arduino pins 9 and 10
Arduino setup
New to Arduino? here
After connecting the servos, open the Arduino IDE on your computer and upload this test code. Be sure to select the correct board and port in menu Tools> Fee and Tools> Menu ports
#include // Import the library Servo servoPan, servoTilt; // Create servo objects int servoMin = 20, servoMax = 160; // Define limits of servos void setup() { // Setup servos on PWM capable pins servoPan.attach(9); servoTilt.attach(10); } void loop() { for(int i = servoMin; i < servoMax; ++i) { 1 // Move servos from minimum to maximum servoPan.write(i); servoTilt.write(i); delay(100); // Wait 100ms } for(int i = servoMax; i > servoMin; --i) { // Move servos from maximum to minimum servoPan.write(i); servoTilt.write(i); delay(100); // Wait 100ms } }
All good, you should be able to see both servos moving slowly back and forth. Note that «servoMin» and «servoMax» are defined as 20 and 160 degrees (instead of 0 and 180). This is partly because these cheap servos can’t accurately move 180 degrees, and the physical size of the webcam prevents full range from being used. You may need to tweak them for your setup.
If they don’t work at all, double check that the circuit is connected correctly. Breadboards can also sometimes vary in quality, so consider purchasing a multimeter to test.
Servo drives nearly too powerful for the Arduino to run, so they will be powered by the Pi. The 5V rail on the Pi is limited to 750mA supplied to the entire Pi, and the Pi draws approximately 500mA, leaving 250mA for the servos. These micro servos draw around 80mA, which means the Pi should be able to handle two of them. If you want to use more servos or more powerful models, you may need an external power supply.
Now upload the following code to Arduino. This will listen for incoming serial data (serial, as in universal consistent bus or USB). The Pi will send this data via USB to the Arduino, telling it where to move the servos.
#include // Import the library Servo servoPan, servoTilt; // Create servo object String data = ""; // Store incoming commands (buffer) void setup() { // Setup servos on PWM capable pins servoPan.attach(9); servoTilt.attach(10); Serial.begin(9600); // Start serial at 9600 bps (speed) } void loop() { while (Serial.available() > 0) { // If there is data char singleChar = Serial.read(); // Read each character if (singleChar == 'P') { // Move pan servo servoPan.write(data.toInt()); data = ""; // Clear buffer } else if (singleChar == 'T') { // Move tilt servo servoTilt.write(data.toInt()); data = ""; // Clear buffer } else { data += singleChar; // Append new data } } }
You can check this code by opening the serial monitor ( top right > Serial Monitor ) and sending some test data: