AccelStepper with Easy Driver only produces 800 steps and not 1600 steps for a 200 step motor

2,996 views
Skip to first unread message

James Duffy

unread,
Jun 8, 2013, 10:10:52 AM6/8/13
to accels...@googlegroups.com
I am very new to this, and I guess I have learned enough to get into trouble but not out of trouble. 
 
When I use Easy Driver with my Arduino Uno Rev3 without AccelStepper, I get 1600 steps per revolution.  In other words, I get 8 microsteps per motor step.  The motor, a Wantai 57BYGH420,  is definitely a 200 step motor or 1.8 degrees per step. 
 
When I use the same configuration with the below code, which uses AccelStepper, I get two complete revolutions for pos=1600.  In other words, I get only 4 microsteps and not 8.  When I change pos to 800, I get one revolution, which confirms I am only getting 4 microsteps.
 
Here is the code I am using:
 
#include <AccelStepper.h>
 
AccelStepper stepper(1, 3, 2);
int pos = 1600;
 
void setup()

  stepper.setMaxSpeed(200);
  stepper.setAcceleration(100);
}
 
void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(3000);
    pos = -pos;
    stepper.moveTo(pos);
  }
  stepper.run();
}
The physical setup and the code are exactly as shown in Example 3 on Brian Schmaltz's website (http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html), except that I am using pins 3 and 2 rather than 9 and 8 step and dir pins on the Easy Driver. 
 
I would like to get 1600 steps per revolution because this would give me smaller increments than 800 per revolution, and I need the smaller step size to get the precision I want to achieve. 
 
What I am doing wrong, or what do I need to do to do to get to 8 microsteps rather than 4? 
 
Thank you for any help you can provide. 
 
Jim

Sandy Noble

unread,
Jun 8, 2013, 10:28:33 AM6/8/13
to accels...@googlegroups.com
Hi Jim, accelstepper doesn't know anything about microstepping vs regular steps, it just understands steps, and leaves it up to the hardware to decide what to do with them.  So if there is something afoot, then it isn't to do with accelstepper as such.

The only thing I can think has happened is that the MS1 pin that you use to pull the easydriver into 8th stepping mode is either disconnected by accident, or if it is connected to the arduino, you need to pull it high.  Perhaps your other code (for the arduino motor shield) already has this in?


sn


--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Sandy Noble

James P. Duffy, III

unread,
Jun 8, 2013, 11:57:55 AM6/8/13
to accels...@googlegroups.com
Thank you, Sandy, I very much appreciate your prompt reply and your suggestion.  

I revised the code to set MS1 HIGH as you will see below, but still no luck.  I also put it before the "if" statement in the loop portion of the code as well as before the stepper.move and stepper.run commands, but it did not change anything.  Perhaps, I did not put the digitalWrite instruction in the right place?  

Here is the revised code with one version of Pin 4 going to MS1 on the Easy Driver and setting MS1 to HIGH:

#include <AccelStepper.h>

AccelStepper stepper(1, 3, 2);

int pos = 1600;

void setup()
{  
  stepper.setMaxSpeed(200);
  stepper.setAcceleration(100);
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(500);
    pos = -pos;
    stepper.moveTo(pos);
  }
  stepper.run();
}

Just to be sure I was not having a problem with my Easy Driver, I ran a program based on Example 2 on the Schmaltz site.  Here is the code:

//Schmaltz Example 2

int Distance = 0;  // Record the number of steps we've taken

void setup() {                
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT);
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
}

void loop() {
  digitalWrite(3, HIGH);
  delayMicroseconds(100);          
  digitalWrite(3, LOW); 
  delayMicroseconds(100);
  Distance = Distance + 1;   // record this step
  
  // Check to see if we are at the end of our move
  if (Distance == 1600)
  {
    // We are! Reverse direction (invert DIR signal)
    if (digitalRead(2) == LOW)
    {
      digitalWrite(2, HIGH);
    }
    else
    {
      digitalWrite(2, LOW);
    }
    // Reset our distance back to zero since we're
    // starting a new move
    Distance = 0;
    // Now pause for half a second
    delay(500);
  }
}

A distance of 1600 produces a single rotation, just using the Easy Driver directly.  Eight microsteps is the default.  So, I did not do anything to MS1, and Easy Driver defaulted to 8 microsteps.  

I must be missing something here as AccelStepper or my code is somehow changing Easy Driver to 4 microstep mode from 8 microstep mode.  


--
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/qNEK_W18ne0/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

---------------------------------------------------------------------------------------
To comply with U.S. Treasury Regulations, this communication (including any attachments) is not intended or written to be used, and cannot be used, for the purpose of avoiding penalties under the tax laws of the United States, or promoting, marketing or recommending to another party any transaction or matter addressed in this communication (and any attachment). 

Confidentiality Statement:  This message (including any attachments) is intended only for the individual or entity to which it is addressed. It may contain privileged, confidential information that is exempt from disclosure under applicable laws. If you are not the intended recipient, please note that you are strictly prohibited from disseminating or distributing this information (other than to the intended recipient) or copying this information. If you have received this communication in error, please notify the sender immediately by e-mail or by telephone at +1-646-719-0390. 

Brian Schmalz

unread,
Jun 8, 2013, 12:28:44 PM6/8/13
to accels...@googlegroups.com
If you have confirmed that code without AccelStepper produces 8x microstepping, and you did not change your hardware at all, then there must be something different that the code is doing when using AccelStepper. Except that Sandy is exactly right - AccelStepper doesn't 'know' about microsteps at all - it just outputs steps, and the EasyDriver converts each 'step' pulse into one microstep movement.

Thus the suggestion about the MS1 pin is right on.

So, here's an experiment you could try. Completely disconnect the MS1, MS2 and MS3 pins from the EasyDriver. In other words, the only connections from the Arduino to the EasyDriver are Step, Direction and Ground. Nothing else.

Then try running both AccelStepper and non-AccelStepper code, and see if you get the same number of microsteps. You should. Let us know if you don't, and we can debug further.

*Brian

From: accels...@googlegroups.com [accels...@googlegroups.com] on behalf of James P. Duffy, III [jpd...@bergduffy.com]
Sent: Saturday, June 08, 2013 10:57 AM
To: accels...@googlegroups.com
Subject: Re: [accelstepper] AccelStepper with Easy Driver only produces 800 steps and not 1600 steps for a 200 step motor

Geoff Probert

unread,
Jun 8, 2013, 1:14:51 PM6/8/13
to accels...@googlegroups.com
If you ~always~ want x8-microstepping, your Arduino code doesn't need to be involved at all.

Simply Hard-wire MS1 to 5V.

I've done this with some Polulu drivers and it frees-up just a little bit more of the Arduino for doing what I ~really~ want to do.

Geoff
Thailand

Brian Schmalz

unread,
Jun 8, 2013, 2:03:31 PM6/8/13
to accels...@googlegroups.com
The EasyDrivers have MS1, MS2 and MS3 pulled-up to 5V already, so if you want them to be high (default) then  you can just not connect anything to those pins of the ED.

*Brian

From: accels...@googlegroups.com [accels...@googlegroups.com] on behalf of Geoff Probert [geoff...@gmail.com]
Sent: Saturday, June 08, 2013 12:14 PM

To: accels...@googlegroups.com
Subject: Re: [accelstepper] AccelStepper with Easy Driver only produces 800 steps and not 1600 steps for a 200 step motor

James P. Duffy, III

unread,
Jun 8, 2013, 3:22:18 PM6/8/13
to accels...@googlegroups.com
Thank you, Brian,

I have done exactly as you suggested, but this time, I configured the Arduino Uno Rev3 exactly as is set forth on your website and used your code directly from your website, with the exception of making the number of steps 1600 rather than 3600.  The motor is powered by a separate power source (12v, 1a) that is not connected to the Arduino, and the Arduino has its own power supply (9v, 650ma) that is not connected to the Easy Driver.  The only connections between Easy Driver and the Arduino are GRD, 8, and 9.  

Using this code (your Example 2 with Distance set at 1600), I get 8 microsteps (i.e., one revolution):

int Distance = 0;  // Record the number of steps we've taken

void setup() {                
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
}

void loop() {
  digitalWrite(9, HIGH);
  delayMicroseconds(100);          
  digitalWrite(9, LOW); 
  delayMicroseconds(100);
  Distance = Distance + 1;   // record this step
  
  // Check to see if we are at the end of our move
  if (Distance == 1600)
  {
    // We are! Reverse direction (invert DIR signal)
    if (digitalRead(8) == LOW)
    {
      digitalWrite(8, HIGH);
    }
    else
    {
      digitalWrite(8, LOW);
    }
    // Reset our distance back to zero since we're
    // starting a new move
    Distance = 0;
    // Now pause for half a second
    delay(500);
  }
}

Using this code (your Example 3 with pos set at 1600), I get 4 microsteps (i.e., 2 revolutions):

#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(1, 9, 8);

int pos = 1600;

void setup()
{  
  stepper.setMaxSpeed(3000);
  stepper.setAcceleration(1000);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(500);
    pos = -pos;
    stepper.moveTo(pos);
  }
  stepper.run();
}

So, I am doing everything exactly as it appears on your website, except for the number of steps, which is the same in each example, namely 1600.  With the non-AccelSteeper code, I get one revolution or 8 microsteps.  With the AccelStepper code, I get two revolutions or 4 microsteps.  

I think there must be a bug somewhere, but I do not think it is with anything I am doing at this point.  

James P. Duffy, III

unread,
Jun 8, 2013, 3:37:19 PM6/8/13
to accels...@googlegroups.com
Thank you, Geoff,

I tried that by wiring the 5v pin on the Easy Driver to the MS1 pin on the Easy Driver.  Unfortunately, it did not work.  The result remains the same.  Non-AccelStepper code is 8 microsteps, but AccelStepper code is 4 microsteps.  

Very perplexing, and thank you for your efforts.  

Jim


--
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/qNEK_W18ne0/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Brian Schmalz

unread,
Jun 8, 2013, 3:43:15 PM6/8/13
to accels...@googlegroups.com
I have reproduced your observed result exactly with my motors and chipKIT UNO32, and EasyDriver.

And it is a 'feature' of the code you wrote. :-) There's nothing wrong with AccelStepper.

I'll give you a hint - your AccelStepper code works exactly as you expect from step 0 to step 1600. But then after that unexpected things happen. If you watch your motor closely right as it starts running and examine the code closely, you'll see why it's moving twice as far as you expect.

Ooops, maybe I gave it away there.

If you can't find it and get frustrated, let me know, and I'll give you another hint that will explain it.

*Brian

Sent: Saturday, June 08, 2013 2:22 PM

James P. Duffy, III

unread,
Jun 8, 2013, 3:43:18 PM6/8/13
to accels...@googlegroups.com
Thank you, Brian.  

The only connections I have now to the ED are the four pins out to the motor, the two power in pins and the three pins for GRD, Step, and Dir.  

I have nothing connected to any other pins at this point.  

Jim


--
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/qNEK_W18ne0/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

James P. Duffy, III

unread,
Jun 8, 2013, 3:58:21 PM6/8/13
to accels...@googlegroups.com
Brian,

I am afraid I am not much of a code expert yet, and that is why I just copied your code from your website.  

I think it must have something to do with setting pos = -pos which gives a distance of twice the interval, from 1600 to 0 and then 0 to -1600 or vice versa, but I am not expert enough yet in writing code to deal with that.  I wondered about this briefly, but, as it was your code, I thought I just did not understand how the protocols work.  

I would think we would need some sort of if statement rather then setting pos to -pos, such as  If pos > 0, set 8 low if not set 8 high?  I am not sure how to write that though.  Maybe there is something in your Example 2 that works.  

As I simply copied your code from your website, what would you suggest as an alternative?  

I would appreciate your suggestions so I can move forward with what I am really trying to do.  

Jim

Sandy Noble

unread,
Jun 8, 2013, 4:01:34 PM6/8/13
to accels...@googlegroups.com
Sorry I'm going to spoil Brian's mischief :) 

So the accelstepper code moves from 0, up to 1600 (one rev), then pauses for half a second (because .distanceToGo() == 0) and resets the target position to be -1600.  Then the motor whizzes back to that point (3200 steps in the opposite direction - 2 revolutions).  And then it pauses for another half a second, gets set to 1600 again, and starts off in the original direction again.  I think!

sn

Brian Schmalz

unread,
Jun 8, 2013, 4:23:00 PM6/8/13
to accels...@googlegroups.com
Jim,

Yup! That's exactly it.

When you start, you go from 0 to 1600. But then once  you reach 1600, you say "go to -1600", So from 1600 to -1600 is 3200 steps! Thus it takes 2 full rotations, then stops and reverses.

You may not be a code expert yet, but each time you struggle a bit through something like this, you come a lot closer. :-)

*Brian


Sent: Saturday, June 08, 2013 2:58 PM

James P. Duffy, III

unread,
Jun 8, 2013, 4:24:22 PM6/8/13
to accels...@googlegroups.com
If you look at my response to Brian, I think you and are both on the same page here, but I just do not know enough about writing code yet to know what to do to get back to 0 rather than to -1600.  I saw that originally, but I figured that, as Brian is the expert, and, as it was his code, I must have missed something.  

Jim


--
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/qNEK_W18ne0/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

James P. Duffy, III

unread,
Jun 8, 2013, 4:36:36 PM6/8/13
to accels...@googlegroups.com
It seems to me that what we need to do is simply change direction and run pos again, but, as I said, I am not yet at that level of writing code yet.  It would seem to me that this is a more complex problem than first appears because the code on your website needs to be changed.  

James P. Duffy, III

unread,
Jun 8, 2013, 5:11:22 PM6/8/13
to accels...@googlegroups.com
If you change "pos = -pos" to "pos = 1600 -pos" in your code, it works.  In the end, it was more a logic problem than a code writing problem.  

If you change the code on your website, you might want to give me some credit for the change!  

Although I have two bachelors degrees, one in engineering and the other in architecte that I got 50 years ago, I never really used them and have been a lawyer for more than 45 years. I should have realized that right from the beginning.  It did not seem right, but I thought I had to go with what the experts said.  As a lawyer, I should have known that every expert needs to be appropriately cross-examined    

Thanks again for all your work with Easy Driver.  I have plans to make use of quite a few of them one of these days, and, as I really do not want to be a code expert per se, I hope to be able to use published work whenever possible.  

Jim
330.gif

Sandy Noble

unread,
Jun 8, 2013, 5:55:48 PM6/8/13
to accels...@googlegroups.com
I think Brian's code does what it is supposed to - "basically the same thing as Example 2" in the sense that is goes back and forth.

pos = -pos means make pos the same as the inverse of what it is now.  So if pos is 1600, then -pos is -1600.  And if pos is -1600, then -pos is 1600.

So to get back to 0 (from _whatever_ position you ended up in) you just do stepper.moveTo(0). The following might do something more like you expected:

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(3000);
    if (stepper.currentPosition() == 0)
         stepper.moveTo(1600);
    else
         stepper.moveTo(0);
  }
  stepper.run();
}

The reason (I guess) Brian's example doesn't do that is because it takes more code to keep track of what direction the motor has been going in order to set the next target as either 0 _or_ 1600.  In his example code, it doesn't matter whether the direction is up or down, because that same command (the pos = -pos) can be used to flip it from positive to negative and vice versa.  It is a more elegant piece of code, and that technique of inverting the number is not esoteric.  But to make sense it _does_ require that you recognise it as an arithmetic operator rather than some kind of weird switch or language-specific operator - and that's not always obvious.

sn






330.gif

James P. Duffy, III

unread,
Jun 9, 2013, 6:56:27 AM6/9/13
to accels...@googlegroups.com
Thank you, Sandy, for this solution.

I think Brian's website is extremely useful for an inexperienced person like me, because it sets everything out very clearly and simply in easy to understand terms.  However, it was not immediately obvious to me that Example 3 was not the functional equivalent in AccelStepper terms of Example 2.  I think I found one very simple solution (changing "pos = -pos" to "pos = 1600 -pos") to make it a functional equivalent in a basic environment, and you have found another more elegant solution.  I like your suggested code because it gives much more control, and I will explain why that is important to me in a moment.  

My reason for getting involved with Arduino and stepper motors in the first place was to control a HO gauge turntable on a model railroad.  I wanted to use AcellStepper because of the acceleration and deceleration features as there is inertia to the bridge, particularly when there is a heavy engine on it.  My solution for Example 3 takes the bridge of the turntable back to where it started out (the inbound track) from either direction but nothing more.  It seems to me that your solution offers a way to manipulate the bridge to intermediate points on the turntable parameter and still return to the inbound track.  

I still do not understand the coding language that much, but it is definitely interesting to learn about it. I will have to think about it more, but I can see possibilities of using switches or other means to send data to your code, or portions of your code, to go to intermediate points and then return to the inbound track.  

I will no doubt have other issues as I try to move my project forward, but I think I will explore further off line and then start a new thread if I have questions.  

Thank you again and thanks to Brian for all your help and your interest in helping me understand these matters better.  

Jim
330.gif

James P. Duffy, III

unread,
Jun 10, 2013, 8:33:38 AM6/10/13
to accels...@googlegroups.com
In looking at your suggested code more closely, it seems to me to be a very elegant solution that is a very compact Accelstepper equivalent to Example 2 on Brian's website.  In fact, you can even eliminate the pos variable.  It is not needed.  Try this, and you will see it works just fine:

#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(1, 3, 2);

void setup()
{  
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(1000);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(1000);
    if (stepper.currentPosition() == 0)
         stepper.moveTo(1600);
    else
         stepper.moveTo(0);
  }
  stepper.run();
}

I guess I am learning there are often may ways to get to a solution.  

Thanks again, and thank you to Brian and Geoff for their efforts as well.  

Jim


On Sat, Jun 8, 2013 at 5:55 PM, Sandy Noble <sandy...@gmail.com> wrote:
330.gif

Sandy Noble

unread,
Jun 10, 2013, 5:43:07 PM6/10/13
to accels...@googlegroups.com
True enough, the pos as a separate variable is redundant.  It is idiomatic to use variables, sometimes even when it doesn't make sense to!  Programmers usually learn this as soon as they find themselves using the same value in two places, and then forget to change it in one of the places.  If I was using this myself (as opposed for documentary purposes) I would probably do:

int lowTarget = 0;
int highTarget = 1600;
int pauseBetweenMoves = 3000;

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    delay(pauseBetweenMoves);
    if (stepper.currentPosition() == lowTarget)
         stepper.moveTo(highTarget);
    else
         stepper.moveTo(lowTarget);
  }
  stepper.run();
}


It's a way to try and separate the logic from the values it acts on.

sn

Mike McCauley

unread,
Jun 10, 2013, 5:50:02 PM6/10/13
to accels...@googlegroups.com
I fully agree with Sandy's model for production code.
Simple and maintainable.

Cheers.
--
Mike McCauley mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com
Phone +61 7 5598-7474 Fax +61 7 5598-7070

Reply all
Reply to author
Forward
0 new messages