Always move the shortest distance 0-360 degrees

167 views
Skip to first unread message

Herr Bengtsson

unread,
Feb 19, 2022, 8:03:42 AM2/19/22
to accelstepper
Hello!

I have an esp8266 project that uses the 28BYJ-48 and ULN2003 with the AccelStepper library. The concept is that I parse a JSON file with the current direction and move a flag to the correct heading. Everything works great except for one thing.

I want the stepper to always move the shortest distance to the its new position. This works most of the time, but I run into problems when I have north wind and the motor passes thru 0 degrees.

So if I have wind coming from lets say 355 degrees and the new update shows a small shift to 5 degrees, the motor will take the long way around.  

I am not a programmer, and I asked two people to solve this for me, but it seems to be a bit tricky. Here is the code I'm running right now. The code that is commented out is the second try that didn't work, but maybe it is possible to modify to reach my goal?

Can I do this with Accelstepper?

// |---------------------------------------------|
// |            Run Steppers methods             |
// |---------------------------------------------|
// Function to move the stepper motor with acceleration - Non Blocking
void RunStepper(float s)
{
  Stepper.enableOutputs();
  DEBUG_STATION_PARSER_SERIAL.println("Stepper.movement: " + (String)s);

  Stepper.moveTo(s);
  while (Stepper.distanceToGo() != 0)
  {
    Stepper.run();
    delay(1);
  }
  Stepper.disableOutputs();
}
void moveStepperShort(float incoming_target)
{
  // float teta = 0;
  // float alfa = 0;
  // float beta = 0;
  // float lambda = 0;
  // float tavo = 0;
  //
  // teta = incoming_target >= 360 ? 0 : incoming_target;
  // alfa = last_target;
  // target = teta;
  //
  // if(teta < alfa)
  //   {
  //       beta = 360 - alfa;
  //       tavo = beta + teta;
  //       lambda = 360 - beta - teta;
  //   }
  //   else if(teta > alfa)
  //   {
  //       beta = alfa - teta;
  //       tavo = teta - alfa;
  //       lambda = 360 + beta;
  //   }
  //
  //   if(lambda > tavo)
  //   {
  //     DEBUG_STATION_PARSER_SERIAL.println("Fordward steps " + (String)tavo);
  //     RunStepper(tavo * stepmotor_scale);
  //     last_target = target;
  //     Stepper._currentPos = last_target * stepmotor_scale;
  //     DEBUG_STATION_PARSER_SERIAL.println("After RunStepper");
  //     DEBUG_STATION_PARSER_SERIAL.println("Stepper Position " +       (String)Stepper._currentPos);
  //   }
  //   else
  //   {
  //     DEBUG_STATION_PARSER_SERIAL.println("Backward steps " + (String)lambda);
  //     RunStepper(-lambda * stepmotor_scale);
  //     last_target = target;
  //     Stepper._currentPos = last_target * stepmotor_scale;
  //     DEBUG_STATION_PARSER_SERIAL.println("# After RunStepper #");
  //     DEBUG_STATION_PARSER_SERIAL.println("Stepper Position " + (String)Stepper._currentPos);
  //   }

  target = incoming_target;
  // call a function to move the stepper
  int dis_1 = (int)(target - last_target);             // 200 - 130 = 70
  int dis_2 = (int)(last_target + 360 - target) % 360; // (130 + 360 - 200) % 360 = 290

  DEBUG_STATION_PARSER_SERIAL.println("Last position: " + (String)last_target);
  DEBUG_STATION_PARSER_SERIAL.println("Target: " + (String)target);
  DEBUG_STATION_PARSER_SERIAL.println("Dis_1: " + (String)dis_1);
  DEBUG_STATION_PARSER_SERIAL.println("Dis_2: " + (String)dis_2);

  // dis_2 < dis_1 => 70 < 290
  if (abs(dis_2) < abs(dis_1)) // Backward motion
  {
    target = target - 360; // 200-360=-160
    RunStepper(target * stepmotor_scale);
    target = target + 360;
    last_target = target;
    Stepper._currentPos = last_target * stepmotor_scale;

    DEBUG_STATION_PARSER_SERIAL.println("After RunStepper");
    DEBUG_STATION_PARSER_SERIAL.println("Steps Old " + (String)last_target);
    DEBUG_STATION_PARSER_SERIAL.println("Stepper._currentPos " + (String)Stepper._currentPos);
  }
  else // Forward motion
  {
    // target = 10
    RunStepper(target * stepmotor_scale);

    DEBUG_STATION_PARSER_SERIAL.println("After RunStepper");

    last_target = target;
    Stepper._currentPos = last_target * stepmotor_scale;
  }
}

Jim Larson

unread,
Feb 19, 2022, 4:59:07 PM2/19/22
to accelstepper
Here's a possible approach.
Determine if you need to move thru zero. Do this if so.
In the example you mention, you want to move 10 degrees. Call it newDist. You can figure out how to calculate this, I think.
Save the new target position, let's call it newTarg.
Use Stepper.setCurrentPosition(0) to make the current position equal 0.
Use your RunStepper routine to move -newDist with scaling.
When the function returns, use Stepper.setCurrentPosition(newTarg*stepmotor_scale).
The motor will have moved the correct distance in the desired direction and the currentPosition will be correct.

Note that the delay(1) you have in RunStepper does nothing since no step will be taken unless it's time to take it.

HTH
      -jim

David Bengtsson

unread,
Feb 20, 2022, 1:43:16 AM2/20/22
to accels...@googlegroups.com
Thanks. I will give it a try!
I.e, ask my brother to solve my problem with this approach :P
> --
> You received this message because you are subscribed to a topic in the Google Groups "accelstepper" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/accelstepper/11vCYkJN9T0/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/accelstepper/7843188a-9b42-43a0-be8b-8700bf5d24c5n%40googlegroups.com.

Herr Bengtsson

unread,
Feb 20, 2022, 1:25:47 PM2/20/22
to accelstepper
Thank you for the help. Seems to work now :) 

// |---------------------------------------------|
// | Run Steppers methods |
// |---------------------------------------------|
// Function to move the stepper motor with acceleration - Non Blocking
void RunStepper(float s)
{
Stepper.enableOutputs();
DEBUG_STATION_PARSER_SERIAL.println("Stepper.movement: " + (String)s);

Stepper.moveTo(s);
while (Stepper.distanceToGo() != 0)
{
Stepper.run();
}
Stepper.disableOutputs();
}
void moveStepperShort(float incoming_target)
{
// +--------------------------------+
// | New Method |
// +--------------------------------+
float teta = 0;
float alfa = 0;
float beta = 0;
float lambda = 0;
float tavo = 0;
teta = incoming_target >= 360 ? 0 : incoming_target;
alfa = last_target;
target = teta;
if(teta < alfa)
{
beta = 360 - alfa;
tavo = beta + teta;
lambda = 360 - beta - teta;
}
else if(teta > alfa)
{
beta = alfa - teta;
tavo = teta - alfa;
lambda = 360 + beta;
}
Stepper.setCurrentPosition(0);
Stepper.setMaxSpeed(600);
Stepper.setAcceleration(200);
if(lambda > tavo)
{
DEBUG_STATION_PARSER_SERIAL.println("Fordward steps " + (String)tavo);
RunStepper(tavo * stepmotor_scale);
last_target = target;
Stepper._currentPos = target * stepmotor_scale;
DEBUG_STATION_PARSER_SERIAL.println("After RunStepper");
DEBUG_STATION_PARSER_SERIAL.println("Stepper Position " + (String)target);
}
else
{
DEBUG_STATION_PARSER_SERIAL.println("Backward steps " + (String)lambda);
RunStepper((-1)* lambda * stepmotor_scale);
last_target = target;
Stepper._currentPos = target * stepmotor_scale;
DEBUG_STATION_PARSER_SERIAL.println("# After RunStepper #");
DEBUG_STATION_PARSER_SERIAL.println("Stepper Position " + (String)target);
}
Stepper.setCurrentPosition(target * stepmotor_scale);
Reply all
Reply to author
Forward
0 new messages