Static and Dynamic Camera Setup

Akshul Goyal
3 min readMay 10, 2021


Fifth Installment in my Project series

Photo by Marcus Urbenz on Unsplash

In this post, we will discuss about how we can attach our Pi camera to a motorized system to follow someone’s movement within the camera frame.

The main objective of this post is to make a dynamic surveillance system with one camera instead of a multi-camera system.

For this setup I am using these Pan-tilt-bracket and these servo-motors. This is how my setup looks like, though it’s a bit flimsy but it does the work for a basic setup.

Motorized Dynamic camera setup

Basics of Servo Motor —
According to SG90’s datasheet, it works on a PWM signal of 20ms cycle and 50Hz frequency. As the sheet mentioned, there are 3 main reference position—

0 (middle), with 1.5ms pulse
+90, 2ms pulse
and -90, 1ms pulse

So for all 3 position the duty cycle respectively are—
1.5/21*100 = 7.14%
2/21*100 = 9.52%
1/21*100 = 4.76%
Duty cycle = (T_on / T_on + T_off) *100
So a range of 4.7–9.5% dc

Generating PWM using RPi GPIO —

# import library
import RPi.GPIO as GPIO
# Initializing
# Setup and channel
servo = 12
GPIO.setup(servo, GPIO.OUT)
# initializing the channel as PWM output with 50Hz freq.
p = GPIO.PWM(servo, 50)
# setting up duty cycle
duty = (ms/21)*100 # ms is pulse T_ON, time for when it's high
# Sending the PWM signal to the motor
GPIO.output(servo_y, True)
GPIO.output(servo_y, False)
# Stop sending the PWM signal

So test the positions/angles, I put the camera mount on my table at -90 degree initial position. Then I marked a vertical straight line. To mark a 90 degree line w.r.t. to the initial position, I used my sticky notes. Look at the following set of pictures to clearly understand my setup.

To test position/rotation of servo

The last picture suggests the camera being rotated at 0 (middle) position.

To test the rotation of the servo, I fed in these 3 mentioned pulses (T_on values). For 0 degree middle position, 1.5ms is the value, but the servo rotation went beyond the marked line. So then I tested -90 degree initial position, that is 1ms. But the servo couldn’t go back to initial position.

So I fed in lesser values of T_on, 0.8ms, 0.5ms, and the servo rotated up-to 0.3ms. When I fed 0.2ms the motor did not move at all. So the -90 degree position was attained by 0.3ms pulse.

The previous 0 position pulse that I gave to motor, led to rotation beyond the marked line, hence I gave a smaller value and kept decreasing the value until the servo was at the marked 90 degree position w.r.t. the initial position. So for 0 degree position, pulse value was 1.25ms.

Similarly for +90 degree position, when I fed 2ms it did not rotated 180 degree w.r.t. the initial position. So I kept increasing pulse value and I found 2.6ms is for +90 degree position.

180 degree rotation to +90 degree position

As seen from the picture above the servo rotated a bit beyond 180 degree rotation. 2.4ms was closer to +90 degree position.

So now the pulse range is 0.3ms-2.6ms, and accordingly duty cycle range is 1.42–12.38% as opposed to theoretically mentioned 4.7–9.5 range in datasheet.

Sometimes you have to go beyond the theoretical limits of a system to test it’s actual limits.

Implementation —
Now that we have understood the basics of a servo motor, we will try to use this system so that the camera can follow a moving object. More about this later.

Stay Tuned!



Akshul Goyal

Hacking the Physical World | Senior Embedded Systems Engineer @ PiRhoAlpha Research (ActiveBuildings) | I write posts about AVR and Raspberry Pi.