Servo control pulse width changes w/o reason

Hello everybody,
I tried to find out (google, this forum), no success so I decided to ask here.
Problem:
The servo moves erratically, closer measurement shows, that even without the servo connected, the control pulse changes width (see the picture below) without a control command - I use Servo.writeMicroseconds() member.
Environment:
Arduino rev 3, Servo library for Arduino using 16 bit timers Version 2, various servos tested, but the problem is not in the servo, but somewhere in the pulse generator.
Power source:
external (not USB), very "hard" one, actual current is up to 0.56 A with a servo, 0.11A w/o servo, signal behaviour is the same, so this should not be a problem. Servo powered from Arduino's 5V pin + GND.
Measurement pic/values:
vert. scale 5V/div, horiz. scale 5.0 ms/div. It is clearly seen, that the pulse gets "wider" - from 1.36ms (most left), than 1.535ms, 2.193ms, and finally 7.3ms... Pulse period is 20ms (OK). And this repeats all the time after executing the attach() command...
The running servo command was servo.writeMicroseconds(1500)...

I'll be gratefull for any advice... Thanks in advance!

Regards Jan

Hi Jan, and welcome.

You told the servo is powered from Arduino's 5 volt.
You also told the Arduino is externally powered.
Does that mean you are using the power plug ?
I'm assuming your board is an Uno r3, but that doesn't really matter here.

If you are using the power plug you are also using the on board regulator.
And connecting the servo to that is a bad idea, the regulator isn't strong enough to handle a servo.

In general it is always advised to power your servos externally, so not through any arduino pin.
So the Arduino gets some 5 volts, the servos get another 5 volts, and all grounds are connected.

I'm not sure this will solve your problem, but it's a start.

Can you post your code if the problem persists ?

Try using a different name for the object, like "myservo".
This minimal code produces a stable 1500µs pulse on an Arduino Due:

#include <Servo.h>
Servo myservo;
int pos = 0;

void setup()
{
  myservo.attach(9);
}

void loop() {
  myservo.writeMicroseconds(1500);
  delay(15);
}

Thank you for replies,
yes, I have Arduino UNO rev 3, the point is, the "pulse width unstability", how I'd call it, occurs regardless the servo is connected or not, so I assume it shall not be a servo consumption related problem or power related problem. Just to answer - yes, I use the onboard power plug for power. But again, the pulse has the same behaviour regardles the servo is connected or not.

Shortened example of my code is below - only parts related to servo are left... (I use GSM shield as well, this part works OK), I posted basically only servo related stuff not to have a long code here, the GSM part is only for understanding when an how I invoke servo actions....

The servo pulse is the same all the time, regardless the myServo1.attach parameters - default or not, pulse is unstable, the same with servo write - regardless if write or writeMicroseconds is used, signal is unstable.

Next try will be do disassemble the entire thing :frowning: and run just a basic code just for servo...

// libraries
#include <GSM.h>
#include <Servo.h>
#define PINNUMBER "xxxx"

// initialize the libraries instances
 GSM gsmAccess; 
 GSM_SMS sms;
 Servo myServo1;

// initialize variables
 int Servopin1 = 9; // Servo pin
 int Tonepin = 8; // tone output pin
 int SensorPin = A0; //Temp sensor pin
 float voltage;
 float temperature;
 int SensorVal;
 char remoteNumber[20];  // telephone number which sent sms
 char incomingMsg[200];  // incoming message
 char c;
 char TempVal[6];
 String LEDREDStat(3);
 String LEDGRStat(3);
 String LEDBLStat(3);
 String outgoingMsg(200); //outgoing message for formatting
 char outgoingMsgChar[200]; //outgoing message as char for sending
 int str_len;
 
 
void setup()
{
   // initialize pins, variables and servo initial position
   pinMode(LEDpin, OUTPUT);
   pinMode(LEDREDpin, OUTPUT);
   pinMode(LEDGRpin, OUTPUT);
   pinMode(LEDBLpin, OUTPUT);
   pinMode(Tonepin, OUTPUT);
   myServo1.attach(Servopin1, 1000, 2000); //"AT THIS MOMENT THE Servopin1 STARTS TO BE ERRATIC"
   Serial.begin(9600);
   Serial.println("Test started");
   digitalWrite(LEDpin, LOW);
   digitalWrite(LEDREDpin, LOW);
   digitalWrite(LEDGRpin, LOW);
   digitalWrite(LEDBLpin, LOW);
   myServo1.writeMicroseconds(1000);


   boolean notConnected = true;

   // Start GSM shield

   while(notConnected)
   {
     if(gsmAccess.begin(PINNUMBER)==GSM_READY)
     {
       notConnected = false;
       digitalWrite(LEDpin, HIGH);
       digitalWrite(LEDREDpin, HIGH);
       digitalWrite(LEDGRpin, HIGH);
       digitalWrite(LEDBLpin, HIGH);
     }
     else
     {
       Serial.println("Not connected");
       delay(1000);
     }
   }
   Serial.println("GSM initialized");
   tone(Tonepin, 950,500);
}

void loop()
{
  //Receiver

   if (sms.available())
   {
     memset(incomingMsg, '\0', 200);
     tone(Tonepin, 1200,1000);
     sms.remoteNumber(remoteNumber, 20);      // Get remote number
     Serial.println(remoteNumber);
     // Read message bytes
     int i = 0;
     while(c=sms.read())
       {  
         incomingMsg [i] = c;
         i++;
       }
     Serial.println("COMPILED MESSAGE");
     Serial.println(incomingMsg);
     sms.flush();      // delete message from modem memory
     if (!strcmp(incomingMsg, "RED OFF"))
      {
       digitalWrite(LEDREDpin, LOW);
       myServo1.writeMicroseconds(1500);
       sendMsg("RED LED is OFF");
      }
      else if (!strcmp(incomingMsg, "RED ON"))
      {
       digitalWrite(LEDREDpin, HIGH);
       sendMsg("RED LED is ON");
       myServo1.writeMicroseconds(1000);
      }
    
     else
     {
       Serial.println("Invalid command");
       sendMsg("Invalid command!");
     }
     }
}
// Sender
int sendMsg (char txtMsg [200])
{
 Serial.print("Message sends to: ");
     Serial.println(remoteNumber);
     Serial.println("Message:");
     Serial.println(txtMsg);
     sms.beginSMS(remoteNumber);      // send the message
     sms.print(txtMsg);
     sms.endSMS(); 
     Serial.println("COMPLETE!");
}

Try the below simple servo test code and see if you still get the issues you describe.

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
  Serial.println("servo-test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    myservo.write(n);
    readString="";
  } 
}

That's why we always ask for the code.
It seems that you have some other hardware and libraries active.
How about using the exact same sketch, with the GSM shield removed, and any GSM shield related line commented out ?
Does that solve your problem at that moment ?
If so, check what that library does.
Perhaps that pin 9 is also affected by the shield (i don't know), you should always check what pins are affected by any shield you plan to use.

So again I'd like to thank to all of you trying to help!
In the meantime I started with a very simple setup without the GSM shield, and everyting worked fine (with zoomkat's code). Everything is OK even with servo connected and powered only through USB.
Then, I reconnected the GSM shield, attached external power supply - and still everything was OK - the code used is here:

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
#include <GSM.h>
#define PINNUMBER "xxxx"
GSM gsmAccess; 
GSM_SMS sms;
Servo myservo;  // create servo object to control a servo 
int Servopin1 = 9; // Servo pin
char incomingMsg[200];  // incoming message
char remoteNumber[20];  // telephone number which sent sms
char c;
 
void setup() 
{
  Serial.begin(9600);
  myservo.attach(Servopin1);
  Serial.println("servo-test"); // so I can keep track of what is loaded
  boolean notConnected = true;
     while(notConnected)
   {
     if(gsmAccess.begin(PINNUMBER)==GSM_READY)
     {
       notConnected = false;
       Serial.println("GSM connected");
     }
     else
     {
       Serial.println("Not connected");
       delay(1000);
     }
   }
}
void loop() 
{
  while (Serial.available()) 
  {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }
  if (readString.length() >0) 
  {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    myservo.write(n);
    readString="";
   }
}

but if I try to do something with the GSM - as in the example below, the pulse width change (and erratic servo movement) is back - regardless if the servo is connected or not.

To eliminate the "power reason", I have separate power for the servo - ground connected, of course - although this is not the issue - the pulse width change is clearly seen on the oscilloscope even if the servo is not connected...

The quick and dirty test code used is here:

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
#include <GSM.h>
#define PINNUMBER "xxxx"
GSM gsmAccess; // include a 'true' parameter for debug enabled
GSM_SMS sms;
Servo myservo;  // create servo object to control a servo 
int Servopin1 = 9; // Servo pin
char incomingMsg[200];  // incoming message
char remoteNumber[20];  // telephone number which sent sms
char c;
 
void setup() 
{
  Serial.begin(9600);
  myservo.attach(Servopin1);
  Serial.println("servo-test"); // so I can keep track of what is loaded
  boolean notConnected = true;
     while(notConnected)
   {
     if(gsmAccess.begin(PINNUMBER)==GSM_READY)
     {
       notConnected = false;
       Serial.println("GSM connected");
     }
     else
     {
       Serial.println("Not connected");
       delay(1000);
     }
   }
}
void loop() 
{
  while (Serial.available()) 
  {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }
  if (readString.length() >0) 
  {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    myservo.write(n);
    readString="";
   }
   if (sms.available())
   {
     memset(incomingMsg, '\0', 200);
     sms.remoteNumber(remoteNumber, 20);      // Get remote number
     Serial.println(remoteNumber);
     int i = 0;
     while(c=sms.read())
       {  
         incomingMsg [i] = c;
         i++;
       }
     Serial.println("Incoming message");
     Serial.println(incomingMsg);
     sms.flush();
     if (!strcmp(incomingMsg, "90"))
      {
       myservo.write(90);
      }
      else if (!strcmp(incomingMsg, "0"))
      {
       myservo.write(0);
      }
     }
}

and what it does? After sending an SMS command "0" or "90", the servo moves to desired position - and then 'oscillates" around it - as the pulse width changes... With clearly noticeable "strikes" of the > 7ms pulse - the same as on my original picture...

So the conclusions I can make so far:

  • the HW itself (GSM shield + servo on pin 9) shall be not in conflict, as the shield can be activated, connected to GSM network - and servo still works fine.
  • The problem starts when the check for incoming SMS is in place - again, it is not an HW or GSM shield issue, as the incoming SMS is processed by the modem first, Arduino only checks if there is an SMS or not (is not involved in the actual SMS receiving)...
  • by now, I have no idea, what can be the root cause of such strange behaviour...

Any advice will be welcomed.
Thanks again to all willing to help!
Jan

From the GSM getting started page:

Communication between the moden and Arduino is handled by the Software Serial library on pins 2 and 3

Apparently the software serial library and the servo library try to use the same hardware timer - they can't co-exist, hence the issue you see.

Thank you for a hint, I'll look into it!