Servo problems but don't understand

Hello,
I have been trying to get a program running using 2 servo’s and I have reached a point where i don’t understand why it isn’t working. I am hoping someone out there can see what i might be doing wrong.
First a snippet of code where I don’t understand why it doesn’t work:

 byte data = byteReceived[3];       // read the incoming byte:
      Serial.println(data);        // Show on Serial Monitor
      switch(data)
        {
          case 2 :  pulseWidth1 = pulseWidth1 - turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // right
          case 4 :  pulseWidth1 = pulseWidth1 + turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // left   
          case 16 :  pulseWidth2 = pulseWidth2 - turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // down
          case 8 :  pulseWidth2 = pulseWidth2 + turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // up

When looking at serial terminal I can see the correct value depending which servo I am trying to move and pulseWidth(x) is showing incremented up or down value starting from an initial 90.
This code snippet is from another post that I am using since it is almost exactly what i need.

To test that the servo’s work I tried out this code that was posted by another:

// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
 #include <Servo.h>
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created

int pos = 0;    // variable to store the servo position

void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}


void loop()
{
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                               
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

After adding the #include that the other person did not and after compiling and downloading it didn’t work until I hit reset, then the servo on pin 9 swept back and forth as expected.

I don’t understand why this program works but the first listed one doesn’t? The first listed code has a serial input that commands either servo to move in direction and by how much. Could the use of the serial input be causing issues with the servo library?
Any idea’s?
Thanks,
Bruce
PS: I started this topic and then saved it as a draft but I can’t find where to bring that back up and “How to use this forum” had no answers to this.

Please post your complete program. The snippet of code that you posted is not enough to provide help.

Ok here it is:

/*
 * http://forum.arduino.cc/index.php?topic=18119.0
 * http://forum.arduino.cc/index.php?topic=155693.0
 */


/*-----( Import needed libraries )-----*/
#include <Servo.h>

/*-----( Declare Constants and Pin Numbers )-----*/
#define RS485lTxControl 3   //RS485 Direction control
#define RS485Transmit    HIGH   // not needed here, the servos attached to the arduino will not transmit any data to the Pelco-D controller 
#define RS485Receive     LOW
#define Pin13LED         13

/*-----( Declare objects )-----*/
Servo servoPAN, servoTILT ;

/*-----( Declare Variables )-----*/
byte byteReceived[7];
int byteNumber = 0;
int byteSend;
int minPulse1     =  0;   // minimum servo position
int maxPulse1     =  180; // maximum servo position
int turnRate1     =  3;  // servo turn rate increment (larger value, faster rate)
int minPulse2     =  0;  // minimum servo position
int maxPulse2     =  180; // maximum servo position
int turnRate2     =  3;  // servo turn rate increment (larger value, faster rate)
/** The Arduino will calculate these values for you **/
int centerservoPAN;
int centerservoTILT;
int pulseWidth1;          // servo pulse width
int pulseWidth2;          // servo pulse width


void setup() {
  servoPAN.attach(9);
  servoTILT.attach(10);
  centerservoPAN = maxPulse1 - ((maxPulse1 - minPulse1)/2);
  centerservoTILT = maxPulse2 - ((maxPulse2 - minPulse2)/2);
  pulseWidth1 =  centerservoPAN;
  pulseWidth2 =  centerservoTILT;
  Serial.begin(38400);      // opens serial port, sets data rate to 38400 bps
  Serial.println("Arduino Serial Servo Control with Pelco D");
  Serial.println();
  pinMode(Pin13LED, OUTPUT);   
  pinMode(RS485lTxControl, OUTPUT);   
  digitalWrite(RS485lTxControl, RS485Receive);  // Init Transceiver   
}//--(end setup )---


void loop() {
  if (Serial.available() > 0)  //Look for incoming serial data from Pelco-D controller
   {
    digitalWrite(Pin13LED, HIGH);  // Show activity
    byteReceived[byteNumber ++] = Serial.read();    // Read received byte
     //Serial.println(byteReceived[byteNumber], DEC);        // Show on Serial Monitor
    //delay(10);
    digitalWrite(Pin13LED, LOW);  // Show activity
    if ( byteReceived[0] != 0xFF ) {byteNumber = 0;}   // When Byte 0 isn't 0xFF (Pelco 1st Byte) reset byteNumber to 0 preventing the serial port being blocked.
   }
    if ( byteNumber > 6 )                                 // process it
    {                 
      byteNumber = 0;                                 // ready for next time
      byte data = byteReceived[3];       // read the incoming byte:
      Serial.println(data);        // Show on Serial Monitor
      switch(data)
        {
          case 2 :  pulseWidth1 = pulseWidth1 - turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // right
          case 4 :  pulseWidth1 = pulseWidth1 + turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // left   
          case 16 :  pulseWidth2 = pulseWidth2 - turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // down
          case 8 :  pulseWidth2 = pulseWidth2 + turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // up
          //case 0x0C :  pulseWidth1 = pulseWidth1 + turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 - turnRate2; servoTILT.write(pulseWidth2); break; // left-up
          //case 0x0A :  pulseWidth1 = pulseWidth1 - turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 - turnRate2; servoTILT.write(pulseWidth2); break; // right-up
         // case 0x14 :  pulseWidth1 = pulseWidth1 + turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 + turnRate1; servoTILT.write(pulseWidth2); break; // left-down
          //case 0x12 :  pulseWidth1 = pulseWidth1 - turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 + turnRate1; servoTILT.write(pulseWidth2); break; // right-down
          default : 
                  break;
        }
       
        // stop servo pulse at min and max
        //if (pulseWidth1 > maxPulse1) { pulseWidth1 = maxPulse1; }
        //if (pulseWidth1 < minPulse1) { pulseWidth1 = minPulse1; }
        // stop servo pulse at min and max
        //if (pulseWidth2 > maxPulse2) { pulseWidth2 = maxPulse2; }
        //if (pulseWidth2 < minPulse2) { pulseWidth2 = minPulse2; }
       
    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    Serial.print("Servo 1: ");
    Serial.print(pulseWidth1);
    Serial.print(" Servo 2: ");
    Serial.print(pulseWidth2);
    Serial.println("degrees");
   }
}

Oh I forgot to add that I am using version 1.6.5 of the Audruino environment.

OK, slightly confusing name "pulseWidth" when you are actually using degrees and the Servo.write() function.

That program appears to do nothing until it gets 7 characters on the serial input. Then it looks at the 3rd character and, based on that, moves one of the servos to a position.

Why doesn't it set the servos to an initial position during setup()?

It does setup an initial position. See "centerservoPAN" and "centerservoTILT".

Once it works i will go through the program and make things easier to read depending on what they are doing.

Ok so I still don’t know why but I got this first code listed working.
What I tried was inserting "servoTILT.write(0) just before the end brace in setup as a desperation
move on my part and downloaded that. I watched the servo move to 0 position after reset and that made me even more confused when i tried sending via serial RS485 a command and wow the servo moved!!
Tried the other servo and it started moving also when commanded!
So this is the code now but still needs some TLC:

/*
 * http://forum.arduino.cc/index.php?topic=18119.0
 * http://forum.arduino.cc/index.php?topic=155693.0
 */


/*-----( Import needed libraries )-----*/
#include <Servo.h>

/*-----( Declare Constants and Pin Numbers )-----*/
#define RS485lTxControl 3   //RS485 Direction control
#define RS485Transmit    HIGH   // not needed here, the servos attached to the arduino will not transmit any data to the Pelco-D controller 
#define RS485Receive     LOW
#define Pin13LED         13

/*-----( Declare objects )-----*/
Servo servoPAN, servoTILT ;

/*-----( Declare Variables )-----*/
byte byteReceived[7];
int byteNumber = 0;
int byteSend;
int minPulse1     =  0;   // minimum servo position
int maxPulse1     =  180; // maximum servo position
int turnRate1     =  3;  // servo turn rate increment (larger value, faster rate)
int minPulse2     =  0;  // minimum servo position
int maxPulse2     =  180; // maximum servo position
int turnRate2     =  3;  // servo turn rate increment (larger value, faster rate)
/** The Arduino will calculate these values for you **/
int centerservoPAN;
int centerservoTILT;
int pulseWidth1;          // servo pulse width
int pulseWidth2;          // servo pulse width


void setup() {
  servoPAN.attach(9);
  servoTILT.attach(10);
  centerservoPAN = maxPulse1 - ((maxPulse1 - minPulse1)/2);
  centerservoTILT = maxPulse2 - ((maxPulse2 - minPulse2)/2);
  pulseWidth1 =  centerservoPAN;
  pulseWidth2 =  centerservoTILT;
  Serial.begin(38400);      // opens serial port, sets data rate to 38400 bps
  Serial.println("Arduino Serial Servo Control with Pelco D");
  Serial.println();
  pinMode(Pin13LED, OUTPUT);   
  pinMode(RS485lTxControl, OUTPUT);   
  digitalWrite(RS485lTxControl, RS485Receive);  // Init Transceiver 
  servoTILT.write(90);
  servoPAN.write(90);  
}//--(end setup )---


void loop() {
  if (Serial.available() > 0)  //Look for incoming serial data from Pelco-D controller
   {
    digitalWrite(Pin13LED, HIGH);  // Show activity
    byteReceived[byteNumber ++] = Serial.read();    // Read received byte
     //Serial.println(byteReceived[byteNumber], DEC);        // Show on Serial Monitor
    //delay(10);
    digitalWrite(Pin13LED, LOW);  // Show activity
    if ( byteReceived[0] != 0xFF ) {byteNumber = 0;}   // When Byte 0 isn't 0xFF (Pelco 1st Byte) reset byteNumber to 0 preventing the serial port being blocked.
   }
    if ( byteNumber > 6 )                                 // process it
    {                 
      byteNumber = 0;                                 // ready for next time
      byte data = byteReceived[3];       // read the incoming byte:
      Serial.println(data);        // Show on Serial Monitor
      switch(data)
        {
          case 2 :  pulseWidth1 = pulseWidth1 - turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // right
          case 4 :  pulseWidth1 = pulseWidth1 + turnRate1; 
                        servoPAN.write(pulseWidth1); 
                        break; // left   
          case 16 :  pulseWidth2 = pulseWidth2 - turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // down
          case 8 :  pulseWidth2 = pulseWidth2 + turnRate2; 
                        servoTILT.write(pulseWidth2); 
                        break; // up
          //case 0x0C :  pulseWidth1 = pulseWidth1 + turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 - turnRate2; servoTILT.write(pulseWidth2); break; // left-up
          //case 0x0A :  pulseWidth1 = pulseWidth1 - turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 - turnRate2; servoTILT.write(pulseWidth2); break; // right-up
         // case 0x14 :  pulseWidth1 = pulseWidth1 + turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 + turnRate1; servoTILT.write(pulseWidth2); break; // left-down
          //case 0x12 :  pulseWidth1 = pulseWidth1 - turnRate1; servoPAN.write(pulseWidth1); pulseWidth2 = pulseWidth2 + turnRate1; servoTILT.write(pulseWidth2); break; // right-down
          default : 
                  break;
        }
       
        // stop servo pulse at min and max
        //if (pulseWidth1 > maxPulse1) { pulseWidth1 = maxPulse1; }
        //if (pulseWidth1 < minPulse1) { pulseWidth1 = minPulse1; }
        // stop servo pulse at min and max
        //if (pulseWidth2 > maxPulse2) { pulseWidth2 = maxPulse2; }
        //if (pulseWidth2 < minPulse2) { pulseWidth2 = minPulse2; }
       
    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    Serial.print("Servo 1: ");
    Serial.print(pulseWidth1);
    Serial.print(" Servo 2: ");
    Serial.print(pulseWidth2);
    Serial.println("degrees");
   }
}

So can anyone enlighten me as to why I needed to send servo data in setup to make this all work? I am very curious as to the why.
Sometimes it’s difficult to troubleshoot code this way. I am so use to using an emulator where i can set a break point to examine registers etc.
Bruce

  centerservoPAN = maxPulse1 - ((maxPulse1 - minPulse1)/2);

Look at the math there. The value that ends up in centerservoPAN is (maxPulse1 + minPulse1)/2. And that value is easier to compute.

What I tried was inserting "servoTILT.write(0) just before the end brace in setup as a desperation move on my part and downloaded that.

That would be using this statement?

  servoTILT.write(90);

90 != 0 in my universe.

So can anyone enlighten me as to why I needed to send servo data in setup to make this all work?

Without knowing anything about your servos or how they are powered? Not likely.

Yes on the code statement.

I used a value of 0 since I wanted to really see the servo move a large distance but when first turned on the servo's move to 90 degrees or center position. That's where the servo's have been at (90) during all of this trial and error.

The servo's are Hytec HS-325HB's with no load on them powered from the Uno that uses an external PS.

So what I have learned is to initialize the servo's to 90 degrees (or what ever is necessary given the mechanics) within setup before the loop. I guess it is a way to get around the oddity of the servo library in this situation.

In setup() try:

servoPAN.write(desiredPos);
servoPAN.attach(9);
  servoTILT.write(desiredPos);  
  servoTILT.attach(10);

The servo's are Hytec HS-325HB's with no load on them powered from the Uno that uses an external PS.

You would be wise not to power the servos directly from the Arduino as its voltage regulator can only supply supply a limited amount of current.

Yes I am very aware of this limitation and when the servo's get loaded will be using external power for them.

One last comment. I think what bothers me the most about this issue I had with getting the servo's to actually move using the code as posted and modified by me by adding the statement "servoTILT.write(90)" in SETUP as a way to test but turns out made the servo function work. None of the tutorials or reference pages say you must put a similar statement in setup field as part of initializing for the servo function and did not show that in any of the code examples. The only thing I can guess at is there may be an issue with the Arduino IDE version 1.6.5 and the servo.h library. I wonder what other library's have an issue with 1.6.5? May find out over time.

Thanks to everyone that responded to this thread with suggestions/help.

So I am finished for now and the controller appears to be working ok so I have made changes and providing the code for anyone that wants to do the same or pieces of it. It’s not pretty but it
is working.

[code]

/*
 * http://forum.arduino.cc/index.php?topic=18119.0
 * http://forum.arduino.cc/index.php?topic=155693.0
 */

/* This program originally came from HanslmGlueck in topic #155693 and I have made changes to the original
 *  to try and make things clearer (doubtfull) and to get it to work with my setup. I used Arduino
 *  IDE ver 1.6.5 and seems to be compiling/working ok after a few changes. I am a newbie to C++ so the code
 *  may not be as compact as it could.
 *  NOTES: the servo control lines go to pins 9 (PAN) and 10 (TILT) on a UNO. The RS485 input goes
 *  to RX pin on the UNO. For RS485 I am using a LTC485 IC and only receive data from a Pelco controller
 *  is used so I eliminated the TX control on RS485 since there is no feedback to Pelco controller.
 *  I am simulating the Pelco-D protocall with 232Analyzer with the Pelco_D device profile, this came
 *  from www.commfront.com.
 *  CAVATS: there is no checksum calculated for the received bytes from serial RS485 input. Only the command 2 
 *  byte is used (byte 3 starting from 0, 4 if you start with 1) to parse out PAN left/right or TILT up/down or
 *  combination. No control of speed or zoom or focus has been attampted by me or the original writer.
 */
/*-----( Import needed libraries )-----*/
#include <Servo.h>


/*-----( Declare objects )-----*/
Servo servoPAN, servoTILT ;

/*-----( Declare Variables )-----*/
byte byteReceived[7];
int byteNumber = 0;
int Pin13LED;
byte data;
int servoPan_deg;
int servoTilt_deg;
int turnRate1     =  3;  // servo turn rate degrees increment (larger value, faster rate)
int turnRate2     =  3;  // servo turn rate degrees increment (larger value, faster rate)

void setup()
{
  servoPAN.attach(9); //servo control signal pins
  servoTILT.attach(10);
  servoPan_deg =  (90);  //depends on where home needs to be
  servoTilt_deg =  (90);
  Serial.begin(38400);      // opens serial port, sets data rate to 38400 bps. Change this to suit your Pelco controller baud rate
/** comment out next 2 lines when debugging done **/
  Serial.println("Arduino Serial Servo Control with Pelco D");  
  Serial.println();
//LED flashes on serial recieve
  pinMode(Pin13LED, OUTPUT);   
  /** move servo's to start position and needed for 1.6.5 & servo.h issue **/
  servoTILT.write(servoTilt_deg);
  servoPAN.write(servoPan_deg);  
}
//--(end setup )---


void loop()
{
  if (Serial.available() > 0)  //Look for incoming serial data from Pelco-D controller 7 bytes total
        {
    digitalWrite(Pin13LED, HIGH);  // Show activity
    byteReceived[byteNumber ++] = Serial.read();    // Read received byte
   
    digitalWrite(Pin13LED, LOW);  // Show activity
          if ( byteReceived[0] != 0xFF )
                {
                byteNumber = 0;   // When Byte 0 isn't 0xFF (Pelco 1st Byte) reset byteNumber to 0 preventing the serial port being blocked.
                }
        }
          if ( byteNumber > 6 )                                 // process it
            {                 
      byteNumber = 0;                                 // ready for next time
      byte data = byteReceived[3];       // read the incoming byte if Pan or Tilt or combo
/** comment out next line when done debugging **/
      Serial.println(data);        // Show on Serial Monitor
    
      switch(data)
             
                  {  
          case 2 :  servoPan_deg = servoPan_deg - turnRate1; //right
          /** don't go over under limits **/
                           if (servoPan_deg <0)
                             {
                               servoPan_deg = 0;
                             }
                        servoPAN.write(servoPan_deg); 
                        break;
                        
          case 4 :  servoPan_deg = servoPan_deg + turnRate1;  //left
                           if (servoPan_deg >180) 
                             {
                               servoPan_deg = 180;
                             }
                        servoPAN.write(servoPan_deg); 
                        break;
                          
          case 16 :  servoTilt_deg = servoTilt_deg - turnRate2; //down
                           if (servoTilt_deg <0) 
                             {
                               servoTilt_deg = 0;
                             } 
                        servoTILT.write(servoTilt_deg); 
                        break;
          case 8 :  servoTilt_deg = servoTilt_deg + turnRate2; // up
                           if (servoTilt_deg >180) 
                             {
                               servoTilt_deg = 180;
                             }
                    servoTILT.write(servoTilt_deg); 
                        break;
                        
          case 12 :  servoPan_deg = servoPan_deg + turnRate1; // left-up
                            if (servoPan_deg >180) 
                             {
                                servoPan_deg = 180;
                             } 
                     servoPAN.write(servoPan_deg);
                     servoTilt_deg = servoTilt_deg - turnRate2;
                            if (servoTilt_deg <0)
                             {
                                servoTilt_deg = 0;
                             }
                     servoTILT.write(servoTilt_deg); 
                        break;
          case 10 :  servoPan_deg = servoPan_deg - turnRate1; //right-up
                            if (servoPan_deg <0)
                             {
                               servoPan_deg = 0;
                             }
                     servoPAN.write(servoPan_deg); 
                     servoTilt_deg = servoTilt_deg - turnRate2;
                             if (servoTilt_deg <0) 
                             {
                               servoTilt_deg = 0;
                             }
                     servoTILT.write(servoTilt_deg);
                        break; 
          case 20 :  servoPan_deg = servoPan_deg + turnRate1; //left-down 
                             if (servoPan_deg >180) 
                             {
                               servoPan_deg = 180;
                             }
                     servoPAN.write(servoPan_deg); 
                     servoTilt_deg = servoTilt_deg + turnRate2; 
                             if (servoTilt_deg >180) 
                             {
                               servoTilt_deg = 180;
                             }
                     servoTILT.write(servoTilt_deg);
                        break; 
          case 18 :  servoPan_deg = servoPan_deg - turnRate1; //right-down
                            if (servoPan_deg <0)
                             {
                               servoPan_deg = 0;
                             }
                     servoPAN.write(servoPan_deg); 
                     servoTilt_deg = servoTilt_deg + turnRate2;
                             if (servoTilt_deg >180) 
                             {
                               servoTilt_deg = 180;
                             }
                     servoTILT.write(servoTilt_deg); 
                     break;
   
          default : 
                  break;
                  }
       
    // print degrees back to the Serial Monitor (uncomment to debug)
/**   Serial.print("Servo 1: ");
    Serial.print(servoPan_deg);
    Serial.print(" Servo 2: ");
    Serial.print(servoTilt_deg);
    Serial.println("degrees"); 
**/    
            }
}

[/code]

  /** move servo's to start position and needed for 1.6.5 & servo.h issue **/

Or perhaps just for your particular servos. If this was a wide-spread problem, I think we would have heard about it by now.

I don't think the servo's were the problem. Putting a scope probe on the signal pins I could see a 1.5mS pulse every 20 mS or so and whenever I sent a Pelco command the pulse would stay at 1.5mS which is center position of the servo or 90 degrees.

I did have an compiling issue with some firmware for my K8200 3D printer, I was installing the K8203 and K8204 upgrades and whenever i tried to compile I got all sorts of errors using 1.6.5. I had another PC loaded with 1.0.5 and compiled there with no errors at all and was able to upload that to the K8200 no problem. Different issue but problem with IDE versions.

I know now what i must do in setup for these servo's to work with my configuration. I was just happy to find it and get things working. So onward and upward!