Servo jtter - found a low level workaround - do i understand this?

Hello all,

I was getting a lot of jitter on a servo that was going into a pan and tilt system and I posted thread a few months ago Resolution question - 12 bit servo, 8 bit Arduino Ethernet - Project Guidance - Arduino Forum and learned that pin 5 has a higher than expected duty cycle and faster freq than the other PWM pins. The servo that was giving me problems was on pin 5 and I moved it to pin 9 and I got rid of the jitter. I let the project go and came back to it recently and I noticed that the jitter is still there. In the old thread, andsetinn posted a link in which someone else had servo jitter problems and showed how they fixed the problem.

andsetinn:
Apparently the Arduino Servo library has limitations that can cause servo jitter. This guy has written a workaround. http://www.karlssonrobotics.com/tutorials/arduino/workaround-for-servo-jitter-on-arduino/ It may not fix your problem but is worth a try.

I had no clue what this code was telling me. I then started reading the ATmega328P data sheet to understand the PWM better and figure out how I can use that code as a basis for my code. I have an okay grasp on what everything is doing inside the code from Karlsson Robotics now. From my understanding, the code creates the variables, sets them up, then initializes the registers for PWM and commands the WGM and CS to be in CTC mode. From there he makes a main loop and an interrupt for the PWM. Inside that interrupt loop is where I am lost. So every time TCNT0 (Time/Counter 0) = OCR0A (Output compare register), it goes into the Interrupt loop and TCNT0 resets to 0x00 - correct? Pin 8 is the pin used for PWM and is oringally set high and then a counter (motorcount) is used to tell the motor to turn on and off. Once motor count hits 999, it resets. So that means that every time TCNT0 = OCR0A, 999 and then restart - correct? In that case, the PWM signal will be based on motorcount setting pin 8 to high/low - correct?

Now here are my problems with this. I read that if I wanted to use motors, I should use Phase PWM because it gives better frequency resolution. I've also read that changing timer0 will cause things like millis() to be off - which I use in my main code. Therefore, wouldn't I want to use a TCNT2? If so, what pins are those exactly? I forget how I found which pins go to which timers a few months back, but I know they do - I'm 99% sure 5 and 6 go to timer0.

EDIT:
I found pin 3,11 timer 2 and pin 9,10 timer1 in my notes. I am using an Arduino Ethernet set up as a server, sooo... what exactly will changing timer2 do to my Ethernet communications?

What are your thoughts? I haven't started writing code yet. I am still not 100% sure what I'm supposed to do. From my understanding though, I'd want to set up the timer in the void steup() area and then have an ISR which does my PWM.

ALSO:
I am currently using a custom servo library, VarServoSpeed. It allows me to move the servos slower than the standard motion - when using the normal library, the servos went to places too fast and I was afraid something may get loose mechanically and get flung to somewhere.

Thanks for reading, Hopefully I explained myself well enough
Matt

For those that can't see the code, it is posted here.
Initialize timers

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 50khz increments
  OCR0A = 4;// = (16*10^6) / (50000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 and CS10 bits for 64 prescaler
  TCCR0B |= (1 << CS11) | (1 << CS10);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

Interrupt Loop

ISR(TIMER0_COMPA_vect){
//timer0 interrupt 50kHz to drive servo motor connect to pin 8
// pulse width is 1 ms in motor state '0' and 2 ms in motor state '1'
switch(motorenabled){
  case 1:
    motorcount++;
    switch(motorstate){
      case 0:
           if(motorcount>motorstate0){
             digitalWrite(8,LOW);
           }
           if(motorcount>motormax){
             motorcount=0;
             digitalWrite(8,HIGH);
           }
       break;
       case 1:
           if(motorcount>motorstate1){
             digitalWrite(8,LOW);
           }
           if(motorcount>motormax){
              motorcount=0;
              digitalWrite(8,HIGH);
           }
       break;
    }
    break;
  case 0:
    ledcount--;
     if(ledcount==0){
       switch(ledstate){
         case 0:
         ledstate=1;
         digitalWrite(ledPin, HIGH);
        ledcount=ledontime;
        break;
        case 1:
             ledstate=0;
         digitalWrite(ledPin, LOW);
        ledcount=ledofftime;
        break;
      }
    }
  }
}

All of the technical information you need is in the Atmel datasheet for the microprocessor you are using.

Before spending a lot of time writing your own servo control code you should experiment to find out how the servo behaves if it is supplied with a pulse of a constant width. No amount of programming the Arduino will solve your problem if the servo jitters when it receives a constant-width pulse.

As you seem to have access to an oscilloscope the first thing might be to monitor the pulses produced by the standard servo library to see if the pulse width is constant within an acceptable margin of error.

You seem to have said that a solution that was working at the end of your other Thread is not now working. That doesn't sound like an Arduino problem.

...R

Thanks for the response,

My problem is a bit mechanical and a bit electrical from what I can gather. When things get tightened down well, my system works fine. However, over time, things get a bit sloppy and the jitter comes back. I have HS-M7990TH servos - high torque, programmable, and digital. When I hook them up to the "official" software which programs them, the servos work perfectly fine and there is no jitter.

My thoughts on the issue are that, yes, it can be solved mechanically, but I feel like that just putting a tourniquet on the wound instead of fixing the problem.

I plan on looking at both PWM outputs today - Arduinos and the servo's official software - and see if I can tell a difference.

I did some more research into PWM and I have a few questions about the SPI and timers, so I am wondering where I should post a thread with my question. I know that this thread would not be the best issue.

Thank you,
Matt

So I finally got the two signals on my oscope and I took a zoomed in look at them. I am not the best with mu current oscope - haven't worked with it too much - so it took me two pictures to get everything set up. I couldn't figure out how to upload an image to this site, so I created a drop box link for both.

Image from the servo's PWM (HPP-21)
https://dl.dropboxusercontent.com/u/60210515/HPP-21_PWM.jpg

Image from the Arduino PWM
https://dl.dropboxusercontent.com/u/60210515/Arduino_PWM.jpg

One thing that was clear to me was that the HPP-21 took a lot longer to reach max voltage - 3.65 us - than the Arduino - 24 ns. Also, the Arduino over shot the 5V mark by ~.3V giving it a max 5.32V voltage at the spike.

I don't know servos well, but can that sharp rise and fall time be a problem with the overshoot?

I'm way out of my depth here, but I think the only thing that matters is how long is the pulse, and your scope pictures don't show that. I would expect the jitter to arise if successive pulses have widths that differ by a significant amount - so you would need a picture of, say, 5 pulses.

I'm very surprised at the gentle rise in your picture. I thought all digital signals would be like the Arduino signal.

...R

Anything after 3 pulses and the pulse width varies from 1480-1520, which I believe to be a resolution issue not a pulse width issue.

https://dl.dropboxusercontent.com/u/60210515/3_pulse_PWM.jpg

Also, where would be a good place to post a question about changing timers? I think I'm going to have to adjust one timer if I write my own code and I want to make sure that I wont mess anything else up if I change a timer.

Matt

How did you get the data for pulse width variation? Your screenshot shows 1500.

What do you mean by "a resolution issue" - do you mean the inability of the oscope to resolve things or the inability of the Arduino (or both) ?

Is that level of variance unacceptable to your servo? Can you alter the deadband to match?

None of this explains why there was no problem previously and now there is a problem.

I don't know what timers the regular Arduino software uses. There is a servoTimer2 library (which I have used) which suggests that timer2 is not normally used. if you haven't tried servoTimer2 maybe it would be worth investigating first. I think I got the code here Digital Modellbahn - Browse /Arduino (v1.0) libaries at SourceForge.net

Maybe the servoTimer2 code would be a good starting point for your own code if it does not solve the problem itself. Careful study of it seems advisable.

...R

I haven't tried other pulse widths, but my assumption is that it would be the same for all pulse widths. I don't see why either would vary with rise time or incorrect pulse width if I commanded a new pulse width (I command 1750 and it gives me 1780).

As for resolution, I mean with respect to the oscope. If I "zoom in" on a pulse, I can get much cleaner details of said pulse but if I zoom out I get more rounded numbers. The way I see it, its like saying my oscope has 1000 points it can use on screen and if I zoom in on one pulse, that pulse can take up 800/1000 points. However, if I have to zoom out, to have three pulses on screen, then the pulses would use 300/1000 which would mean each pulse would have 100/1000 spots on the oscope.

I don't fully understand the deadband, but what I know is that when I increase my deadband area, the jitter is more pronounced.

I went to the communications section on these forumns and someone informed me that SPI doesn't really use the timer1 feature, it is just used as a normal pin. Which is great news for me. I can use timer1 on pin 9 and write my own code.

Matt

So I finally took my system apart and took my oscope to the actual servo being stressed and I found these attached pictures. One is with freq, ride time, Vpp, width, and Vmax showing, the other uses the cursors to see how large the dip in signal is. Attached are both pictures.

Any thoughts on how to clean up the signal?

Matt

I would be very surprised if it is necessary to "clean up the signal". I would expect servos to be designed to work in a noisy environment.

If I am interpreting your comments correctly your Arduino produces consistent pulses even if they may not be exactly the same width as the program code demanded. If you are getting consistent pulse widths then I think you should be looking elsewhere for the cause of the jitter.

I can't recall if I mentioned it earlier in this thread, or in a different thread, but it may be worth seeing what happens if you put a 4k7 resistor between the servo signal and ground. A substantial (100uF?) capacitor between the servo power and ground wires might also be worth trying.

Have you written a very short Arduino sketch that does nothing but drive the servo? How does that perform?

Have you tried the servoTimer2 library?

...R

I tried putting in a 4.7k resistor along the PMW signal path and the signal still looked the same. I also zoomed in on 1 pulse and the width is 1500 us like I command. The reason I'm wondering about the signal is because every time there is a large jitter, it shows up on the oscope as a "glitch" (or whatever you call the dip in signal voltage).

I haven't worked on writing my own code yet. Mainly, I know what to start, but I don't want to have conflicting servo code because I'm not 100% sure where all the parts go yet.

Also, I tried putting the servo pulses through a buffer and it made it worse...

I tired putting the 4.7k in series with the pulse, that was worse, and so was the 4.7k from pulse to ground. Nothing worked there. Guess I should start trying to code...

The drop in voltage that coincides with the glitch sounds like a shortage of amps and may be the effect of the glitch and not the cause. That's why I suggested a large capacitor across the servo Power and Gnd.

I would try putting a voltage divider on the signal line to find out what is the lowest voltage that will work the servo. If the "glitches" don't bring the voltage below that level then it's unlikely to be the low voltage that is causing the glitches.

What about using the resistor to bridge the signal line to +ve (i.e. holding the line high unless the Arduino pulls it down).

Can you describe the glitches in detail. What exactly happens and how often? Can you predict when it will happen?

...R

The servos are powered by my power supply which also powers the Arduino which sends the signal. So in otherwords, the servos are in parallel with eachother and the Arduino. The only thing the Arduino is doing is providing a PWM train to the servos. I know that the servos can't be powered by the Arduino, it isn't meant to handle something that large. I think people are give a 12V .5A wall wart ps with each arduino and rough math says that's like 6W which is not enough to power my servos. From the manufacturers website, they say that the signal should be 3-4V with a refresh rate of 20 ms and a "high time" between .9 ms and 2.4 ms with 1.5 ms in the middle. Which is another reason why I'm a bit confused because it doesn't look like the servo signal doesnt drop that low on my oscope.

I wired up a pull up resistor and it basically made the jittering more pronounced. I then zoomed in on the rise time and noticed that the signal jumps up to ~7V, so I did a LPF on the signal for 550 Hz - that's components I had laying around - and the signal looks nicer, but its still jittering. Attached is a zoomed in picture of the servo signal under stress at rise time.

I think the instantaneous current from time to time is too much from the Arduino. Would A driver IC work in this case?

EDIT:
I forgot to describe the "glitch". Its basically just it jittering but now I can see it on my oscope as a divot on the 5V line. It even if the divot isn't on the 5V signal, I can still see it popping up every now and then on the ground line. It seems like it is a bit random as to when it shows up, but it does.

Matt

Please describe your power supply arrangements in detail with a wiring diagram.

0.5Amps isn't nearly enough to power a servo, never mind the servo and the Arduino - it's probably barely enough for the Arduino.

If you have a 12v power supply how are you producing the lower voltage needed by the servos?

What do you mean by

it doesn't look like the servo signal doesnt drop that low on my oscope

?

I really think you need to change your mindset. Assume the Arduino provides perfectly adequate pulses and look for the problem elsewhere. Countless problems in threads here have been due to an inadequate power supply where people have mistaken the symptoms for an Arduino problem. Try using your scope to watch the servo power supply.

...R

Standard hobby servos have been known to exhibit jitter behavior when they are supplied more than the recommended 6v.

Uploaded is a pic of the power situation with my Arduino. It is a simplified version, but it gives the main idea. The LPP-100-7.5 power supply gives 13.5A at 7.5V. That powers the servos and Arduino. The Arduino just provides a PWM signal to the servo. That's it. The servos are optimized at 6.4, they are meant for large scale RC automotive.

I don't think its that my servos aren't getting enough power, i think the the arduino isn't providing a strong enough signal to the servos. I'm going to try and put a driver on my signal and then take it to the servos to see if that fixes it.

Matt

The servos are optimized at 6.4, they are meant for large scale RC automotive.

Do you have a link to those servos?

I don't think its that my servos aren't getting enough power, i think the the arduino isn't providing a strong enough signal to the servos.

I've used standard hobby RC servos with the arduino with the arduino using the servo library and never seen noticeable jitter. My servos were being supplied at 5.7v. The below link is somewhat dated, but should give you some idea of the internals of a standard hobby servo.

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

Your diagram is clear but it doesn't give any indication of the physical layout of the wiring. For example are there long wires from the battery to the servos? Are those wires heavy enough to carry the current? What sort of connectors are you using? Is the servo current passing through PCB traces?

Are there separate wires from the battery to the Arduino? Or is the Arduino fed from wires that also carry the servo current?

Have you tried the servos, the Arduino and the battery without anything else connected and with a minimal sketch?

Have you tried powering the Arduino with a separate battery?

...R

Zoomkat,

Correction, they are 7.4 optamized. Here is their link - HS-M7990TH High Voltage, Mega Torque, Magnetic Encoder Ultra Premium Servo | HITEC RCD USA. I failed to mention that their feedback is based on a 12bit encoder instead of a pot. That may be important, I'm not 100% sure.

Variable Speed Control Modification to the Futaba S3003 RC Servo

So the feedback is just there to make sure that the servo doesn't over shoot while the pulse is there to move the servo? So if I'm getting a problem with the jitter, would that be feedback?

Robin2,
The servos are connected to the power supply directly. I made a custom shield for my Arduino Ethernet which takes the PWM pulse and puts it to a 2 pin MTA header- http://www.digikey.com/product-detail/en/640454-2/A19423-ND/258984 - The female part is connected to a wire which goes directly to the servos. I'm positive that the wire which connects the servos is strong enough to handle the current. Also, the wires are all less than 2 feet long, and most are less than 6 inches.

The battery in the last picture is actually an AC-DC converter, I just didn't draw it in because I'm not using any AC in my system.
Matt