Moving a stepper motor to two places with one command and AccelStepper library

Hello, I need with one command lets say character "V" to make two movements, moveTo(2000) and then moveTo(0) again (I have performed homing before sending the command). However as it stands, it only takes the second command and doesn't move at all. I am thinking it has something to do with not being in the void loop. Any help ? The first movement comes from Grab() and the second from Z_GO_BACK(). If I use the serial again with "B" it works as it should however I need it to be doing the 2 movements automatically without me intervening. The code is this

#include <AccelStepper.h>

char receivedCommand;
int receivedCell;


int travel_z = 2000;


bool newData, runallowedz = false; // booleans for new data from serial, and runallowed flag


AccelStepper stepper_z(1, 4, 5);// direction Digital 9 (CCW), pulses Digital 8 (CLK)


#define home_switchz 10 //Limit switch z





void setup() {
  Serial.begin(9600); //define baud rate


  //setting up some default values for maximum speed and maximum acceleration
  Serial.println("Default speed: 400 steps/s, default acceleration: 800 steps/s^2.");


  //Stepper z
  stepper_z.setMaxSpeed(400); //SPEED = Steps / second
  stepper_z.setAcceleration(800); //ACCELERATION = Steps /(second)^2

  stepper_z.disableOutputs(); //disable outputs

  
    
  pinMode(home_switchz, INPUT_PULLUP);

  
}

void loop() {
    //Constantly looping through these 2 functions.
    //We only use non-blocking commands, so something else (should also be non-blocking) can be done during the movement of the motor
 
    checkSerial(); //check serial port for new commands
    

    RunTheMotorz(); //function to handle the motor   z


}




void checkSerial() //function for receiving the commands
{  
    if (Serial.available() > 0) //if something comes from the computer
    {
        receivedCommand = Serial.read(); // pass the value to the receivedCommad variable
        newData = true; //indicate that there is a new data by setting this bool to true
 
        if (newData == true) //we only enter this long switch-case statement if there is a new command from the computer
        {
            switch (receivedCommand) //we check what is the command
            {
 
            case 'V': //R uses the moveTo() function of the AccelStepper library, which means that it moves absolutely to the current position.            
             Grab();
             Z_GO_BACK(); 
             break; 

             case 'B': 
             Z_GO_BACK();
             break;  

 
 
            case 'L': //L: Location
 
                
                runallowedz = false; //we still keep running disabled
                stepper_z.disableOutputs(); //disable power
                Serial.print("Current location of the motor Z: ");//Print the message
                Serial.println(stepper_z.currentPosition()); //Printing the current position in steps.
                break;
               
            case 'H': //H: Homing
 
                runallowedz = true;
         
                Serial.println("Homing"); //Print the message
                
                GoHomez();// Run the function
                break;
 
            default:  

                break;
            }
        }
        //after we went through the above tasks, newData is set to false again, so we are ready to receive new commands again.
        newData = false;       
    }
}

void Grab()
{  
    runallowedz = true; 
    stepper_z.setMaxSpeed(400);
    stepper_z.moveTo(2000);
   
}

void Z_GO_BACK()
{
    runallowedz = true;
    stepper_z.setMaxSpeed(400);
    stepper_z.moveTo(0);
  
   
}


void RunTheMotorz() //function for the motor
{
    if (runallowedz == true)
    {
        stepper_z.enableOutputs(); //enable pins
        stepper_z.run(); //step the motor (this will step the motor by 1 step at each loop)  
    }
    else //program enters this part if the runallowed is FALSE, we do not do anything
    {
        stepper_z.disableOutputs(); //disable outputs
        return;
    }
}



void GoHomez(){
  long initial_homingz=1;
  stepper_z.setMaxSpeed(100.0);     
  stepper_z.setAcceleration(100.0);

   while (digitalRead(home_switchz)) {  // Make the Stepper move CCW until the switch is activated   
    stepper_z.moveTo(initial_homingz);  // Set the position to move to
    initial_homingz++;  // Decrease by 1 for next move if needed
    stepper_z.run();  // Start moving the stepper
    delay(5);
  }
  stepper_z.setCurrentPosition(0);  // Set the current position as zero for now
  stepper_z.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepper_z.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homingz=-1;

  while (!digitalRead(home_switchz)) { // Make the Stepper move CW until the switch is deactivated
    stepper_z.moveTo(initial_homingz);  
    stepper_z.run();
    initial_homingz--;
    delay(5);
  }
  stepper_z.setCurrentPosition(0);
}

Thank you in advance

AccelStepper rotates the stepper when run() is executed. moveTo() only sets the target position, so if Z_GO_BACK() is executed after Grab(), the target position is overwritten.

Whether the destination has been reached by run() can be determined by stepper.distanceToGo().
like this:
AccelStepper: Random.pde (airspayce.com)

Edit: if you want to wait until the stepper move, you can use runToNewPosition().
like this:
AccelStepper: Blocking.pde (airspayce.com)

1 Like

Thank you very very very much!! Changing the commands from moveTo() to runToNewPosition() was excactly what I needed. I didn't know what blocking was or that it was a thing and I thought I had to manually calculate the time needed for a motor to get to a position and then add it as a delay(). I have since read that this is the worst thing you could do. I have a follow up question regarding blocking and 2 stepper motors having the same dir and pulse. Should I open another thread, could I pm you, can I ask it right here in the comments? I am not familiar with the way the forum rules work, so I await your response to what I should do and hopefully your help again.

According to How to get the best out of this forum - Using Arduino / Installation & Troubleshooting - Arduino Forum, you can ask same thread if your question come from same your project.

1 Like

Very well. Let's say I have 3 motors, 1 for z and 2 for y. As stated previously the dir and pulse is the same for the 2 y motors. Based on your response the movement of a motor works exactly how I want to, however I need to perform the following sequence. Move the z axis while blocking and not doing anything, then move the y axis while blocking and not doing anything, again return the z axis to its initial position and lastly return the y axis to its initial position while blocking and not doing anything. However, having 2 motors for the y axis makes this impossible with the runToNewPosition() function. As shown in the code below

stepper_z.runToNewPosition(2000);

stepper_y1.runToNewPosition(1000);
stepper_y2.runToNewPosition(1000);

stepper_z.runToNewPosition(0);

stepper_y1.runToNewPosition(0);
stepper_y2.runToNewPosition(0);


what will happen is the y1 motor will move first each time and then the y2 will begin. If I use the moveTo() function based on my original question the motors y1 and y2 will not move from the position 0 because the moveTo() function as you stated will get overwritten.

So, what I am asking, and this will be my last question should you have a solution, is:
Is there a way to move the y1 and y2 motors simultaneously while also blocking? In detail can y1 and y2 go to 1000 together but also while blocking the rest of the commands?

The MultiStepper class is useful if you want to run multiple motors simultaneously.
The following example is helpful.
AccelStepper: MultiStepper.pde (airspayce.com)

Thanks again! Right before you answered I remembered I have seen there is a MultiStepper class and was looking into it.

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