Stepper motor CNC shield accelstepper.h

I am trying to move a stepper motor to specific step positions (Eg:- 50, 150, 200) using accelstepper library. My stepper motor is a NEMA 17HS3401 attached to the CNC shield V3. The code given below was written with the ideas i got from the internet sources and I still can't seem to get it working properly like i want to.

#include <AccelStepper.h>
#define dirPin 5
#define stepPin 2

AccelStepper basestepper = AccelStepper(1, stepPin, dirPin);
void setup() {

basestepper.setMaxSpeed(2000);

}

void loop() {
basestepper.setCurrentPosition(0);
basestepper.moveTo(50);
while(basestepper.currentPosition()!=50)
{
basestepper.run();
}

basestepper.moveTo(150);
while(basestepper.currentPosition()!=150)
{
basestepper.run();
}

basestepper.moveTo(200);
while(basestepper.currentPosition()!=200)
{
basestepper.run();
}

}

NP: The enable pin is already connected to the ground pin using a jumber wire and I believe that is not an issue because the motor is providing the holding torque at idle condiitons.

Actual ouput I want is the motor to stop at positions 50 150 and 200 for brief period of time( 250 milli seconds). The output which I observed is that the motor is moving in small steps which are nowhere close to my desired posiitons (acceleration and decelerations are observed as well). Could anyone point out the issues in my code and if there are any mistakes in my approach. Any help is much appreciated. Thanks in advance

Here is a demo code that I wrote a while back that may be close to what you want to do. It uses an array of positions and an array of speeds. The motor will go to each position in sequence at the speed in the array. Use whatever parts that you need.

#include <AccelStepper.h>

const unsigned int NUM_STEPS = 6;

unsigned int xArray[NUM_STEPS] = {0, 900, 650, 400, 650, 100};
unsigned int xSpeeds[NUM_STEPS] = {200, 2000, 200, 100, 400, 50};

const byte enablePin = 8;

AccelStepper x_stepper(AccelStepper::DRIVER, 2, 5);

void setup()
{
   Serial.begin(115200);
   pinMode(enablePin, OUTPUT);
   digitalWrite(enablePin, LOW);
   x_stepper.setAcceleration(2000);
   x_stepper.setMaxSpeed(200);
   x_stepper.setSpeed(200);
   x_stepper.setCurrentPosition(0);
}

void loop()
{
   static unsigned int index = 0;
   if (x_stepper.run() == 0)
   {
      delay(250);
      Serial.println(index);
      x_stepper.moveTo(xArray[index]);
      x_stepper.setMaxSpeed(xSpeeds[index]);
      index++;
      if (index >= NUM_STEPS)
      {
         index = 0;
      }
   }
}

@groundFungus thankyou for your quick response. Just have a querie regarding the use of x_stepper.run() . From the references I checked out, I understood that run function should be called after setting the position to reach and the speed using these x_stepper.moveTo(xArray[index]);
x_stepper.setMaxSpeed(xSpeeds[index]);

But in the programs you have send , you haven't done that. Could you please correct what part I am understanding the wrong way?

And in the code which you have provided the index will be set to 0 in every iteration of the loop right?

I will try to explain. See the comments.

 // if 1 the stepper has not reached the position so the run function will                               
 // step the stepper but skip over the rest of the code
 // If 0 the stepper has reached the target position and has stopped
 if (x_stepper.run() == 0)  // so the rest of the code will run to load a new speed and position
   {
      delay(250);  // your delay between steps
      Serial.println(index);  
      x_stepper.moveTo(xArray[index]);  // set the next position to the next array position
      x_stepper.setMaxSpeed(xSpeeds[index]);  // set the next speed to the next array position
      index++;  // increment the index for the next step in the sequence
      if (index >= NUM_STEPS)  // if the 6 steps have happened 
      {
         index = 0; // reset the index to 0 to a start a new sequence
      }
   }  //  go back to the top and call run again.  Since a new position and speed have been set
      // the run function will run the stepper at the new speed toward the new position

I hope that that is more clear. If not

No. The index is reset to 0 after the last of the 6 positions has been reached.

The run function must be called over and over to run the stepper. The stepper will only move 1 step if the run function is called and it is time for a step. So to move, say, 200 steps, the run function has to be called at least 200 times and, depending on speed, probably many many more times.

Thanks a lot for that perfect explanation, really helped a lot.
Your code works perfect as it is. I made a small change in the code so that the stepper motor will repeatedly move to the same position over and over again by setting the position of the stepper to zero everytime the index becomes equal to the number of steps. I felt like the code makes sense but the outut doesnt seem to be inline with the code.
The following is the code
#include <AccelStepper.h>
const unsigned int NUM_STEPS = 4;

unsigned int xArray[NUM_STEPS] = {0, 50, 100, 150};
unsigned int xSpeeds[NUM_STEPS] = {200, 200, 200, 200};

const byte enablePin = 8;

AccelStepper x_stepper(AccelStepper::DRIVER, 2, 5);
static unsigned int index = 0;
void setup()
{
Serial.begin(115200);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW);
x_stepper.setAcceleration(2000);
x_stepper.setMaxSpeed(200);
x_stepper.setSpeed(200);
x_stepper.setCurrentPosition(0);
}

void loop()
{

if (x_stepper.run() == 0)
{
delay(250);
Serial.println(index);
x_stepper.moveTo(xArray[index]);
x_stepper.setMaxSpeed(xSpeeds[index]);
index++;
if (index >= NUM_STEPS)
{
index = 0;
x_stepper.setCurrentPosition(0);
delay(80);
}
}
}

I am attaching the drive link to the video of how the motor is rotating. I want the motor to keep stopping at posiiton 0 50 100 and 150respectively but it is not working for some unknown reason. Could you please point out the mistakes i am making , if any...

Drive link for video: https://drive.google.com/file/d/1PJiFoTznvVhXit-91CPM4gjkczostSxQ/view?usp=sharing

@aravindshaji, as your code does not seem to have anything to do with Interfacing w/ Software on the Computer, your topic has been moved to a more suitable location on the forum.

Sorry, I do not know what that means. Can you clarify the difference in what is happening versus what you want?

If you want the stepper to move 50 steps, stop for 250ms, pause 80ms every 4 steps and keep repeating that for ever just do this:

#include <AccelStepper.h>

const byte enablePin = 8;

AccelStepper x_stepper(AccelStepper::DRIVER, 2, 5);

void setup()
{
   Serial.begin(115200);
   pinMode(enablePin, OUTPUT);
   digitalWrite(enablePin, LOW);
   x_stepper.setAcceleration(2000);
   x_stepper.setMaxSpeed(200);
   x_stepper.setSpeed(200);
   x_stepper.setCurrentPosition(0);
}

void loop()
{
   static byte index = 0;  // variable to count moves
   if (x_stepper.run() == 0)
   {
      delay(250);     
      x_stepper.move(50); // move 50 steps relative to last postition
      x_stepper.setMaxSpeed(200);
      index ++;
      // extra delay every 4 steps and reset index
      if(index >= 4)
      {
         index = 0;
         delay(80); 
      }
   }
}

@sterretje could you please make a suggestion as to which will be a more suitable location on the forum.

@groundFungus sorry I didn't make my requirement clear earlier.
I need my stepper motor to stop at regular intervals in a complete rotation based on a user input.
for input as 4 it should stop at 0 50 100 150 200 over and over again
for input as 6, it will have to stop at 0 33 66 100 133 166 200 (approximating the decimal places)
for this purpose I believe I will have to avoid using the relative method as it could lead to creation of cummilative errors after a few rotations. That is why I went for the array method for chosing the positions. But even then I feel like i am getting an output which is not according to the code. Coulld you tell me if i was wrong anywhere in my code. ( the delay of 80ms was a silly move to get a visual indication of the start of next cycle).

I can't speak for @sterretje, but since he put it in Motors, Mechanics, Power and CNC, I would assume that that is the section that he thinks is appropriate.

In your code in reply #6 the stepper only moves 3 times because you set the currentPosition to 0 then the first move in the array is to 0. The stepper is already there (at 0) so no move occurs.

How about this (delay set to 2000 to be able to see the pause):

#include <AccelStepper.h>
const unsigned int NUM_STEPS = 4;

unsigned int xArray[NUM_STEPS] = {50, 100, 150, 200};  // removed 0, added 200
unsigned int xSpeeds[NUM_STEPS] = {200, 200, 200, 200};

const byte enablePin = 8;

AccelStepper x_stepper(AccelStepper::DRIVER, 2, 5);
static unsigned int index = 0;
void setup()
{
   Serial.begin(115200);
   pinMode(enablePin, OUTPUT);
   digitalWrite(enablePin, LOW);
   x_stepper.setAcceleration(2000);
   x_stepper.setMaxSpeed(200);
   x_stepper.setSpeed(200);
   x_stepper.setCurrentPosition(0);
}

void loop()
{

   if (x_stepper.run() == 0)
   {
      delay(250);
      Serial.println(index);
      x_stepper.moveTo(xArray[index]);
      x_stepper.setMaxSpeed(xSpeeds[index]);
      index++;
      if (index > NUM_STEPS) // changed from >= to > to get 4 steps
      {
         index = 0;
         x_stepper.setCurrentPosition(0);
         delay(2000);
      }
   }
}

@groundFungus I tried the code in reply 8, there are a few issues in rotations even then.
https://drive.google.com/file/d/1G-SX3wBxU2fL5r7Q_ldbaUrU34uM3Wt-/view?usp=sharing
Please check the attached video and me know if you know what might be the reason for the same

I tried the code in reply 11 and here is the video
https://drive.google.com/file/d/1G1AuqB33TkmeRNLbZITyaPNy-uaGKiMx/view?usp=sharing

I believe that what you are seeing in both of those videos is the effect of resonance. Undamped steppers running at full steps (no microstepping) suffer from resonance. See this page. I had to set my drivers to, at least, x2 to get smooth running while testing the code that I posted. I usually run x4 to x16 in my applications. Most of the motors that I have resonate at 200 steps/second (full steps), right where your speed is.

So I suggest that you set the drivers to microstepping at x4 (quarter step) and adjust the steps and speeds in the arrays accordingly.

MS1 MS2 MS3 Microstep Resolution
Low Low Low Full step
High Low Low Half step
Low High Low Quarter step
High High Low Eighth step
High High High Sixteenth step

low is no jumper, high is jumper in place.

I am really sorry for the late reply.
I am very new to stepper motors and thus I am not very good at the concepts of micro stepping.
Just to get a confirmation,
In full step mode speed of 200 steps/rev and displacement of 200 steps will be equal to a speed of 800 steps/rev and a displacement of 800 steps respectively in quarter step mode. And this is the only change i have to make in the code right?

Thanks a lot for your help

That is right.

Hi, this is really helpful, can you please tell how to control 4 stepper motors independently at same time with this kind of array (mot important requirement) work and also please tell me how to have a pause in rotation for a fixed time (in seconds) while it's operating.

I have to actually control 4 motors at independent speeds with speed calculation using a equation for all 4 motors independently (equation tells speed of motor w.r.t time).
I can use this method, then I will not use equation , but I need to know how to program for 4 motors, then I will put all speed and steps for them so to get desired result.

But if you have any other idea on how to use an equation (which I already have) to get speed and steps and then run the motors in real time with the formula I have, then it will help me to eliminate the array step and develop a system which will fill steps and speed in real time.

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