Stepper Motor Library for Easy Driver, Big Easy Driver, Allegro STEP/DIR chips

Hi everyone,

As part of a much larger project, I wrote a library for controlling stepper motors attached to Easy Drivers, Big Easy Drivers, or any of the Allegro driver chips that use STEP/DIR interfaces.

There are, of course, libraries for this already. Where mine differs, I think, is in a few key points:

  • LGPL instead of GPL. IMO this is important for libraries so as to avoid dictating how other people license the rest of their code.

  • Consistent motor speed regardless of drive mode, set in RPM. If you change drive mode while the motor is moving, its speed will not change.

  • Consistent position index (measured in 1/16th steps) regardless of drive mode, so even after changing drive modes, position 1000 will refer to the same location as before

  • It does linear acceleration, but without any heavy math or floating point numbers. You can set acceleration in RPMPM (RPM per minute) or turn it off entirely. Acceleration allows you to drive heavier loads and reach higher speeds.

  • Handling of the MS1/MS2/MS3 pins using a user-friendly enum to specify a chosen drive mode.

  • Accurate timing. If you set the speed of the motor to 120 RPM, it will move at 120RPM... not 115 or 125. Assuming, of course, that you call the work() method often enough.

  • Automatic handling of Enable pin if desired

I hope others find it useful. It is now on github: GitHub - risitt/kissStepper: Lightweight and fast Arduino and Teensyduino library for controlling a stepper motor driver with a STEP/DIR interface

I've tested it with an Easy Driver. It should also work flawlessly with the Big Easy Driver and Allegro STEP/DIR-based chips, but since I haven't been able to test it with any of them, I'm kept the library in "beta" state.

Hopefully this helps give back to the Arduino community which has helped me for so many years!

Thanks for sharing.

I don't see a description of the API on the Github page but maybe I missed it ?

I wonder if your library is suitable for driving multiple motors in a coordinated way as would be required for CNC or 3D printing? For example MotorA moves 237 steps in the same time that MotorB moves 87 steps.

...R

Hi Robin,

I do intend to document the API very soon. Is there a standard method of doing so, or should I just stick something like an instructions.txt file in there?

Hmm, for moving two motors, you'd have to instantiate two instances of the class. To make two motors move different distances in the same time, you'd then have to calculate the RPM for each separately, but since it is an int, you will almost certainly get error with one finishing earlier than desired.

As I see it, the best way to solve that would be to add a new method which takes two inputs... the target position and the time to get there. For a CNC I'd want to use AVR directly, though. The more frequently you check the stepper timing, the more accurate individual step timing will be. Things like digitalWrite() take up enough clock cycles that they may actually create problems. And maybe run the work() method from a timer interrupt for good measure.

So I guess, short explanation, probably not as written.

Instructions.txt would be a lot better than nothing.

...R

I've added documentation in HTML format. Not sure if that is preferred vs markdown on Github or not... this being my first time actually using Github.

Edit: answered my own question, I went with markdown. Displays nicely in Github.

Writing it made me aware of a few minor things I'd like to change, and I'm still thinking about your comment regarding coordinated stepping of multiple motors. The timing code within the work() method is itself capable of reaching a target position with an timing accuracy of about 4 microseconds (last time I tested it, anyway) on an 8Mhz Arduino Pro Mini. But it's the integer RPM unit that introduces a weakness in terms of how precise you can be. With the public methods, you can use 199 or 200 RPM but not 199.5, for example, and RPM is not the best way of thinking about the type of movements needed for a CNC or 3d printer anyway. So, maybe you can select a pair of RPM settings whose ratio works out to the angle you need, but that is certainly not the most straightforward way of doing it.

I will consider adding a timedMoveTo() method that accomplishes what you want. Would anybody have hardware (a DIY CNC/3d printer) suitable for testing this? Over here, I can test timing with a scope and such, and while I have a bunch of steppers laying around, they certainly aren't connected to a CNC (I wish!)

Full marks for the documentation.

Sorry, but I won't be a CNC guinea pig - it would be too much trouble to change from my already-working DIY code.

My code (on my PC) figures out how many steps are needed by each motor for a given move. Then it figures out which motor will take the longest. Then it allocates the steps for the other motors over the same time interval. And then it sends data to the Arduino telling it the total time for the move and the interval between steps for each motor. That makes my Arduino code as simple as possible.

...R

Ah, well, if you can offload the calculations to the PC, then that's the way to go for sure.

I made this account for the sole purpose of letting you know how great of a library you have made. The documentation is great, you can define microstepping with ease, there's automatic acceleration and deceleration, and you can easily get how far the motor has gone, and you can define how far it goes all with just a few lines of code. It's amazing!

Also, is there a way to decelerate without actually going down to 0. I am running on a track where I am trying to hit a point that is at or further than 9 meters. However, the speed timing ends at 8 meters. Naturally, I want it to go at top speed before 8 meters and then decelerate to a very slow speed so that it can stop more accurately It does stop very accurately with your library now, but I also want to make sure that it does not decelerate before 8 meters.

Also, it does not mention at what rate deceleration happens in the documentation. I'm not sure if it decelerates as fast as possible or if it decelerates as fast as it accelerates.

Also, I tried using the code you provided to get the position of the vehicle and then use an if statement to check if it passed my desired number of steps, but it overshot by nearly a meter. When I used the moveTo method, it worked fine. Both ways of programming it should work. Any idea for why the disparity happens?