Let's Make Robots!

How, When, Damn it, Why do servos jitter?

I've had a lot of trouble with servo jitter lately, I seem so have solved the problem but I'm not sure why it has worked.

servos.jpgAt first I thought it was the power supply being spiked, no amount of decoupling capacitors solved the problem.

I thought it was software and although my code was improved, the jitter continued.

Because I was using optic sensors, I thought fluctuations in the light is causing my inputs to give false readings. Still no luck and I stubbed my toe in the dark.

The oscilloscope showed clean power and signals to the servo but ocassionally the pulse width changed rapidly.

Still could be software. Debug was slowing the whole thing down too much so I got the picaxe to transmit just the 3 variables I was interested in via the sertxd command and serial cable to the terminal emulator built into the programming editor.

My software was behaving and all of a sudden my servo was behaving. I tried a different servo, same thing, jumps all over the place like a kangaroo in peakhour traffic the moment I removed the sertxd command. So now I'm baffled and wondering if anyone out there knows what is going on. For now I've left the sertxd command in.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Thanks to Frits for his extensive knowledge on servos and picaxe :)

Thankyou Voodoobot for an idea for input filtering I had not previously considered and will use with my sonar sensor )))

Rik, you little ripper! thanx for refurbishing my code with lasers and warp drive. Oh yes, the servo doesn't jitter either :) 

Bugger! It's a hot day today and I have the windows open for the breeze, my object tracker keeps staring at the window like a moth drawn to the light. It shakes it's head occasionally as it attempts to watch the curtains move. I won't be able to test your good ideas till after dinner.

This also means my "Pet Hunter" will have to be nocturnal.

I knew nature was stronger than technology, but this is as simple as daylight. Maybe your creature should evolve its own umbrella (parasol?) in an attempt to bring its own, much needed, darkness.


Hey Oddbot, no worries mate!

I did reproduce your jitters. It's getting late, so I won't go into all the details of my research. (*relieving sigh* by the arties)

Here's what  I did. It may have been suggested above, or before. Dunno.

Right after setting the servo in the new desired position, bring its pin low again. This means that the servo can be easily turned by an external force. At least in between servo commands. That's alright. We come back here soon enough to correct that.

The short code goes like this (servo on pin 1):

  servo 1, b0
  pause 4
  servopos 1, b0  ' not sure if this is needed with the pause 4
  low 1
  ' do other stuff
  goto main


The long code goes like this, but without explanation looks like rubbish:

#picaxe 28x1

symbol svo = 1               ' servo pin
symbol laysor = 5            ' super cool debug laysor
symbol irled = 7             ' IR LED pin
symbol awhile  = 1          ' replacement symbol for the 15 ms pause
symbol amoment = 1          ' similar for the second pause
symbol forcomms = 2         ' pause length just for serial comms
symbol wait4svo = 4         ' pause length for servo

let pins=0
low portc 0,5,6,7
servo svo,150                ' init servo in the center
pause 3000                   ' wait for operator to pay attention 8-)

let b0=150                   ' servo position throughout program
let b1=10                    ' division factor for overshoot protection

  high laysor                               'turn laser on
  servo svo,b0               
  pause wait4svo
  servopos svo,b0                           'Position servo
  low svo
  readadc 5,b2                              'read left ambient light
  let b2=255-b2
  readadc 6,b3                              'read right ambient light
  let b3=255-b3
  high irled                                'Turn on IR LEDs
  pause awhile                              'Allow time for inputs to stabilise
  'gosub time2waste
  readadc 5,b4                              'Front left IR
  let b2=b4-b2      
  readadc 6,b5                              'Front right IR
  let b3=b5-b3-26                           'Calibrate right IR to match left
  let w5=b3*100/121
  let b3=w5+26
  low irled                                 'turn off IR LEDs
  low laysor                                'turn laser off
  pause amoment                             'Allow time for inputs to stabilise 
  'gosub time2waste
  if b2<150 or b3<150 then                  'If Object is within range
    let b2=b2/b1                            'scale variable to prevent servo overshoot
    let b3=b3/b1
    let b0=b0+b3-b2 min 75 max 225          'adjust servo position to track object
    pin0=1                                  'turn on object detect LED
    pin0=0                                     'turn off object detect LED
    if b0>150 then let b0=b0-1 min 150 end if  're-centre servo if object lost
    if b0<150 then let b0=b0+1 max 150 end if  're-centre servo if object lost
  end if
  'sertxd (#b2," ",#b3," ",#b0,13,10)        'Transmit data to emulator
  'pause forcomms
  goto main
   ' on a picaxe 28x1 @ default resonator of 4 MHz
   ' warpfactor   cycletime
   '  255         375   ms
   '  127         190   ms
   '    1           1.5 ms
   symbol warpfactor = 7
   let b24 = 0 do inc b24 loop while b24 < warpfactor




Rik read this:


Yes, you have fixed it, but your fix will not be universal :)

Even when my solution works in two continents, it still would not be universal. My research did not prove why it happens and why the low pin solves the problem. But it turns out it works in this particular instance.

It was every bit a debugging process as Frits described above. That's how the laysors and warp factors entered the code. And got commented out of it again.


My humble object tracker has been upgraded with a debugging laser beam and is now warp capable, factor 7 no less!

From now on I'll have to dip my code in liquid nitrogen befor posting it so it will be cool enough for this site!!

As a bonus I've got people all over the world (well.. 1 person anyway) speaking Aussie :)


Thanx for the help, I'm gonna be busy for a while experimenting with all these ideas.

I always out-comment one line at a time when it happens.

Then inserting one line at a time, I see where the problem is caused.

And trust me, it does not make sense ;)

The instructions are only the top of the iceberg, benieth is a lot of libraries called.. and this is to my experience what is the cause; One thing tripping over the other in the little picaxe-brain, that is not really ment to be multitasking.

When I find the line that causes the jitter to happen (or to re-phrase; A line that together with all else that is going on causes jitter), I then experiement with lowering ports here and there, inserting pause commands (like a few miliseconds) here and there, till that line again can be a part of the program, without causing jitter. Sometimes doing this before that also eliminates the problem.

This way I end up with code that sometimes has strange pauses here and there, or do a few commands in a strange order, but always works rock steady :)

It is also my experience that smaller light weight servos are more likely to be hit from the jitter-flue.

Finaly; It is always better to send fewer commands than more to the servo, and pulsout commands are ofthen parts where it is a good idea to close down a port, or make a small pause. But there IS no rule, and only one fix; the one described above.

I've been think about what you said, especialy the libraries / bootstrap subroutines conflicting. This would explain why the sertxd command had the effect it did. Strange code indeed.
I'm Arty, and I know what I talk about :D