Stepper Motor Setup Trouble Shooting CNC Shield V3.0 - AccelStepper.h

Hi all,

I'm trying to setup a couple NEMA 17 motors but running into some trouble. I'm using a single motor in full step mode with no load. Running on the code below using the AccelStepper library, to run the stepper at a constant speed.

The problem I'm having when using this code is that the stepper does not run constantly but instead spins for a couple revolutions then stops. It does this on all three of my motors and drivers.

With a simple sketch using delays between turning the step pin HIGH and LOW, I have gotten the motors to run constantly without a problem. But I would prefer to use a library as I'm controlling multiple steppers.

My Setup:

I'm calculating the stepper current limit using this equation. Current Limit = Vref / (8 x Rcs). Measuring the voltage between the potentiometer and ground.

Various guides I have seen online recommend using various equations for calculating the current limit, so I'm not sure whether this is correct.

Currently I'm running the drivers using 0.8 / (8 x 0.1) = 1A.
The A4988 has two R100 resistors on the side which is where I got the RCS value from.

Any help would be appreciated.
Cheers

#include <AccelStepper.h>

#define step_x 2
#define step_y 3
#define step_z 4

#define dir_x 5
#define dir_y 6
#define dir_z 7

// AccelStepper stepper_x(1, step_x, dir_x);
AccelStepper stepper_y(1, step_y, dir_y);
// AccelStepper stepper_z(1, step_z, dir_z);


void setup() 
{
    stepper_y.setMaxSpeed(1000);
    stepper_y.setSpeed(100);
}

void loop() 
{
stepper_y.runSpeed();
}

Your code that just uses the function-call

should work as expected
Have you checked the temperature of the of the A4988-chip?
After what amount of time does the motor stop?
Did you run your test-code using delay() for the same amount of time?

Did you try to measure the real coil-current?
Be careful when measuring the real coil-current.
You should only connect / disconnect the motor-wires when the power-supply of the stepper-motor is switched off.

The coils are inductive loads and cause high voltage spikes on connecting disconnecting under power.
This can destroy / damage the A4988-driver

If you try to measure the real coil-current you have to use full-step-mode and send single step-pulses.
The current goes up and down with the steps and you have to catch that step where the highest current is applied from the A4988-driver to the motor.

best regards Stefan

Check the temperature of the driver chip. I use heatsink and a fan to run "forever",

1 Like

Hi Stefan,

Thank you for your reply.

I've run some more tests to verify my claims.
The stepper motor doesn't run for longer than 10 seconds using the AccelStepper Library code and the driver stays cold.

The test code for using delay() ran for over 8 minutes (I stopped the test), two out of the three times I tested it. However, on the first test the stepper only ran for 3mins and stopped similarly to the AccelStepper. Then ran no problem, for the other test after a reboot.

Only during the delay() tests did the driver heatsink get slightly warm to the touch.

I haven't tried measuring the real coil-current. Is this something you would recommend over the potentiometer method?

Is this the case when the microcontroller is unpowered? As the stepper motor doesn't seem to be energized or drawing any current from my bench top psu.

Post a real picture of your real hardware setup

Post your digitaWrite HIGH-LOW delay-code

post what microcontroller you are really using

What happens if you repeat the test with the digitalWrite HIGH-Low code ?

Not sure what that means if you write

This is a too short description to be really understandable.
You should explicitly write for each and every component what has power switched on and what has power switched off

I have created a WOKWI-simulation with exact your code
This code runs and runs and runs.

As you can see from the screenshots the code has run up to more then 2^16 steps still running.
So it is very likely that you have either a hardware-problem
or
on the arduino is running a different code-version than you have posted.
To exclude this possability you should upload a new code-version that blinks the onboard led for three times in setup to indicate this new code was successfully uploaded

1 Like

Hardware




Code uploaded properly.

#include <AccelStepper.h>

#define step_x 2
#define step_y 3
#define step_z 4

#define dir_x 5
#define dir_y 6
#define dir_z 7

int led = 13;

// AccelStepper stepper_x(1, step_x, dir_x);
AccelStepper stepper_y(1, step_y, dir_y);
// AccelStepper stepper_z(1, step_z, dir_z);


void setup() 
{
  pinMode(led, OUTPUT);

  for(int n = 0; n < 3; n++)
  {
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
    delay(500);
  }

  stepper_y.setMaxSpeed(1000);
  stepper_y.setSpeed(100);
}

void loop() 
{
stepper_y.runSpeed();
}

#define step_x 2
#define step_y 3
#define step_z 4

#define dir_x 5
#define dir_y 6
#define dir_z 7

//Set up timing
unsigned long previous_stepper_time = millis();

long stepper_interval = 1;


void setup() 
{
  pinMode(step_y, OUTPUT);
  pinMode(dir_y, OUTPUT);

  digitalWrite(dir_y, LOW);
}

void loop() 
{
  unsigned long current_stepper_time = millis();

  digitalWrite(step_y, LOW);

  if(current_stepper_time - previous_stepper_time > stepper_interval){
    digitalWrite(step_y, HIGH);
    previous_stepper_time = current_stepper_time;
  }
}

and after what time does the motor stop rotating?

Do you have a digital multimeter that can measure frequency?

Do you have a second microcontroller ?
That coud be used to measure the frequency of the step-output?

as an alternative
install the MobaTools-libary with the library-manager of the Arduino-IDE

Then use the minimum stepper example-code to test the stepper-motor

/* ====== minimumStepper =======================================
 *  Bare minimum to get a stepper with step/dir driver turning
 */
#include <MobaTools.h>
// Stepper connections - Please adapt to your own needs.
const byte stepPin = 3;
const byte dirPin = 6;

const int stepsPerRev = 200;    // Steps per revolution - may need to be adjusted

MoToStepper stepper1( stepsPerRev, STEPDIR );  // create a stepper instance

void setup() {
  stepper1.attach( stepPin, dirPin );
  stepper1.setSpeed( 300 );              // 30 rev/min (if stepsPerRev is set correctly)
  stepper1.setRampLen( stepsPerRev / 2); // Ramp length is 1/2 revolution
  stepper1.rotate(1);                    // start turning, 1=vorward, -1=backwards                    
}

void loop() {
}

The Accel Stepper ran for no longer than 5 seconds before stopping.
Ran the millis() code test twice again, lasted 3mins (stopped) and 7mins (turned it off).

My multimeter does measure frequency. Never used it before! First time for everything. I connected it to ground and positive probe to the step pin for step_y. It read 99.9Hz for the duration the stepper rotated then after 10seconds the motor stop and it dropped to 0.0Hz. (Accel)

Very strange behaviour!???!?!?!

Would you mind installing the MobaTools-Library and test the MobaTools-library?

The MobaTools have the advantage of beeing able to
"set and forget "

driving the stepper-motor.

You do a single function-call and the motor runs
either infinitely with function
rotate(1);
rotate(-1);

or a specified number of steps as relative or absolute position
The step-pulses are created in the backround through a timer-interrupt
This means you can execute code in parallel to the step-pulse-creation

best regards Stefan

1 Like

I tried the example code you provided above and it worked. I tested it for 8 minutes and it ran no problem. Driver heat sink remained cool as well.

Indeed :confused:

With the accelstepper-code you have the smallest possible loop()

#include <AccelStepper.h>

#define step_x 2
#define step_y 3
#define step_z 4

#define dir_x 5
#define dir_y 6
#define dir_z 7

int led = 13;

// AccelStepper stepper_x(1, step_x, dir_x);
AccelStepper stepper_y(1, step_y, dir_y);
// AccelStepper stepper_z(1, step_z, dir_z);


void setup() 
{
  pinMode(led, OUTPUT);

  for(int n = 0; n < 5; n++)
  {
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
    delay(500);
  }

  stepper_y.setMaxSpeed(1000);
  stepper_y.setSpeed(100);
}

void loop() 
{
stepper_y.runSpeed();
delayMicroseconds(800);
}

test again with a small delay
if it does not work increase the delaytime

1 Like

It ran for longer than 10seconds! I had to call it quits for today though, I don't want to wake people up with the whining motor. I'll run a proper test tomorrow.

Thank you so much Stefan. Really appreciate your help! :slight_smile:

Played around with adding delay time.
Starting to feel like a hardware issue? Throughout testing the motors has been running very loud. I measure between 65-70dB on my phone.

Delay (μs) Run Time 1 Run Time 2
800 01:00 01:08
1000 00:54 05:00
1200 00:58 02:30
1400 00:57 00:20
2000 01:09 02:03
3000 01:51 03:00
4000 02:57 02:40

I think it is a software issue of accelstepper.
Your loop()-function has only these two commands

This means the loop is "looping" very fast.
Your digital Multimeter can for sure measure frequencies in the 100 kHz-range
which is way more than any stepper-motor can do and more than accelstepper can do.

In a former test you measured frequency and the frequency dropped at the same time as the motor stopped.

A4988 drivers do their job but are not the best ones.
Have you ever tried to use 1/16 microstepping stepping mode?

the more microsteps the higher the frequency must be to reach the same rpm
example:
100 rpm at fullstep-mode is 100 Hz

100 rpm at 1/16 microstepping mode is 100 * 16 = 1600 Hz which might be already above what accelstepper can do on an arduino-uno

There is another parameter you can test
https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#af4d3818e691dad5dc518308796ccf154

setMinPulseWidth(100);

So you could run a test

#include <AccelStepper.h>

#define step_x 2
#define step_y 3
#define step_z 4

#define dir_x 5
#define dir_y 6
#define dir_z 7

int led = 13;

// AccelStepper stepper_x(1, step_x, dir_x);
AccelStepper stepper_y(1, step_y, dir_y);
// AccelStepper stepper_z(1, step_z, dir_z);


void setup() 
{
  pinMode(led, OUTPUT);

  for(int n = 0; n < 5; n++)
  {
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
    delay(500);
  }
  setMinPulseWidth(200);

  stepper_y.setMaxSpeed(1000);
  stepper_y.setSpeed(100);
}

void loop() 
{
stepper_y.runSpeed();
delayMicroseconds(800);
// delay(1);  // alternativey use a 1 millisecond delay
}

Anyway me personal I always prefer the MobaTools over any other stepper-library
because of the set and forget feature

best regards Stefan

I had only tried 1/4 step before. Just given 1/16 a try, much quieter as expected. But the problems persist.

I believe that setSpeed() is only reliable up to 1000 for most applications...
Trying 1/16 microsteps at setSpeed(1000) it had a frequency of 0.998kHz but after 15s of running the frequency bumped up to 1.464kHz which was interesting.

I tried to use the code you provided but it resulted in a compile error stating that setMinPulseWidth was not declared?!

All of that said I will move forward with your recommendation of MobaTools and scrap AccelStepper for now.

Cheers Tom