Servo - tiny bug report

14 Nov 2009 . Edited: 15 Nov 2009

When I (foolishly) pass negative values into a Servo, my servos go into a high-speed continuous rotation.

That's potentially quite destructive of the cobbled-together assemblies of wire and gluegun that the servo is driving. Perhaps the Servo library ought to range-check its input ?

Richard

15 Nov 2009

Hi Richard,

Richard Sewell wrote:
Perhaps the Servo library ought to range-check its input ?

Sounds like a good enhancement. The basic logic to extend the Servo functionality could be pretty simple, such as forcing the value to always be in range:

// force a value to always lie within a range
float clamp(float value, float min, float max) {
    if(value < min) {
        return min;
    } else if(value > max) {
        return max;
    } else {
        return value;
    }
}

For those new to coding in C, here is an alternative version using the "(cond) ? true : false" conditional notation (it looks a bit funny as it is nested):

// force a value to always lie within a range (alternative)
float clamp(float value, float min, float max) {
    return (value < min) ? min : (value > max) ? max : value;
}

This should be about all that is needed to be added to the Servo logic to avoid self destruction. I think a worthy update would also include allowing calibration to specify position in degrees and to cope with the bounds clamping for different servos, as the different makes all behave a bit differently in terms of range and ratios.

Simon

16 Nov 2009

Hi,

I've just looked at the Servo class; here is an updated version that supports:

  • Clamping values to within bounds (so you can't overdrive it)
  • Calibration and setting of these bounds (so you can set it to allow maximum movement for that model of servo)
  • Specifying the position in degrees, and the calibration variable to make it accurate.
The code is just part of a project for now, and also includes a simple terminal app to allow finding the appropriate calibration settings.

The approach for calibration is simply to connect up a servo, and move it to it's maximum bounds, then alter the range to see where it starts to strain/buzz (usually you here it as the motor tries to continually move to where it can't). The range (pulsewidth offset from centre) is printed out every time it is changed, and this value can then be used in your code once you've decided what it is.

In the same way, you can measure the offset from centre at the maximum position in degrees, and enter that as the second calibrate argument.

myservo.calibrate(0.0009, 50.0); // +/-range and +/-degrees

Now you'll be able to set the position either using the 0.0-1.0 assignment (like a PwmOut) for maximum range with, or explicitly set the position in degrees (e.g. -45.0 - 45.0) using position(degrees).

myservo.position(-23.0); // set to -23 degrees

Also, there is no fear going outside this range, as the results will be clamped within the supported range of the servo.

I haven't written this up anywhere; lets see if it useful first. Please have a play!

Simon