Execute loop for an assigned time frame

Hello,

I want to have a code that executes a while loop for a specified amount of time that is given to the serial monitor.

This is my current code:

#include <DynamixelShield.h>

DynamixelShield dxl;
const uint8_t DXL_ID_1 = 1;
const uint8_t DXL_ID_2 = 2;
const uint8_t DXL_ID_3 = 3;

const float DXL_PROTOCOL_VERSION = 2.0;

float distance_to_time = 60 / (34.2 * 2 * PI * 10);

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  delay(10);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    String mess = Serial.readStringUntil('.'); // input values are time "__,__,__,__."
    Serial.print("Input values: ");
    Serial.println(mess);
    delay(10);

    int mess_1 = mess.indexOf(','); // this value represents the amount of time you want to activate motor 1
    String distance1 = mess.substring(0, mess_1); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_2 = mess.indexOf(',', mess_1 + 1); // this value represents the amount of time you want to activate motor 2
    String distance2 = mess.substring(mess_1 + 1, mess_2); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_3 = mess.indexOf(',', mess_2 + 1); // this value represents the amount of time you want to activate motor 3
    String distance3 = mess.substring(mess_2 + 1, mess_3); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_4 = mess.indexOf(',', mess_3 + 1); // this value represents the amount of time you want to activate linear servo
    String position4 = mess.substring(mess_3 + 1, mess_4); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    // convert string to integer
    int moving_distance1 = distance1.toInt();
    int moving_distance2 = distance2.toInt();
    int moving_distance3 = distance3.toInt();
    int target_position4 = position4.toInt();

    Serial.print("Moving distance 1 (mm) = ");
    Serial.println(moving_distance1);
    Serial.print("Moving distance 2 (mms = ");
    Serial.println(moving_distance2);
    Serial.print("Moving distance 3 (mm) = ");
    Serial.println(moving_distance3);
    Serial.print("target position for linear servo (mm) = ");
    Serial.println(target_position4);

    if (moving_distance1 > 0) {
      float time1 = moving_distance1 * 1000 * distance_to_time; // unit is in milliseconds
      Serial.print("Motor 1 rotation time: ");
      Serial.println(time1/1000);
      unsigned long runtime1 = millis();
      if ((millis() - runtime1) < time1) {
        dxl.setGoalVelocity(DXL_ID_1, 300);
        runtime1 ++;
        Serial.print("Motor 1 rotation time: ");
        Serial.println(millis()); // check how much time it took to execute the while loop above
      }
      
    }
    else if (moving_distance1 < 0) {
      int time2 = (-1) * 1000 * moving_distance1 * distance_to_time;
      unsigned long runtime2 = millis();
      unsigned long totalruntime2 = millis();
      while ((totalruntime2 - runtime2) < time2) {
        dxl.setGoalVelocity(DXL_ID_1, 1324);
        runtime2 ++;
      }
      Serial.print("Motor 1 rotation time: ");
      Serial.println(totalruntime2 - runtime2);

    }
    else {
      dxl.setGoalVelocity(DXL_ID_1, 0, UNIT_RPM);
      Serial.println("Motor 1 did not rotate.");
    }


I have eliminated some irrelevant code for simplicity.

After i upload my code to the arduino uno and input (10,0,0,0.) into the serial monitor (the "10" is the value that is supposed to be used for the first while loop). Once I did that, my serial monitor outputted

Moving distance 1 (mm) = 10
Moving distance 2 (mms = 0
Moving distance 3 (mm) = 0
target position for linear servo (mm) = 0
Motor 1 rotation time: 0.28 (expected rotation time)
Motor 1 rotation time: 4290 (actual time it took for the code to execute? im not sure how to measure that either...)

which are not the values that i envisoned initially.

I expected that the expected roation time, which is 0.28 seconds, to match the actual rotation time.

So my questions are

  1. How would i correctly write a code that executes for a specified amount of time, in this case "moving_distance1 * 1000 * distance_to_time (ms)" ?

  2. How would I find how long it took for the while loop to execute in total?

Thank you so much!

Comment, please

one approach


char buf [90];

unsigned long msecPeriod;
unsigned long msecLst;

void
loop (void)
{
    unsigned long msec = millis ();
    if (msecPeriod)  {
        if (msec - msecLst < msecPeriod)  {
            Serial.println (" do something");
        }
        else
            msecPeriod = 0;
    }

    if (Serial.available ()) {
        int n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
        buf [n] = '\0';

        int val;
        sscanf (buf, "%d", &val);
        msecPeriod = 1000 * val;
        msecLst    = msec;
    }
}

void
setup (void)
{
    Serial.begin (9600);
}

This while loop doesn't appear to update a timestamp within the loop. What do you expect to end the loop?

later edit:

oops -- I thought the runtime2++ was a counter separate from the timestamps, but no-- Instead it advances the runtime2 timestamp and quickly pushes the difference into the negative/unsigned long rollover region.

By using the function millis()

storing a stimestamp = a snapshot of time right before your while-loop starts executing
and then storing a second timestamp right after your while-loop
then calculating the difference.

most stripped down demo-code to demontrate this

unsigned long myCounter = 0;
unsigned long startTime;
unsigned long endTime;


void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
}


void loop() {

  startTime = millis();
  
  while (myCounter < 10000000) {
    myCounter++;
  }
  
  endTime = millis();
  
  Serial.print("counting up to 10.000.000 took ");
  Serial.print(endTime - startTime);
  Serial.println(" milliseconds");
  myCounter = 0;
}

serial monitor

counting up to 10.000.000 took 875 milliseconds

I assume that your final code will do much more than just moving motor 1 and that you want these other things to execute at the same time as motor 1 is moving.

This requires non-blocking coding
Your while-loop is blocking.
As long as the while-loop is running you can't do anything else.
Only exception code that you put into the while-loop
but this would mess up the code.

the one and only loop of non-blocking code is
void loop() itself

I started a tutorial about this which is yet not finished

best regards Stefan

This example still has the blocking while-loop

The WokSim below demonstrates how you let do

void loop()

do the "looping" for a certain amout of time started by a button-press

This demo-code also shows how you can use serial printing to make visible what the code is doing. Serial printing is the main technique for debugging

same code as in the WokSim

unsigned long myTimer = 0;
const unsigned long RunPeriod = 2800;

unsigned long myCounter = 0;

boolean startHasBeenPressed = false;

const byte startButtonPin = 4;

#define pressed  LOW
#define released HIGH

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  Serial.println("press button to start non-blocking");
  Serial.println("time-based upcounting loop");

  pinMode(startButtonPin, INPUT_PULLUP);
}


void loop() {

  // check if counting up through pressing the button
  // has not yet started
  if (startHasBeenPressed == false) {
    // check for button-press
    if ( digitalRead(startButtonPin) == pressed) {
      startHasBeenPressed = true;
      myTimer = millis(); // store snapshot of time
      Serial.println("Startbutton pressed start counting ....");
    }
  }

  // check if startbutton has been pressed
  if (startHasBeenPressed == true) {
    myCounter++;

    // check if number of milliseconds 
    // stored in variable RunPeriod have passed by
    if ( TimePeriodIsOver(myTimer, RunPeriod) ) {
      // when number of milliseconds stored in variable RunPeriod
      // have REALLY passed by
      startHasBeenPressed = false; // stop counting
      Serial.print("counting up for ");
      Serial.print(RunPeriod);
      Serial.print(" milliseconds is over myCounter=");
      Serial.println(myCounter);
      myCounter = 0; // reset counter to zero
    }
  }
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

best regards Stefan

As a next step to expand the demo-code this version has a STOP-Button and the code is "instantly" responsive to the STOP-Button at any time while the timed upcounting is running

Again with comments and serial printing to make visible what the code is doing

code as in the WokSim

unsigned long myTimer = 0;
const unsigned long RunPeriod = 2800;

unsigned long myCounter = 0;

boolean startHasBeenPressed = false;

const byte startButtonPin = 4;
const byte STOPButtonPin  = 5;

#define pressed  LOW
#define released HIGH

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  Serial.println("press green button to start non-blocking");
  Serial.println("time-based upcounting loop");
  Serial.println("press red button to STOP the 'looping'");

  pinMode(startButtonPin, INPUT_PULLUP);
  pinMode(STOPButtonPin,  INPUT_PULLUP);
}


void loop() {

  // check if upcounting is running
  if (startHasBeenPressed == true) {
    // check if STOP-button us pressed
    if ( digitalRead(STOPButtonPin) == pressed) {
      startHasBeenPressed = false;
      Serial.print("STOP-Button terminated upcounting at counter=");
      Serial.println(myCounter);
      myCounter = 0;

      Serial.print("time between pressing Start / STOP-Button ");
      Serial.print(millis() - myTimer);
      Serial.println(" milliseconds");
    }
  }

  // check if counting up through pressing the button
  // has not yet started
  if (startHasBeenPressed == false) {
    // check for button-press
    if ( digitalRead(startButtonPin) == pressed) {
      startHasBeenPressed = true;
      myTimer = millis(); // store snapshot of time
      Serial.println("Startbutton pressed start counting ....");
    }
  }

  // check if startbutton has been pressed
  if (startHasBeenPressed == true) {
    myCounter++;

    // check if number of milliseconds 
    // stored in variable RunPeriod have passed by
    if ( TimePeriodIsOver(myTimer, RunPeriod) ) {
      // when number of milliseconds stored in variable RunPeriod
      // have REALLY passed by
      startHasBeenPressed = false; // stop counting
      Serial.print("counting up for ");
      Serial.print(RunPeriod);
      Serial.print(" milliseconds is over myCounter=");
      Serial.println(myCounter);
      myCounter = 0; // reset counter to zero
    }
  }
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

Now to keep code easy to maintain and easy to develop / adding more functions
you should organise the code into sub-units where each sub-unit does one thing and then give this sub-unit a self-explaining name

This is realised in version 3 of the demo-code

If you take a close look the code is "packed" into functions

printStartMessage();

  checkForStartButtonPress(); 
  
  checkForSTOPButtonPress();

  doTimeBasedUpCounting();

WokSim

and complete code of the WokSim

unsigned long myTimer = 0;
const unsigned long RunPeriod = 2800;

unsigned long myCounter = 0;

boolean startHasBeenPressed = false;

const byte startButtonPin = 4;
const byte STOPButtonPin  = 5;

#define pressed  LOW
#define released HIGH

void setup() {
  Serial.begin(115200);

  // function-call to that part of the code that does 
  // what the function names are saying
  printStartMessage();

  pinMode(startButtonPin, INPUT_PULLUP);
  pinMode(STOPButtonPin,  INPUT_PULLUP);
}


void loop() {
  // function-calls to that part of the code that does 
  // what the function's name are says
  checkForStartButtonPress(); 
  
  checkForSTOPButtonPress();

  doTimeBasedUpCounting();
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}


void printStartMessage() {  
  Serial.println("Setup-Start");
  Serial.println("press green button to start non-blocking");
  Serial.println("time-based upcounting loop");
  Serial.println("press red button to STOP the 'looping'");
}


void checkForStartButtonPress() {
  // check if counting up through pressing the button
  // has not yet started
  if (startHasBeenPressed == false) {
    // check for button-press
    if ( digitalRead(startButtonPin) == pressed) {
      startHasBeenPressed = true;
      myTimer = millis(); // store snapshot of time
      Serial.println("Startbutton pressed start counting ....");
    }
  }
}


void checkForSTOPButtonPress() {
  // check if upcounting is running
  if (startHasBeenPressed == true) {
    // check if STOP-button us pressed
    if ( digitalRead(STOPButtonPin) == pressed) {
      startHasBeenPressed = false;
      Serial.print("STOP-Button terminated upcounting at counter=");
      Serial.println(myCounter);
      myCounter = 0;

      Serial.print("time between pressing Start / STOP-Button ");
      Serial.print(millis() - myTimer);
      Serial.println(" milliseconds");
    }
  }
}

void doTimeBasedUpCounting() {
  // check if startbutton has been pressed
  if (startHasBeenPressed == true) {
    myCounter++;

    // check if number of milliseconds 
    // stored in variable RunPeriod have passed by
    if ( TimePeriodIsOver(myTimer, RunPeriod) ) {
      // when number of milliseconds stored in variable RunPeriod
      // have REALLY passed by
      startHasBeenPressed = false; // stop counting
      Serial.print("counting up for ");
      Serial.print(RunPeriod);
      Serial.print(" milliseconds is over myCounter=");
      Serial.println(myCounter);
      myCounter = 0; // reset counter to zero
    }
  }
}

best regards Stefan

P.S. hm ... - an almost general-purpose tutorial about writing code

It doesn't need to add up more than once before the difference goes into negative/unsigned rollover territory to 2^32-1= 4294967295 and fails the test.

thank you!

So would this code let the while loop run for time2 milliseconds since it breaks out of the while loop once timeNow - timeAtStart reaches time2? or is the value reducing as the while loop goes on and on?

@DaveX :
why are you sending newcomers on the blocking-code-track?

@gno :laughing: are you sure that you only want to do one thing at a time in your final code?

Because that’s the track the OP started down, posted code for, and titled their topic with.

If you need to do more than one thing at a time, using loop() to loop is better than creating blocking delays with while.

What's the difference between a blocking code and a non-blocking code?

How would I make this non-blocking? I'm sorry im a newbie and im not sure how to do all this!

Hello!

I changed my code as you suggested to the following:

if (moving_distance1 > 0) {
      float time1 = moving_distance1 * 1000 * distance_to_time; // unit is in milliseconds
      Serial.print("Time that the motor should run: ");
      Serial.print(time1);
      Serial.println(" milliseconds");
      
      unsigned long timeAtStart1 = millis();
      unsigned long timeNow1 = millis(); 
      while ((timeNow1 - timeAtStart1) < time1) {
        dxl.setGoalVelocity(DXL_ID_1, 300);
        timeNow1 = millis();
      } 
      Serial.print("Motor 1 rotation time: ");
      Serial.println(timeNow1 - timeAtStart1);
      Serial.println(" milliseconds");
      Serial.print("Motor 1 roated clockwise for ");
      Serial.print(moving_distance1);
      Serial.println(" mm.");

And the serial monitor outputted this:

------------------ INPUT VALUES ------------------
Moving distance 1 (mm) = 10
Moving distance 2 (mm) = 0
Moving distance 3 (mm) = 0
target position for linear servo (mm) = 0
--------------------------------------------------
Time that the motor should run: 279.22 milliseconds
Motor 1 rotation time: 307 milliseconds
Motor 1 rotated clockwise for 10 mm.

It seesm like the expected rotating time and actual rotation time to be different. How can i fix this issue?

Without seeing the complete sketch it is hard to analyse
you should always post the complete sketch.
The code-sexction limits the visible height of the code

best regards Stefan

it takes around 34-35 milliseconds for that line to run. I do need to activate the motor I am using (Dynamixel motor) and use it constantly in order to maintain the speed of the motor consistently.

Should i change the code to

while ((timeNow1 - timeAtStart1) < time1 - 35) {
        dxl.setGoalVelocity(DXL_ID_1, 300);
        timeNow1 = millis();
      }

?

#include <DynamixelShield.h>
#include <Servo.h>

#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560)
#include <SoftwareSerial.h>
SoftwareSerial soft_serial(7, 8); // DYNAMIXELShield UART RX/TX
#define DEBUG_SERIAL soft_serial
#elif defined(ARDUINO_SAM_DUE) || defined(ARDUINO_SAM_ZERO)
#define DEBUG_SERIAL SerialUSB
#else
#define DEBUG_SERIAL Serial
#endif

DynamixelShield dxl;
Servo myservo;

const uint8_t DXL_ID_1 = 1;
const uint8_t DXL_ID_2 = 2;
const uint8_t DXL_ID_3 = 3;

const float DXL_PROTOCOL_VERSION = 2.0;

float distance_to_time = 60 / (34.2 * 2 * PI * 10);

int pos = myservo.read();

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  delay(10);

  // Servo setup
  myservo.write(0); // this ensures that the linear servo is initially at rest
  myservo.attach(11);

  // dynamixel port baud rate: 57600 bps
  dxl.begin(9600);

  // Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  // Get DYNAMIXEL information
  dxl.ping(DXL_ID_1);
  dxl.ping(DXL_ID_2);
  dxl.ping(DXL_ID_3);

  // Turn off torque when configuring items in EEPROM area
  dxl.torqueOff(DXL_ID_1);
  dxl.setOperatingMode(DXL_ID_1, OP_VELOCITY);
  dxl.torqueOn(DXL_ID_1);

  dxl.torqueOff(DXL_ID_2);
  dxl.setOperatingMode(DXL_ID_2, OP_VELOCITY);
  dxl.torqueOn(DXL_ID_2);

  dxl.torqueOff(DXL_ID_3);
  dxl.setOperatingMode(DXL_ID_3, OP_VELOCITY);
  dxl.torqueOn(DXL_ID_3);

}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    String mess = Serial.readStringUntil('.'); // input values are time "__,__,__,__."
    Serial.print("Input values: ");
    Serial.println(mess);
    delay(10);

    int mess_1 = mess.indexOf(','); // this value represents the amount of time you want to activate motor 1
    String distance1 = mess.substring(0, mess_1); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_2 = mess.indexOf(',', mess_1 + 1); // this value represents the amount of time you want to activate motor 2
    String distance2 = mess.substring(mess_1 + 1, mess_2); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_3 = mess.indexOf(',', mess_2 + 1); // this value represents the amount of time you want to activate motor 3
    String distance3 = mess.substring(mess_2 + 1, mess_3); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    int mess_4 = mess.indexOf(',', mess_3 + 1); // this value represents the amount of time you want to activate linear servo
    String position4 = mess.substring(mess_3 + 1, mess_4); // positive value: clockwise | negative value: counterclockwise
    delay(10);

    // convert string to integer
    int moving_distance1 = distance1.toInt();
    int moving_distance2 = distance2.toInt();
    int moving_distance3 = distance3.toInt();
    int target_position4 = position4.toInt();

    unsigned long startingtime = millis();
    dxl.setGoalVelocity(DXL_ID_1, 300);
    unsigned long endingtime = millis();

    Serial.print(endingtime - startingtime);

    Serial.println("------------------ INPUT VALUES ------------------");
    Serial.print("Moving distance 1 (mm) = ");
    Serial.println(moving_distance1);
    Serial.print("Moving distance 2 (mm) = ");
    Serial.println(moving_distance2);
    Serial.print("Moving distance 3 (mm) = ");
    Serial.println(moving_distance3);
    Serial.print("target position for linear servo (mm) = ");
    Serial.println(target_position4);
    Serial.println("--------------------------------------------------");

    if (moving_distance1 > 0) {
      float time1 = moving_distance1 * 1000 * distance_to_time; // unit is in milliseconds
      Serial.print("Time that the motor should run: ");
      Serial.print(time1);
      Serial.println(" milliseconds");

      unsigned long timeAtStart1 = millis();
      unsigned long timeNow1 = millis();
      while ((timeNow1 - timeAtStart1) < time1) {
        dxl.setGoalVelocity(DXL_ID_1, 300);
        timeNow1 = millis();
      }
      Serial.print("Motor 1 rotation time: ");
      Serial.print(timeNow1 - timeAtStart1);
      Serial.println(" milliseconds");
      Serial.print("Motor 1 roated clockwise for ");
      Serial.print(moving_distance1);
      Serial.println(" mm.");

    }
    else if (moving_distance1 < 0) {
      int time2 = (-1) * 1000 * moving_distance1 * distance_to_time;

      unsigned long timeAtStart2 = millis();
      unsigned long timeNow2 = millis();
      while ((timeNow2 - timeAtStart2) < time2) {
        dxl.setGoalVelocity(DXL_ID_1, 1324);
        timeNow2 = millis();
      }
      Serial.print("Motor 1 rotation time: ");
      Serial.print(timeNow2 - timeAtStart2);
      Serial.println(" milliseconds");
      Serial.print("Motor 1 rotated counterclockwise for ");
      Serial.print(moving_distance1 * (-1));
      Serial.println(" mm.");
    }
    else {
      dxl.setGoalVelocity(DXL_ID_1, 0, UNIT_RPM);
      Serial.println("Motor 1 did not rotate.");
    }


    // motor 2 control
    if (moving_distance2 > 0) {
      int time3 = 1000 * moving_distance2 * distance_to_time; // unit is in milliseconds
      unsigned long timeAtStart3 = millis();
      unsigned long timeNow3 = millis();
      while ((timeNow3 - timeAtStart3) <= time3) {
        dxl.setGoalVelocity(DXL_ID_2, 300);
        timeNow3 = millis();
      }
      Serial.print("Motor 2 rotation time: ");
      Serial.print(timeNow3 - timeAtStart3);
      Serial.println(" milliseconds");
      Serial.print("Motor 2 roated clockwise for ");
      Serial.print(moving_distance2);
      Serial.println(" mm.");

    }
    else if (moving_distance2 < 0) {
      int time4 = (-1) * 1000 * moving_distance2 * distance_to_time;
      unsigned long timeAtStart4 = millis();
      unsigned long timeNow4 = millis();
      while ((timeNow4 - timeAtStart4) < time4) {
        dxl.setGoalVelocity(DXL_ID_2, 1324);
        timeNow4 = millis();
      }
      Serial.print("Motor 2 rotation time: ");
      Serial.print(timeNow4 - timeAtStart4);
      Serial.println(" milliseconds");
      Serial.print("Motor 2 rotated counterclockwise for ");
      Serial.print(moving_distance2 * (-1));
      Serial.println(" mm.");
    }
    else {
      dxl.setGoalVelocity(DXL_ID_2, 0, UNIT_RPM);
      Serial.println("Motor 1 did not rotate.");
    }

    // motor 3 control
    if (moving_distance3 > 0) {
      int time5 = 1000 * moving_distance3 * distance_to_time; // unit is in milliseconds
      unsigned long timeAtStart5 = millis();
      unsigned long timeNow5 = millis();
      while ((timeNow5 - timeAtStart5) < time5) {
        dxl.setGoalVelocity(DXL_ID_3, 300);
        timeNow5 = millis();
      }
      Serial.print("Motor 3 rotation time: ");
      Serial.print(timeNow5 - timeAtStart5);
      Serial.println(" milliseconds");
      Serial.print("Motor 3 roated clockwise for ");
      Serial.print(moving_distance3);
      Serial.println(" mm.");

    }
    else if (moving_distance3 < 0) {
      int time6 = (-1) * 1000 * moving_distance3 * distance_to_time;
      unsigned long timeAtStart6 = millis();
      unsigned long timeNow6 = millis();
      while ((timeNow6 - timeAtStart6) < time6) {
        dxl.setGoalVelocity(DXL_ID_3, 1324);
        timeNow6 = millis();
      }
      Serial.print("Motor 3 rotation time: ");
      Serial.print(timeNow6 - timeAtStart6);
      Serial.println(" milliseconds");
      Serial.print("Motor 3 rotated counterclockwise for ");
      Serial.print(moving_distance3 * (-1));
      Serial.println(" mm.");
    }
    else {
      dxl.setGoalVelocity(DXL_ID_3, 0, UNIT_RPM);
      Serial.println("Motor 1 did not rotate.");
    }

    // linear servo

  }

}

This is the entire code

please activate timestamp in the serial monitor and post what gets printed

Input values: 10,10,10,0
------------------ INPUT VALUES ------------------
Moving distance 1 (mm) = 10
Moving distance 2 (mm) = 10
Moving distance 3 (mm) = 10
target position for linear servo (mm) = 0
--------------------------------------------------
Time that the motor should run: 279.22 milliseconds
Motor 1 rotation time: 309 milliseconds
Motor 1 roated clockwise for 10 mm.
Motor 2 rotation time: 307 milliseconds
Motor 2 roated clockwise for 10 mm.
Motor 3 rotation time: 309 milliseconds
Motor 3 roated clockwise for 10 mm.

i have inputed 10,10,10,0. into my serial monitor and the above values are the output.

Thank you!

please activate the

timestamp

in the serial monitor

Input values: 10,10,10,0
14:43:37.468 -> ------------------ INPUT VALUES ------------------
14:43:37.573 -> Moving distance 1 (mm) = 10
14:43:37.609 -> Moving distance 2 (mm) = 10
14:43:37.609 -> Moving distance 3 (mm) = 10
14:43:37.645 -> target position for linear servo (mm) = 0
14:43:37.717 -> --------------------------------------------------
14:43:37.750 -> Time that the motor should run: 279.22 milliseconds
14:43:37.824 -> Motor 1 rotation time: 309 milliseconds
14:43:38.100 -> Motor 1 roated clockwise for 10 mm.
14:43:38.136 -> Motor 2 rotation time: 308 milliseconds
14:43:38.424 -> Motor 2 roated clockwise for 10 mm.
14:43:38.459 -> Motor 3 rotation time: 309 milliseconds
14:43:38.741 -> Motor 3 roated clockwise for 10 mm.

This is what the serial monitor outputs when inputting (10,10,10,0) (same as before).

Should i add addtional serial.print statements to check the actual time spent??