Change servo speed?

Hi,

Is there a way for me to slow down the speed of a servo?

It’s not the end of the world, but it’s running a bit fast which means it’s making a lot of noise.

It’s a normal 180* servo, not a continuous one, which I know would be easy to do, but I want it to be precise in it’s movements.

Here’s my code, if you can help I’d really appreciate it.

Thanks

Tim

Servo timservo; 
Servo louservo;// create servo object to control a servo
                // a maximum of eight servo objects can be created

int timpos = 0;    // variable to store the servo position for timservo
int loupos = 0;    // variable to store the servo position for louservo
 
void setup()
{

//Setup the Servo to the function 
Particle.function("timservo", updatetimServo);
//Set pin D0 to be an output
pinMode(D0, OUTPUT);
//Attach the servo to D0
timservo.attach(D0);
//Setup the Servo to the function 
Particle.function("louservo", updatelouServo);
//Set pin D0 to be an output
pinMode(D1, OUTPUT);
//Attach the servo to D0
louservo.attach(D0);
//Take control over the LED on the board
RGB.control(true);
//Turn off the LED - we dont want it flashing behind the photo frame at night
//There may be a better way to do this like turning it off, I found it just as easy to set the colour to nothing
RGB.color(0, 0, 0);
}
 
void loop()
{
// We don't need to do anything here
 
}
 
//This function is triggered by IFTTT - the 'command' word represents the object used to store the 'position' we send to the function.
//The 'position' we send represents where we want the servo to move to
int updatetimServo(String command)
{
//Convert string to integer, the code after this requires the 'command' object to be in a number format. IFTTT however passes the object as a 'string' even if it is a 'number'.
uint8_t timpos = command.toInt();
//This tells the servo, attached to D0 to move to the position defined in the 'command' object that was passed when we triggered this function from IFTTT
timservo.write(timpos);
//Flash the LED on so we can see that a message has been recieved - just because we can
RGB.color(255, 0, 0);
//Remember to add the delay for 2 seconds, otherwise the LED will just flash for a period of time too small for us to see
delay(2000);
//Now set the LED back to off
RGB.color(0, 0, 0);
//We return something to signify the end of the function - doesn't really matter what it is
return 1;
 

  }
  

  
//This function is triggered by IFTTT - the 'command' word represents the object used to store the 'position' we send to the function.
//The 'position' we send represents where we want the servo to move to
int updatelouServo(String command)
{
//Convert string to integer, the code after this requires the 'command' object to be in a number format. IFTTT however passes the object as a 'string' even if it is a 'number'.
uint8_t loupos = command.toInt();
//This tells the servo, attached to D1 to move to the position defined in the 'command' object that was passed when we triggered this function from IFTTT

delay(5000);

louservo.write(loupos);
//Flash the LED on so we can see that a message has been recieved - just because we can
RGB.color(0, 0, 255);
//Remember to add the delay for 2 seconds, otherwise the LED will just flash for a period of time too small for us to see
delay(2000);
//Now set the LED back to off
RGB.color(0, 0, 0);
//We return something to signify the end of the function - doesn't really matter what it is
return 1;
 

  }

you can put a delay (prefer non-blocking!!) in between servo writes and work your way across the delta more slowly.

I would take the servo write out of your Particle.function() and just update the target direction. Then in loop() you can write a function that is always being called to move the servo (until the target == currentPosition).

4 Likes

@timtiernan,

you can try like this example:


const int ROTATION_DELAY = 25; // Play wiht this number, 25ms looks smooth and was quiet on my servo

struct MyServo{
  byte rgbColor[3];
  int target;
  int actual;
  unsigned long lastUpdateMillis;
  Servo* servo;
  int pin;
  // not used here //void begin(int pin) {servo = new Servo; pinMode(pin, OUTPUT); servo->attach(pin); servo->write(actual);} ;
  void begin(int pin, byte r, byte g, byte b) {this->servo = new Servo; pinMode(pin, OUTPUT); servo->attach(pin); servo->write(actual); rgbColor[0] = r; rgbColor[1] = g; rgbColor[2] = b; } ;
};

//Tim's Two MyServo objects:
MyServo timServo;
MyServo louServo;

void updateServo(MyServo& servo);

void setup()
{
  Serial.begin(9600);
  Particle.function("timservo", setTimServo);
  Particle.function("louservo", setLouServo);
  Particle.variable("timPos", timServo.actual);
  Particle.variable("louPos", louServo.actual);
  // begin() initializes the servos and sets them to position zero... don't use this method outside of setup()
  timServo.begin(D0, 0, 0, 255); // (PIN for Servo, RED, GREEN, BLUE) values RGB LED
  louServo.begin(D1, 0, 255, 0);
}

void loop()
{
  updateServo(timServo);
  updateServo(louServo);
}

void updateServo(MyServo& servo)
{
  if(servo.target == servo.actual)
  {
    return;
  }
  unsigned long nowMillis = millis();
  if(nowMillis - servo.lastUpdateMillis > ROTATION_DELAY)
  {
    RGB.control(true);
    RGB.color(servo.rgbColor[0], servo.rgbColor[1], servo.rgbColor[2]);
    Serial.printlnf("Actual:%03d, Target:%03d", servo.actual, servo.target);
    if(servo.actual < servo.target) servo.actual++;
    else servo.actual--;
    servo.servo->write(servo.actual);
    servo.lastUpdateMillis = nowMillis;
    if(servo.actual == servo.target) RGB.control(false);
  }
}

int setTimServo(String command)
{
  uint8_t timpos = command.toInt();
  if(timpos >= 0 and timpos <= 180)  // you may have to adjust if (like me) you don't get a full 180 degrees of rotation on your servos
  {
    timServo.target = timpos;
    return timpos;
  }
  return -1;
}

int setLouServo(String command)
{
  uint8_t loupos = command.toInt();
  if(loupos >= 0 and loupos <= 180)
  {
    louServo.target = loupos;
    return loupos;
  }
  return -1;
}
2 Likes