Servo stability and Digital Signal Processing

Hi,

I've been doing some playing with off-the-shelf radio control and servos with a view to doing something similar with arduino.

I've played with a couple of cheap RC systems. They both seem to manage to achieve rock-solid stability and consistency. If I don't touch the joystick then the servo remains in position without moving, when I move the joystick the servo moves steadily and consistently to it's new position and then stays there, when I move the joystick back the servo moves back.

I've done something very similar with arduino (mega's and mini-pros). I connect the joystick potentiometer to an analogue input pin, I read the analogue value and use that to set the servo position. It works pretty well but to be honest it's just not as good as the RC version. I just can't manage to get the same level of stability of the servo. It will move in proportion to the joystick position, but it suffers from occasional 'twitching' and the twitches are worse during periods of transition (i.e. when I change the joystick position).

When I first encountered this problem I thought it was probably due to differences in the quality of the joystick and the servo. However I've recently tried stripping the joystick and servo from the RC unit and using these on my arduino version but the results are the same - so it can't be these components!

I've done some testing and it's apparent that the arduino itself can accurately and consistently position the servo exactly where it's told to, the problem seems to be with the way the I'm processing the joystick values. Basically I setup the joystick pot. as a 'voltage divider' circuit, I read the values into an array, average them all and use this to set the joystick position. The attached image shows how I've connected the pot..... Don't get me wrong, what I've done actually works pretty well. But what I want to know is what is a cheap chinese RC clone doing that gives such rock-solid positioning consistency using exactly the same cheap components I'm using?

My guess is that the chinese RC version must be doing some digital signal processing to smooth out the values it's getting from the joystick, any suggestions as to what I can do to replicate this?

Thanks

You have not posted the code that “actually works pretty well” so it is difficult to know how it might be improved.

Maybe you need to build in a dead-band so that minor variations in the value detected by the ADC are ignored?

…R

You have not posted the code that "actually works pretty well" so it is difficult to know how it might be improved

I'm not actually asking for a 'code fix' I'm asking for some suggestions on technique and general approaches to the problem.

I already incorporate a dead-band, any changes that will result in a change of less than 1 degree of movement will be ignored. The problem with this approach is that some smoothness is lost.

I've tried monitoring the analogue voltage from the potentiometer (A0 on the above diagram) with a voltmeter, and its apparent that when the joystick is actually moved there can be large (but brief) fluctuations which can effect not only the instantaneous value from the ADC, but also the average.

As mentioned I load all the joystick values into an array, I've tried taking the average (mean) value, the mid-position (median) value, and the most frequently occurring (modal) value. They all give similar results, but none of them produce the stability I would like. I've also tried varying the number of samples held in the array, and the frequency at which the samples are taken.

I'm wondering if professional servo control units might use some sort of PID algorithm to smooth the values?

My guess is that the chinese RC version must be doing some digital signal processing to smooth out the values it’s getting from the joystick

It probably is doing two things.

One, it is probably reading the potentiometer position several times, averaging the readings.

Two, it is probably only sending a new value when the new value is significantly different from the previous value sent, for some definition of “significantly”.

You, too, can do both of these things.

Fulliautomatix: I already incorporate a dead-band, any changes that will result in a change of less than 1 degree of movement will be ignored. The problem with this approach is that some smoothness is lost.

That sounds very coarse. Using Servo.writeMicroseconds() gives you finer control. With an ADC range of 1023 you should in theory be able to move in increments of 0.175 degrees (180/1023). With a deadband maybe increments of 0.3 or 0.5 degrees would be possible.

Smoothing might also be helped by sending changes in small increments. For example when the indication from the ADC is for (say) 2 degrees implement that as 4 steps of 0.5 degrees. (I have never tried this).

...R