Getting a Servo to move within a given time frame

Hi all,

I'm working on a project where an arduino is sent a JSON message that contains two fields - the angle the servo should move to, and the time it should take to get there.

I have the JSON Decoding bit working, but for some reason I can't work out the "move over this amount of time" bit.

My code is as follows:

// Receive message as {"angle": "123", "duration": "5"}
// Angle is degrees to point to, duration is time in seconds to get there
void callback(char* topic, byte* payload, unsigned int length) {
  StaticJsonDocument<256> doc;
  deserializeJson(doc, payload, length);
  JsonVariant new_angle_tmp = doc["angle"];
  int new_angle = new_angle_tmp.as<int>();
  int duration = doc["duration"];
  // Is the new angle greater than the current angle?
  // If so, increase the current angle until we reach the target position.
  if (new_angle > current_angle){
      // Work out the delay by multiplying the duration by 1000 to
      // turn it into seconds, then divide that by the number of
      // degrees that we need to move to get the delay between each step
      int step_delay = (duration * 1000) / (new_angle - current_angle);
      if (step_delay < 1){
          step_delay = 15;
      }
      Serial.print(new_angle);
      Serial.print(" is greater than ");
      Serial.print(current_angle);
      Serial.println(" - Increasing current angle");
      while( new_angle > current_angle){
          current_angle = current_angle + 1;
          servo.write(current_angle);
          delay(step_delay);
      }
  }
  // The new angle is less than the current angle, so
  // we do the same as above, but this time we decrease until we
  // reach the target position.
  else if (new_angle < current_angle){
      int step_delay = (duration * 1000) / (current_angle - new_angle);
      if (step_delay < 1){
          step_delay = 15;
      }
      Serial.println(step_delay);
      Serial.print(new_angle);
      Serial.print(" is less than ");
      Serial.print(current_angle);
      Serial.println(" - Decreasing current angle");
      while( new_angle > current_angle){
          current_angle = current_angle - 1;
          servo.write(current_angle);
          delay(step_delay);
      }
  }
  // If we've got this far, then the angle sent is 
  // the same as the angle we're currently pointing at,
  // so we don't need to do anything
  else {
      Serial.println("No need to rotate");
  }
}

I'm sure this is a really simple fix, I've just been banging my head against the wall for a good few hours trying to work out why it always moves at the same speed, and why the "decrease" side of things doesn't move it at all!

That 'while' won't do anything. You probably meant:
while( new_angle < current_angle) {

I knew it would be simple. OK, so that explains why it's not moving in the appropriate direction, thanks.

Now to work out why it takes exactly the same amount of time to move from location to location regardless of what the "duration" is set to...

I see you deserialize 'duration' differently from 'angle'. Maybe you should display the value you get for 'duration' to see if it is deserialized correctly.

Personally, I think you want:

  int new_angle = doc["angle"].as<int>();
  int duration = doc["duration"].as<int>();

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.