elapsedMicros and micros() pauses program

Peter Lingaas

New member
Hi! I am building a library for running my robot arm. I have tried out all the code earlier and it works fine,
but now that I am using it via my library, micros() and elapsedMicros pauses the program. It runs for 5000-30000 microseconds
and then it pauses until its around 7 million microseconds and runs normally. This is the function that is using the code:

Code:
void RobotArm::goToWithTime(float x, float y, float z, float rx, float ry, float rz, float move_time)
{

  Serial.println("STARTING MOVE");
  Angles angles = IK(x, y, z);

  if (!angles.legal || z < 50) {
    Serial.println("ERROR: POSITION IS OUTSIDE OF WORKSPACE");
    return;
  }
  
  int j1Steps = angles.theta1 * 88.88888889;
  int j2Steps = angles.theta2 * 55.55555567;
  int j3Steps = angles.theta3 * 55.55555567;

  actuators[0].moveTo(j1Steps, move_time, acc_time_percentage, dec_time_percentage);
  actuators[1].moveTo(j2Steps, move_time, acc_time_percentage, dec_time_percentage);
  actuators[2].moveTo(j3Steps, move_time, acc_time_percentage, dec_time_percentage);
  
  run();
}

void RobotArm::run() 
{
  bool a, b, c = false;
  bool finished = false;
  
  [B]elapsedMicros time_elapsed;
  while (!finished) 
  {
    a = actuators[0].run(time_elapsed);
    b = actuators[1].run(time_elapsed);
    c = actuators[2].run(time_elapsed);
    finished = a && b && c;
  }[/B]
  Serial.println("New position reached");
}

Everything runs properly when I dont use my RobotArm library, but when I use it elapsedMicros and micros() just pauses?
I have been messing around for 5 hours trying to figure it out, but I can't seem to find the issue.

This is how the code looks when its outside the library and runs just fine:

Code:
void goTo(float x, float y, float z, float T, float t_in, float t_out) {

  Angles angles = IK(x, y, z);

  if (!angles.legal || z < 50) {
    Serial.println("ERROR: POSITION IS OUTSIDE OF WORKSPACE");
    return;
  }
  int j1Steps = angles.theta1 * 88.88888889;
  int j2Steps = angles.theta2 * 55.55555567;
  int j3Steps = angles.theta3 * 55.55555567;
  Serial.println(j1Steps);
  Serial.println(j2Steps);
  Serial.println(j3Steps);

  stepper1.moveTo(j1Steps, T, t_in, t_out);
  stepper2.moveTo(j2Steps, T, t_in, t_out);
  stepper3.moveTo(j3Steps, T, t_in, t_out);
  
  bool a, b, c = false;
  bool finished = a && b && c;
  
  [B]elapsedMicros time_elapsed;
  while (!finished) {
    a = stepper1.run(time_elapsed);
    b = stepper2.run(time_elapsed);
    c = stepper3.run(time_elapsed);
    finished = a && b && c;
  }
  Serial.println("FINISHED");[/B]
}
 
Last edited:
I finally found the line that is causing this issue.

Deep within the code there is a step() function that steps the stepper motors:

Code:
void PeterStepper::step()
{
    
    digitalWrite(dirPin, direction);
    digitalWrite(stepPin, LOW);
    [B]delayMicroseconds(minPulseWidth);[/B]
    digitalWrite(stepPin, HIGH);
}

Both snippets posted above use this function, but when it is used through the library RobotArm it causes the program to stop? What can the reason for this be?
 
Well, I'll go out on limb here:
1. elapsedMicros() and micros() are different, but in any case I don't see any calls to micros(). elapsedMillis() is probably a better choice.
2. In the lower code, you define time_elapsed and then use it in the calls to steppers.run() without initializing it. It's not clear what you're trying to do here, without knowing more about stepper.run().

I suspect that the "good" code isn't actually doing what you want.
 
The good code does exactly what I want as far as I can see, it moves my robot arm to the coordinates i specify.

I tried using micros() but that also crashed so I ended up ignoring it and sticking with elapsedMicros which is what I want to use because of overload.
I posted the source code on github: https://github.com/Plingaas/RobotArm

You can find the stepper.run() function in the PeterStepper.cpp file.
 
OK, I see what you're doing. A bit strange, but I'll come back to that in a minute.
micros() is a free-running counter that isn't (I don't think) guaranteed to start at zero. It rolls over every 2^32 microseconds (4295 seconds). elapsedMicros is also a free-running counter. When defined inside a functions (as in your goTo function) it starts at zero when the function executes. But note that it will be well past zero microseconds by the time it gets to your calls to stepper.run(). You should include the line
Code:
time_elapsed = 0;
right before the while loop.

When you define an elapsedMicros variable inside a class method (RobotArm::run()), the initialization behavior may be different. It might be initialized (starts counting) sooner. Again, you can fix this by explicitly setting time_elapsed to zero right before you use it.

But this whole method is really limiting, and will prevent you from every doing anything else while the arm is moving. It's much more flexible to use elapsedMicros to create a fixed-duration loop in which multiple functions are called to take any necessary actions and then quickly return. Here's an article that explains in detail how to do this.

The call to delayMicroseconds() in step() isn't necessarily a problem, even though it's a blocking function. It depends on the duration of minPulseWidth relative to other time scales in which other time-critical actions need to be performed.
 
Aha I will look into doing that so I can do more than just moving the arm thank you! I checked minpulsewidth now and I just realized something very odd is happening with the way I created the PeterStepper constructors. All the values are wrong. minpuisewidth was set to -23 for some reason even though the code says 5. I am very new to c++ so there is probably a very good reason for this though.

Thank you for helping :)
 
Back
Top