Dejan Levec

Pan & Tilt Servo bracket

Recently I bought Pan & Tilt Servo bracket set that looks like this:

Servo motors are not robust as I am used to them, but they will be good enough to hold a light web cam.

Servos are controlled by PWM (pulse width modulation) and they need special hardware support. Thankfully, ordinary Arduino supports 6 PWM channels which should be enough for most projects.

Arduino already has a library called Servo to support these motors and there are a lot of articles explaining how it works, so I won’t go into details.

In my case I want to control it from a computer (or in the future from Raspberry Pi or some router running OpenWRT) and therefore need a way to communicate with Arduino.

Servos can be set to a fixed angle where they will stay no mater what (if you don’t put too much force to them) and this angle is from 0 to 180 degrees – half a circle.

Communication between Arduino and computer is usually in the form of data transfer through USB emulated serial port. Serial port communication is intended for transferring text so you must send/receive chars – which are represented by bytes. Byte consists of 8 bits and therefore can represent 128 different states or numbers.

Since 180 degrees is a bit bigger than 128 we need to find another way. I chose to separate data about each angle into two bytes.

First byte holds number from 0 to 127, and second one holds the reminder to 180. For example 160 degrees angle is sent as 127 and 33 – together they represent number 160.

Final format looks like this:

[first motor 0-127] [first motor 0-53] [second motor 0-127] [second motor 0-53]

The only remaining question is how do we know when byte from first motor starts? What if communication is interrupted before sending every byte? We need a unique identifier identifying the start of this sequence.

I decided to firstly post 127 and after that our sequence. However, we need to change the first byte for both motors from 0-127 to 0-126, so that 127 is never send anywhere else except at start.

Final Arduino code looks like this:

#include <Servo.h>

Servo s1,s2;

void setup() {
s1.attach(2);
s2.attach(3);
Serial.begin(9600);
}

int angle0=90, angle1=90;

void loop() {
s1.write(angle0);
s2.write(angle1);

if(Serial.available()>4 && Serial.read()==127) {
int ss = Serial.read()+Serial.read();
int ss2 = Serial.read()+Serial.read();
angle0=ss;
angle1=ss2;
}
}

At the start motors are at 90 degrees, and then we wait for 5 available bytes with first of them equal to 127. After that we simply add bytes and change global variables which will be latter sent to Servo library.

Example C# code with serialPort and two trackBars on form looks like this:

private void Form1_Load(object sender, EventArgs e)
{
serialPort1.Open();
}

private void Send()
{
int x1 = trackBar1.Value,x2=0;

if (x1 > 126)
{
x2 = x1 – 126;
x1 = 126;
}

int y1 = trackBar2.Value, y2 = 0;

if (y1 > 126)
{
y2 = y1 – 126;
y1 = 126;
}

byte[] buf = new byte[5];
buf[0] = 127;
buf[1] = (byte)x1;
buf[2] = (byte)x2;
buf[3] = (byte)y1;
buf[4] = (byte)y2;

string a = “”;

for (int i = 0; i < 5; i++)
{
a += Convert.ToString((int)buf[i]);
a += “,”;
}
label1.Text = a;
serialPort1.Write(buf, 0, buf.Length);
}

private void trackBar1_Scroll(object sender, EventArgs e)
{
Send();
}

private void trackBar2_Scroll(object sender, EventArgs e)
{
Send();
}

Now I might use this for a webcam controlled by Wii Nunchuck or via web page.

Leave a Reply

Your email address will not be published. Required fields are marked *