Smoothing or averaging input values for a servo.

Hi,

I’ve written a library for controlling a couple of servos from a potentiometer-based joystick. I’ve got a system that works but I want some advice on whether my solution is the best or not.

The joystick consists of a pair of potentiometers connected via about 5 meters of cable to an arduino mini connected to a pair of servos. Both the pots in the joystick are connected as voltage dividers, the output from each voltage divider is connected to an analogue input pin to give a value from 0 to 1024 representing the joystick position.

The problem....
Is that the value that gets picked up on the analogue input pin is continuously varying (slightly). I believe this is either due to the length of the joystick cables, or the quality of the joystick (or voltage drop over the cable length). If I attempt to use this value to drive the servo directly, then the servo suffers from constant wobble.
My solution....
Is to load the values from the joystick pots into an array and take the average of these values to drive the servos. Basically, rather than using the current instantaneous joystick position to set the servo position, I use the average joystick position taken over the last half second or so.

My solution works just fine, but I’m not convinced there’s not a better way of doing it. The biggest issue is probably memory usage, I store and average 100 different samples of the joystick position, 2 bytes for each value and a total of two servos means I’m using 400 bytes of memory to smooth the joystick – that’s a big chunk of the available memory in for a arduino mini! I can reduce the size of the array, but the smoothness of the output seems to be directly proportional to the size.

So, my question boils down to this.... is there a better way of smoothing or average the joystick input values?

Thanks

Have you tried adding a Cap across the Analog input pin?

Also, Atmel's ADCs tend to just have jitter in them. Another option would be to discard the last 1-2 bits of data. I have however gotten decent work out doing a rolling average of the last 4 samples.

Or simply move the pots to the Arduino, and put the servos at the ends of the 5metre cable.
Or the ever popular avg = ((avg * 7) / 8) + (newReading / 8);

Have you tried adding a Cap across the Analog input pin?

Not yet - I'll give it a go!

move the pots to the Arduino, and put the servos at the ends of the 5metre cable

This is a possibility, but the power is provided by a regulator in the same package as the arduino, so 5 meters of cable might lead to a bit of a voltage drop.

Or the ever popular

avg = ((avg * 7) / 8) + (newReading / 8);

Looks good - I'll give that a try!

Both mr2b and robtillaart posted some analogRead smoothing code here:

http://forum.arduino.cc/index.php?topic=190305.0

It sounds as if you have already confirmed that in this case the jitter is caused by variations in the input, but bear in mind that some servos do inherently jitter under some conditions anyway.

I tinkered with the below test code a while back for a joystick controlled pan/tilt cam. This has a dead band setup to limit the cam jittering. The delay is just for easier viewing using the serial monitor.

//zoomkat dual pot/servo test 12-29-12
//view output using the serial monitor

#include <Servo.h> 
Servo myservo1;
Servo myservo2;

int potpin1 = 0;  //analog input pin A0
int potpin2 = 1;

int newval1, oldval1;
int newval2, oldval2;

void setup() 
{
  Serial.begin(9600);  
  myservo1.attach(2);  
  myservo2.attach(3);
  Serial.println("testing dual pot servo");  
}

void loop() 
{ 
  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){  //dead band setup
    myservo1.write(newval1);
    Serial.print("1- ");
    Serial.println(newval1);
    oldval1=newval1;
  }

  newval2 = analogRead(potpin2);
  newval2 = map(newval2, 0, 1023, 0, 179);
  if (newval2 < (oldval2-2) || newval2 > (oldval2+2)){  
    myservo2.write(newval2);
    Serial.print("2- ");    
    Serial.println(newval2);
    oldval2=newval2;
  }
  delay(50); //delay for easier value viewing in serial monitor
}

Hi.

This is a possibility, but the power is provided by a regulator in the same package as the arduino, so 5 meters of cable might lead to a bit of a voltage drop.

Are you using the Arduino's 5V output, if so it is not recommended as most servos do consume quite a bit of current.
Try supplying the servos with their own 5V supply, remember to connect the arduino gnd and the servo supply gnd together so that the control circuit has a current return.

Tom..... :slight_smile:

The voltage divider circuit in the joystick is using the arduinos 5v supply. The servos themselves have a dedicated 6v regulator, they share the same earth.

Thank for your help everyone. Why can't the ebay support line be as quick and helpful as this forum?

cheers