Pololu A4988 chopper stepper driver

I don't see many threads for this board, so I thought I'd post one.

By way of learning Arduino programming and helping my friend learn, too, I'm helping him automate a manual drilling machine. It has a rotary tool shaft that it moves on a linear slide, contolled by a hand cranked 1/4-20 allthread.

We've put a small stepper on it from a junked printer. The Stepper library is not meant for a Step/Dir control like the A4988, so I'm writing code for it.

We started with the Blink Without Delay sketch. millis() does not have the speed sufficient to move a stepper at any useful speed, so I am using micros() instead. It was fairly straightforward to convert it.

I found a mistake in Blink Without Delay - it does the math correctly to avoid the Rollover problem (millis() rolls over after about 49 days), but it mistakenly uses a long instead of an unsigned long for previousMillis. Simple enough to correct. Perhaps not much of a problem, although it would cause errors after half of the time to rollover, about 24 days. But for micros(), which rolls over in about 9 hours, it would cause it to break after about 4.5 hours.

Anyway, using micros() we've got a 200 step per turn motor running at 4 inches per second, which is all his drilling machine will take until we replace a few parts.

Here is a video we shot of it just moving back and forth every 5 seconds:

We tried using tone() to output steps, and it works great. But if the code were to crash, tone keeps sending, and the stepper would keep running. Using micros(), if the code crashes, the Arduino should stop sending Step signals. At least it is less likely to.

We'll be adding Home and End microswitches, a display, and a bunch of buttons to control various functions.

I’m doing something similar with a small metal working lathe which I hope will also be able to operate as a 3D printer.

…R

Anyway, using micros() we've got a 200 step per turn motor running at 4 inches per second, which is all his drilling machine will take until we replace a few parts.

I'm impressed that you are getting a stepper to run at (20t.p.i. x 4in. x 60) 4,800 r.p.m. especially from that setup!

Now that would be a video to see.

Snork. Oops… I think I multiplied instead of dividing in there somewhere. That would be impressive!

500uS between Step transitions with full steps, therefore 1mS between steps with 200 steps per turn, therefore 0.2Sec per revolution. So in one second, 5 turns or 300rpm. That’s more like it. With a 1/4-20 allthread, 1/4 inch per second. We set the Sketch to switch direction every 5 seconds, so it is moving back and forth 1-1/4 inches.

How embarrassing…

polymorph:
I found a mistake in Blink Without Delay - it does the math correctly to avoid the Rollover problem (millis() rolls over after about 49 days), but it mistakenly uses a long instead of an unsigned long for previousMillis. Simple enough to correct. Perhaps not much of a problem, although it would cause errors after half of the time to rollover, about 24 days. But for micros(), which rolls over in about 9 hours, it would cause it to break after about 4.5 hours.

Doesn’t matter, it only limits the maximum delay you can wait for to 4.5 hours, the
rollover doesn’t break because the difference is taken and the difference is correct
with both signed and unsigned values (useful property of 2’s complement arithmetic)

Signed and unsigned subtraction are exactly the same operations at the bit
level, if you ignore overflow/underflow (which C explicitly does).

Signed and unsigned comparison are different however, but we are always comparing
a non-negative number to a non-negative interval so it only limitation is the largest
positive interval you can represent (4.5 or 9 hours).

But you are right, the code should use unsigned.

Signed and unsigned comparison are different however, but we are always comparing
a non-negative number to a non-negative interval so it only limitation is the largest
positive interval you can represent (4.5 or 9 hours).

But if I am first loading an unsigned integer into a signed integer, and the unsigned integer is greater than the signed integer can hold, how does that roll over?

This is a code fragment typed from memory with stuff missing:

long currentMillis = 0;
long previousMillis = 0;
int interval = 0;
bool currentStep = 0;

void setup() {
// set the step, direction, and enable pins as outputs

void loop() {

currentMillis = millis();

if (currentMillis - previousMillis > interval) {
currentStep = !currentStep;
digitalWrite(stepPin, currentStep);
previousMillis = currentMillis;
}

So after about 4.5 hours, millis() will be greater than the 2x10^9 that currentMillis can hold. What ends up in CurrentMillis, then?

I haven't done any calculations so I may well be wrong (as often happens) ...

The only difference between an unsigned long and a long is the way the compiler treats the most significant bit. Both will have exactly the same binary digits.

And (here I'm just guessing) I wonder if it makes no difference to the binary subtraction whether it's a long or an unsigned long - as long as the "interval" is less than a long?

...R