Servo driver - big gaps in sending

I’m trying to help someone in this thread.

The results are unexpected, for me, so obviously I don’t understand servo motors properly.

Code:

#include <Servo.h> 

Servo myservo;  

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

void loop() 
{ 
  myservo.write(35);
}

Results on pin 9:

The poster’s problem is slightly more complex than that, but I’m wondering why the 3-second gaps in output to the servo? I presume you aren’t supposed to use them that way?

Looking at the other thread as well as this, I wonder if things would work perfectly if the servo is only written to whenever its position needs to be changed, and not every loop. Presumably when you do servo.write() it goes through some sort of "resetting" process that may account for the gap. Is it possible that the size of the gap is just influenced by the Arduino being busy doing other stuff? Also, loop should repeat very quickly compared to servo signals.

...R

Yes, but in the other thread, that is what he does:

void loop() 
{ 
  myservo.write(35);
  delay(2000);
  myservo.write(135);
  delay(2000);
}

The delays therefore mean the servo is being changed every two seconds, which doesn't really account for one-second gaps when no servo signal is being sent.

Sounds weird - the Servo library is entirely interrupt driven (write and writeMicroseconds
only update slots in the datastructures used by the interrupt handler.

Disabling interrupts would cause gaps of course, but delay() doesn't do that.

Out of RAM? buffer overrun? Loose connection?

How could this code be out of RAM?

void loop() 
{ 
  myservo.write(35);
}

But yes, I'm prepared to believe anything right now. If someone else could reproduce this, or not reproduce it, that would at least confirm if I am going mad, or not.

I don't really buy the "loose connection" argument, it's not as if the cat is batting the test bed (although he's been known to do strange things, he isn't in the room at present).

I'll try compiling on another PC, and see if that changes things.

I compiled and uploaded on my Windows PC. That gave the same results. The length of the "active" part is 900 mS.

Having jumped in rather hastily earlier it occurs to me now to ask what your 'scope picture is showing?

What are the yellow bits, and what are the black bits?
The yellow bits look like a compressed square wave ... what are they like if you expand them?

I would expect that following servo.write() there would be an indefinite unbroken signal with pulses of a constant width between 1ms and 2ms (?) repeating at least every 20ms. On that basis there would be no gaps like in your image - unless, perhaps, you did servo.detach() (if that's the correct code).

The implication seems to be that something behind the scenes is interfering with the servo signal.

Have you connected a servo to your Uno to see how it behaves while the 'scope is producing that picture?

I will try some tests later today.

...R

Is this just a scope aliasing effect?
The displayed frequency looks right for continuous 20ms updates.

I'm interested to see your conclusion. Are the yellow blocks many cycles 20 ms apart?
I prefer this:

So, to be clear, you are getting this outcome without trying to do GPS or anything else, at the same time ?

Simple servo test code you can use with the serial monitor to evaluate different servo command outputs.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// 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.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7, 500, 2500);  //the pin for the servo control, and range if desired
  Serial.println("servo-test-22-dual-input"); // 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

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

I've written a short sketch on a Mega (because it was there) which records the state of pin 8 every 500 usecs.

I've also uploaded Nick's first sketch to an Uno and I have connected the servo output (pin 9) to pin 8 of the Mega.

Over 500 samples the Uno seems to be sending uninterrupted pulses to the servo every 20 msecs (every 40 samples). I also have a servo connected and it works fine.

I can't imagine it makes any difference but this was done with an XUbuntu netbook and Arduino IDE 1.0.5

...R

I just put the code in the OP onto an Uno.
My scope (Rigol DS1052E) sees no gaps (as expected) on a 1 second/division range, though interestingly it doesn't correctly display the frequency (shows 5Hz) on this range, and I have to drop to 100ms/division to get it to display anything like 50Hz.
I don't actually have a servo connected.

Robin2:
Having jumped in rather hastily earlier it occurs to me now to ask what your 'scope picture is showing?

What are the yellow bits, and what are the black bits?
The yellow bits look like a compressed square wave ... what are they like if you expand them?

The yellow bits are the square wave, the black bits are no square wave. Zooming in:

I would expect that following servo.write() there would be an indefinite unbroken signal with pulses of a constant width between 1ms and 2ms (?) repeating at least every 20ms.

I'm glad to hear you say that, because it repeats every 20 mS.

The width of the pulse is 900 µS:

I presume that is about right for positioning to 35 degrees?

michinyon:
So, to be clear, you are getting this outcome without trying to do GPS or anything else, at the same time ?

That is correct. I am running the code in the original post with no hardware connected at all except for a scope on pin 9 (and Gnd of course). On a Uno, IDE 1.0.5.

Further testing indicates that this appears to be an aberration of this particular scope. Running in the "slow" mode it looks like it is capturing a batch of points, drawing them, and leaving a gap.

The logic analyzer shows no such gaps.

Oh well, back to the other thread to try to sort out the original problem. :slight_smile:

Thanks to everyone that tested. Your results showed my testing itself was at fault.

Well, that's some sort of progress.

I think I simulated the situation your scope showed with the following code

void loop() 
{ 
  myservo.write(35);
  delay(2000);
  myservo.attach(8);
  delay(2000);
  myservo.attach(9);
}

When I run this and push the servo arm with my finger the force collapses when the signal stops (i.e. when myservo.attach(9) operates) and reasserts itself when the signal is restored. This is very obvious when the servo is under load, but not noticeable without a load.

...R

Yes, but the original problem stayed with the same servo. I better try to reproduce that now.

AWOL:
I just put the code in the OP onto an Uno. My scope (Rigol DS1052E) sees no gaps (as expected) on a 1 second/division range, though interestingly it doesn’t correctly display the frequency (shows 5Hz) on this range, and I have to drop to 100ms/division to get it to display anything like 50Hz.I don’t actually have a servo connected.

Perhaps the 50hz used with the servo h-bridge is generated in the internals of the servo itself. Interesting servo info below.

http://www.seattlerobotics.org/encoder/200009/S3003C.html

Perhaps the 50hz used with the servo h-bridge is generated in the internals of the servo itself

It seems to me to be more economical to use a roughly 50Hz time base derived from the input PWM frequency.