Advanced PAN/TILT webcam controller w/position presets and more!

  1. Hi to all!

i’m complety new on the world of microcontrollers and HW programming (only a few php) and i’m very exciting what arduino can do, also i have the documentary of arduino if anybody want the copy of it :slight_smile:

so i will explain better between this week… i’m creating a pan/tilt controller for a webcam, managing all by the usb port from the computer; in the future i wanna be able to control the position of the pan/tilt also the speed of how fast/slow i want to move the controller cam.

also another good one feature is the posibility to set preset position, for a video conferencing; this could be so great if u move the cam to one person and save the present and then u move to other person, and if u need to return to the first one, only you press a buttom and the cam will as fast as possible to the saved position.

now i have a little of code than moreless work, so if anyone are interesed in collaborate, it would be nice, tomorrow i will submit a little of video of how it works and the wiring diagram (is so simple, lol)

the code is here:

 * NewSerialServo-extreme
 * --------------
 * Servo control from the Serial port
 * Alteration of the control interface to use < and > keys
 * to slew the servo horn left and right.  Works best with
 * the Linux/Mac terminal "screen" program.
 * RE-adapted in 25 febrary 2011
 * copyleft 2011 Hector Fernandez (clonick)
 * basics created from code by Tom Igoe
 * copyleft 2007 Brian D. Wendt
 * Adapted from code by Tom Igoe

/** Adjust these values for your servo and setup, if necessary **/
int servoPin     =  9;    // control pin 9 for servo motor
int servoPiny     =  11;    // control pin 11 for servo motor
int minPulse     =  660;  // minimum servo position
int maxPulse     =  2270; // maximum servo position
int turnRate     =  30;  // servo turn rate increment (larger value, faster rate)
int refreshTime  =  20;   // time (ms) between pulses (50Hz)
int minPulsey     =  660;  // minimum servo position
int maxPulsey     =  2270; // maximum servo position
int turnRatey     =  30;  // servo turn rate increment (larger value, faster rate)
int refreshTimey  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position X
int pulseWidth;          // servo pulse width
int moveServo;           // raw user input
int moveServoy;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse
int centerServoy;         // center servo position Y
int pulseWidthy;          // servo pulse width
long lastPulsey   = 0;    // recorded time (ms) of the last pulse

void setup() {
  pinMode(servoPin, OUTPUT);  // Set servo X pin as an output pin
  pinMode(servoPiny, OUTPUT);  // Set servo Y pin as an output pin
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth = centerServo;   // Give the servo a starting point (or it floats)
  centerServoy = maxPulsey - ((maxPulsey - minPulsey)/2);
  pulseWidthy = centerServoy;   // Give the servo a starting point (or it floats)
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press a,w,s,d to move, spacebar to center Pan and Y to center Tilt");

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo =;
    // ASCII example '<' is 44, ASCII '>' is 46 (comma and period, really) w is 119. s is 115
    if (moveServo == 97) { pulseWidth = pulseWidth - turnRate; } //97 is a
    if (moveServo == 100) { pulseWidth = pulseWidth + turnRate; } //100 is d
    if (moveServo == 115) { pulseWidthy = pulseWidthy - turnRatey; } //s is 115
    if (moveServo == 119) { pulseWidthy = pulseWidthy + turnRatey; } //w is 119
    if (moveServo == 32) { pulseWidth = centerServo; } //32 is spacebar
    if (moveServo == 121) { pulseWidthy = centerServoy; } //121 is y (for center the Y axis
               //the next line will be used for the presets, actually the position is manual set, and when u press 1...4 the pan/tilt will go to the position mentioned above.
        if (moveServo == 49) {{ pulseWidthy = 835;} {pulseWidth = 805; }} //49 is 1
        if (moveServo == 50) {{ pulseWidthy = 1825;} {pulseWidth = 1260; }} //50 is 2
        if (moveServo == 51) {{ pulseWidthy = 805;} {pulseWidth = 1410; }} //51 is 3
        if (moveServo == 52) {{ pulseWidthy = 1375;} {pulseWidth = 720; }} //52 is 4

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth < minPulse) { pulseWidth = minPulse; }
    if (pulseWidthy > maxPulsey) { pulseWidthy = maxPulsey; }
    if (pulseWidthy < minPulsey) { pulseWidthy = minPulsey; }

     Serial.print("X: "); //print for axis X
     Serial.println(" ");   // nothing for move the servos more smooth
     Serial.print("Y: "); //print for axis Y
     Serial.println(" \n");   // double line break (enter) for only one line brake use \r


  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servoPin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }  else if (millis() - lastPulsey >= refreshTimey) {
    digitalWrite(servoPiny, HIGH);   // start the pulse
    delayMicroseconds(pulseWidthy);  // pulse width
    digitalWrite(servoPiny, LOW);    // stop the pulse
    lastPulsey = millis();     

thanks for your comments and support

moveServo == 97)

Off the top of your head, do you know what character code this is?
No, me neither.

Is there a good reason for not using the servo library?

97 is an 'a'

no reason for not use the servo library, as i mention, i'm newbie and i don't know what to do to use the servo library.

exist some example code for call the servo library but in my ardunio uno, the verifying process have error with the line:


or something like that, says than the refresh has not declared moreless.

but if someone have a better proposal, only say it.

at now i will work on the part of how to save in a variable some prosition and after call it by a preset.

regards! :grin:

You probably can duplicate my servo pan/tilt cam below using an arduino with a 100 ohm resistor to prevent resetting.

hi zoomkat

could you explain me the appliance of the resistor of 100ohm for resetting? i din't have idea about that.

also, your desing is interesting, but as you aren't using arduino, discover in that way will be more complicated for me.

now with my code my pan tilt works, is very simple, also the future inmediatly of this project will be used un and documentary wildlife in monterrey, mexico, so we require optimizing it for outdoor weather also have theposibility to have more features per system and arduino could do so well that job.

at this moment i wish to work in the part of the save some positions of the pan tilt and call it later.

any suggestion?

could you explain me the appliance of the resistor of 100ohm for resetting? i din't have idea about that.

also, your desing is interesting, but as you aren't using arduino, discover in that way will be more complicated for me.

In my setup, a pan/tilt command is sent from a web page to the apache web server running on my computer, apache runs a batch file containing the command that opens the com port and sends the command to the servo controller. This can be duplicated using the arduino if a 100 ohm resistor is used to defeat the auto reset of the arduino when the com port is opened. Without the resistor, the arduino is resetting while the serial data is being sent, so the arduino never sees the commands. This will probably become more apparent to you as you do some testing.

here is the alpha controller.

i'm using 2 small servos connecting directly to the arduino uno.


The servo library doesn't have or need a refresh method anymore.

so anyone could writte an example of my code but using servo library?


anyone isn't interesed or really i'm so out of way in my project? LOL


You are not on your own, but you don't expect people to write code for you (well, not for free anyway!).
There are plenty of examples of using the servo library around, here on the forum or over at the playground.
Work through a few until you understand what is going on - probably best to start with a single servo and add more as you get more confidence.

Below is code you can use for two servo based pan/tilt cam.

// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550

#include <Servo.h> 
String readString, servo1, servo2;
Servo myservo1;  // create servo object to control a servo 
Servo myservo2;

void setup() {
  myservo1.attach(6);  //the pin for the servo control 
  Serial.println("servo-test-21"); // so I can keep track of what is loaded

void loop() {

  while (Serial.available()) {
    if (Serial.available() >0) {
      char c =;  //gets one byte from serial buffer
      readString += c; //makes the string readString

  if (readString.length() >0) {
      Serial.println(readString); //see what was received
      // expect a string like 07002100 containing the two servo positions      
      servo1 = readString.substring(0, 4); //get the first four characters
      servo2 = readString.substring(4, 8); //get the next four characters 
      Serial.println(servo1);  //print to serial monitor to see results
      int n1; //declare as number  
      int n2;
      char carray1[6]; //magic needed to convert string to a number 
      servo1.toCharArray(carray1, sizeof(carray1));
      n1 = atoi(carray1); 
      char carray2[6];
      servo2.toCharArray(carray2, sizeof(carray2));
      n2 = atoi(carray2); 
      myservo1.writeMicroseconds(n1); //set servo position