AccelStepper anomaly - .run() finishing prematurely

Hi - Sorry to be annoying, I try to dump my problems on other people infrequently, but this one has got me stumped.

I have an ESP32 here running tasks pinned to each of the two cores: core 0 performs stepper motor operations, core 1 communicates with a touchscreen.

My motor function core has a switch function for various motor states (selected on the touchscreen), and within those there's a couple while functions which run the stepper motors. There are two stepper motors running simultaneously with the run() function. Relevant code here:

void IRAM_ATTR MotorStuff() {

  switch(Motor_State) {
    case SELECTOR_A:
                /* Does some math to define stepper2 oscillation endpoints (int Move_2_A, int Move_2_B) */
                /* Also defines stepper1 finish point */
                /* The result is stepper1 turns one direction, while stepper2 goes back and forth */
    break; //end SELECTOR_A state

    case OSCILLATE_R:

            while ((stepper1.distanceToGo() != 0) && (cancel_run == false)) {
              stepper2.moveTo(Move_2_B);
              while (stepper2.distanceToGo() != 0) {
                  stepper1.run();
                  stepper2.run();
                  };
              stepper2.moveTo(Move_2_A);
              while (stepper2.distanceToGo() != 0) {
                  stepper1.run();
                  stepper2.run();
                  };
                  };
              if (cancel_run == true) {Motor_State = CANCELLED;}
              if (stepper1.distanceToGo() == 0) {Motor_State = SELECTOR_A;}
    break; //end OSCILLATE_R state

    case CANCELLED:
            /* ...cancels everything */
    break; //end CANCELLED state

  }; //end Motor_State
}; //end MotorStuff(), Core 0 functions

OK so everything is functioning great, but for some mysterious reason, my stepper2 motor (the one swaying back and forth between int Move_2_A and int Move_2_B) consistently ends prematurely. Stepper1 continues spinning to its endpoint, but stepper2 just gives up.

I've tested it many times, restructured the functions, and cannot root this one out. There is no change happening to those Move_2_x ints while the motors are running, so there's absolutely no reason I can see for the thing to end its run.

The fact that stepper1 continues to run (whilst looping in the same while function as stepper2) makes me think there is some sort of hardware issue occurring with stepper2. On the other hand, after repeated tests, I've found consistency in the times when stepper2 chooses to stop itself, so...I'm not sure what's going on anymore.

Does AccelStepper not play well with ESP32s?

I would really, really, really, really, appreciate some help here if possible. I'll go back to trying to debug it for now..

Take the "runs" out of the whiles and put them in the main loop().

JCA34F:
Take the "runs" out of the whiles and put them in the main loop().

I have two separate cores running pinned functions simultaneously (though the focus is on one single core here) - isn't the main loop meant to remain unused? The suggestion is confusing, maybe you could enlighten me though because I only need the run() classes to be used at specific times for finite periods.

edit: to be more specific, the cores are pinned in "for" arguments like this:

Void Task1code( void * parameter) {
  for(;;) {
      MotorStuff(); // the function in the original post, running on infinite loop
    (...)
  }
}

Are you suggesting that the nested While loops in a For argument loop are causing confusion?

I'll try putting the code on a standard setup (not pinning to the cores) to see if it corrects itself, but I don't have high hopes...all the tests I've been running have the thing stopping at a seemingly predetermined point during the running process, but the bounds are clearly defined so...maybe it's a core thing, maybe it's the AccelStepper library having troubles.

Maybe It's the nested loops, I dunno...I'm gonna be trying all this stuff out, but I really need any insight or ideas anyone may have. My head has been in this a while and I'm running out of thoughts...

jtbennett:
isn't the main loop meant to remain unused?

I don't know the answer to that but I suggest you put the run() statements where they will be called all the time the program is running. The AccelStepper library will automatically stop moving the motor when it has reached its destination even though run() continues to be called.

...R

So if I were to place the run() statements on core1 and the math and other stepper commands on core0, would that theoretically work out?

jtbennett:
So if I were to place the run() statements on core1 and the math and other stepper commands on core0, would that theoretically work out?

I can't answer that - I have not studied the workings of an ESP32

...R

Robin2:
I can’t answer that - I have not studied the workings of an ESP32

…R

OK well I went ahead and made a simplified, standard version of things - I will include the sketch just below so you can see all the critical stuff properly. It functions with just the same issue: the stepper2 strafing motion stops prematurely at ~280 - 300 revolutions (out of the 500 stepper1 revolutions). All the math is visible, it’s using two TB6600 stepper motors and two NEMA23 3.2A motors:

#include <AccelStepper.h>
AccelStepper stepper1(AccelStepper::DRIVER, 26, 25);
AccelStepper stepper2(AccelStepper::DRIVER, 16, 27);
int Move_2_A;
int Move_2_B;
int blockSPS = 8000;
int SPS = 1600;
int SPR = 1600;
int RPMs = 300;
int autoSets1 = 4000;
int s2_bobbinSpace = 0;
int RawSpeed2 = 0;
int MaxSpeed2;
int blockWPS = 1;
int Move1;
int blockWinds = 500;
int to_step = 200;
float bobbinSpace = 14.5;
long MAX_SPD = 29333;
long MAX_XCL = 25000; /* 100000 */
void setup() {
  
 Serial.begin(115200);
  stepper1.setMinPulseWidth(20);
  stepper1.setEnablePin(17);
  stepper1.setPinsInverted(false, false, true);
  stepper1.disableOutputs();
  stepper2.setMinPulseWidth(20);
  stepper2.setEnablePin(14);
  stepper2.setPinsInverted(false, false, true);
  stepper2.disableOutputs();
delay(1000);
};
void SELECTOR_A() {
             s2_bobbinSpace = round(bobbinSpace * to_step);
             RawSpeed2 = (blockSPS / SPR) * (s2_bobbinSpace / blockWPS);
             MaxSpeed2 = round(RawSpeed2 * .3333);
             Move1 = blockWinds * SPR;
             
             Move_2_A = 0;
             Move_2_B = s2_bobbinSpace;
             
            stepper1.enableOutputs();
            stepper2.enableOutputs();
            stepper1.setCurrentPosition(0);
            stepper2.setCurrentPosition(0);
            
             stepper1.setMaxSpeed(blockSPS);
             stepper1.setAcceleration(autoSets1);
             stepper2.setMaxSpeed(MaxSpeed2);
             stepper2.setAcceleration(MAX_XCL);
             
             stepper1.moveTo(Move1);
             stepper2.moveTo(0);
              
              vTaskDelay(1);
};
void OSCILLATE_R() {
            while (stepper1.distanceToGo() != 0) {
              stepper2.moveTo(Move_2_B);
              while (stepper2.distanceToGo() != 0) {
                  stepper1.run();
                  stepper2.run();
                  };
              stepper2.moveTo(Move_2_A);
              while (stepper2.distanceToGo() != 0) {
                  stepper1.run();
                  stepper2.run();
                  };
                  vTaskDelay(1);
                  };
                  
              if (stepper1.distanceToGo() == 0) {
                END();
              };
              
              vTaskDelay(1);
};
void END() {
        stepper1.stop();
        stepper2.stop();
        stepper1.disableOutputs();
        stepper2.disableOutputs();
        vTaskDelay(10000);
};
void motor_control() {
   SELECTOR_A();
   OSCILLATE_R();
   END();
};
void loop() {
    motor_control();
};

If there’s anything wrong with it that you could see, any possible culprits, I would be very grateful. When I come back to this tomorrow, I’ll try alternate structures/functions/classes for the run() loops. Very tiring stuff…day 4 with this issue.

jtbennett:
If there's anything wrong with it that you could see, any possible culprits, I would be very grateful.

I assume your latest code is also on an ESP32. Then, if your "you" refers to me, I cannot help - as already mentioned.

Hopefully someone will come along who does have experience with the ESP32 and stepper motors.

...R

PS ... it may be a good idea to edit your Original Post and add the words "on an ESP32" to your Title.

:cry: ok

Hi again - first, thank you Robin2 for humoring me a couple times, but I'm happy to report that the issue was not ESP related. It was my stepper driver current control settings. I had the amperage level at 2.8 (motors rated at 2.8) to maximize torque. When backed down to 2.5, the problem held off a little longer, and then finally down to 2 and everything is functioning just fine.

It could be the cheap Chinese knockoff TB6600 drivers (the ones in the black casing with green wire posts that you're probably all familiar with), or it could be my ugly grounding setup that has everything running to a single point at once before out through the power cable. I dunno, I've never been good at electronics.

I immediately assumed this issue was related to my previous issue from a year ago (before I paused working on this project) related to the watchdog timer (Task Watchdog & AccelStepper · Issue #2892 · espressif/arduino-esp32 · GitHub). It was a very similar result, so I never considered that it was my amperage.

Anyway, sorry to waste your time. Anyone else in the future who may be having trouble running simultaneous motors, try backing the amperage down on your steppers first :slight_smile:

Thanks for the update. Good to see you have a solution.

...R