The Big Easy Stepper Motor Driver + Arduino
Stepper (or step) motors are really cool. They are perfect for automation or any time you need a motor to turn to a specific point, at a specific speed, in a specific direction. And, unlike typical motors, steppers are able to do all of this, and hold their position when they are not moving - The trade off is that they cant move as fast, and you have to power them at full power all the time, but you get total control in return.
Steppers have a minimum amount they can move known as a step. You can feel these steps if you slowly turn your stepper by hand. The most common steppers have 200 steps per revolution, so all movement is in 1.8º increments (360º / 200). Controlling them can get tricky at first, so today we are doing an article on using the Big EasyDriver Stepper Motor Driver. The big easyDriver is the big brother of the easy driver we wrote about last year. It is able to take a lot more abuse and power, so it isn't as easy to destroy as the easy driver, can power much larger motors, and it also gives you a little more control by letting you change the microstepping setting.
Motor Voltage / Current
A lot of people ask about what voltage they should use to power their motor. Well, when using a stepper driver, you are powering the driver, not the motor. The driver will take over powering the motor for you.
It is best to power the driver with the highest voltage you can ( up to 35V max for this driver ). This will allow the motor to spin faster than if powered at a lower voltage. Exactly why this is is pretty complex, but if you want to know more about it, you should really read this: Gecko Drive - Step Motor Basics
On the bigEasy driver is a mini potentiometer to control the current to the motor. This varies between 0ma and 2A (2000ma). You want to set it to whatever your motor is rated to. Too high, and you could burn the motor up, too low, you wont get all the power out of your motor. Note: The arrow indicators on the current adjustment potentiometer are backwards. Keep this in mind when adjusting the current limits. If you are running a higher power motor, you will probably want to put a heat sink on the driver as well.
Hooking it up
Even though there are some 30 pins on the Big Easy Driver, we only need a few to get this up and running. In fact, a good deal of the pins are actually just duplicates that are spaced out differently.
The barebones setup:
Power the driver with 8-35v - If using a wall adapter, make sure the adapter has at least enough current for the motor. A higher current/amperage rating is better, and just means it wont burn out. (The Big Easy Driver can supply up to 2 amps)
Connect the 3 control wires from the "gnd", "dir", and "step" of the Big Easy Driver to the Arduino as shown.
Connect the stepper motor to the driver - For me the red/green were one pair, and the blue/yellow was another. If this does not work for you, see the section below on finding your motors coil pairs.
Code
For the arduino code for the driver, im going to be using AccelStepper Library. This is an amazing library that I use for all my stepper needs now. It is even does acceleration and deceleration, supports multiple drivers at once, and most importantly it is non blocking. Meaning, you can be moving your motor as you are reading from a sensor, or turning on lights etc.
The library even keeps track of the position of the motor. So if you tell it to go to 10,000 - It knows it is at 9,00 already, so it moves an additional 1000 steps. Then you can tell it to go home, and it will go back 10,000 steps to 0.
I highly recommend you download the full library from the author. The version I have here is barebones with none of the examples. It is just here because I believe if you post code, you should post everything you need to make it work
To make this code work, before you load the code, or even open the Arduino program, we need to place the "AccelStepper" folder into your Arduino Library. If you don’t know where that is by default, Look to the right.
If you click the download button to the right of “Arduino” you can download the whole thing as a zip, so you dont need to copy all the files.
Default Library Folder Location
On your Mac:: In (home directory)/Documents/Arduino/libraries
On your PC:: My Documents -> Arduino -> libraries
On your Linux box:: (home directory)/sketchbook/libraries
AccelStepper.cpp
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
// AccelStepper.cpp
//
// Copyright (C) 2009 Mike McCauley
// $Id: AccelStepper.cpp,v 1.5 2012/01/28 22:45:25 mikem Exp mikem $
#include "AccelStepper.h"
void AccelStepper::moveTo(long absolute)
{
_targetPos = absolute;
computeNewSpeed();
}
void AccelStepper::move(long relative)
{
moveTo(_currentPos + relative);
}
// Implements steps according to the current speed
// You must call this at least once per step
// returns true if a step occurred
boolean AccelStepper::runSpeed()
{
// Dont do anything unless we actually have a speed
if (_speed == 0.0f)
return false;
unsigned long time = micros();
// Gymnastics to detect wrapping of either the nextStepTime and/or the current time
unsigned long nextStepTime = _lastStepTime + _stepInterval;
if ( ((nextStepTime >= _lastStepTime) && ((time >= nextStepTime) || (time < _lastStepTime)))
|| ((nextStepTime < _lastStepTime) && ((time >= nextStepTime) && (time < _lastStepTime))))
{
if (_speed > 0.0f)
{
// Clockwise
_currentPos += 1;
}
else if (_speed < 0.0f)
{
// Anticlockwise
_currentPos -= 1;
}
step(_currentPos & 0x7); // Bottom 3 bits (same as mod 8, but works with + and - numbers)
_lastStepTime = time;
return true;
}
else
{
return false;
}
}
long AccelStepper::distanceToGo()
{
return _targetPos - _currentPos;
}
long AccelStepper::targetPosition()
{
return _targetPos;
}
long AccelStepper::currentPosition()
{
return _currentPos;
}
// Useful during initialisations or after initial positioning
void AccelStepper::setCurrentPosition(long position)
{
_targetPos = _currentPos = position;
computeNewSpeed(); // Expect speed of 0
}
void AccelStepper::computeNewSpeed()
{
setSpeed(desiredSpeed());
}
// Work out and return a new speed.
// Subclasses can override if they want
// Implement acceleration, deceleration and max speed
// Negative speed is anticlockwise
// This is called:
// after each step
// after user changes:
// maxSpeed
// acceleration
// target position (relative or absolute)
float AccelStepper::desiredSpeed()
{
float requiredSpeed;
long distanceTo = distanceToGo(); // +ve is clockwise from curent location
if (distanceTo == 0)
return 0.0f; // We're there
// sqrSpeed is the signed square of _speed.
float sqrSpeed = sq(_speed);
if (_speed < 0.0)
sqrSpeed = -sqrSpeed;
float twoa = 2.0f * _acceleration; // 2ag
// if v^^2/2as is the the left of target, we will arrive at 0 speed too far -ve, need to accelerate clockwise
if ((sqrSpeed / twoa) < distanceTo)
{
// Accelerate clockwise
// Need to accelerate in clockwise direction
if (_speed == 0.0f)
requiredSpeed = sqrt(twoa);
else
requiredSpeed = _speed + fabs(_acceleration / _speed);
if (requiredSpeed > _maxSpeed)
requiredSpeed = _maxSpeed;
}
else
{
// Decelerate clockwise, accelerate anticlockwise
// Need to accelerate in clockwise direction
if (_speed == 0.0f)
requiredSpeed = -sqrt(twoa);
else
requiredSpeed = _speed - fabs(_acceleration / _speed);
if (requiredSpeed < -_maxSpeed)
requiredSpeed = -_maxSpeed;
}
// Serial.println(requiredSpeed);
return requiredSpeed;
}
// Run the motor to implement speed and acceleration in order to proceed to the target position
// You must call this at least once per step, preferably in your main loop
// If the motor is in the desired position, the cost is very small
// returns true if we are still running to position
boolean AccelStepper::run()
{
if (_targetPos == _currentPos)
return false;
if (runSpeed())
computeNewSpeed();
return true;
}
AccelStepper::AccelStepper(uint8_t pins, uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4)
{
_pins = pins;
_currentPos = 0;
_targetPos = 0;
_speed = 0.0;
_maxSpeed = 1.0;
_acceleration = 1.0;
_stepInterval = 0;
_minPulseWidth = 1;
_dirInverted = false;
_stepInverted = false;
_enablePin = 0xff;
_lastStepTime = 0;
_pin1 = pin1;
_pin2 = pin2;
_pin3 = pin3;
_pin4 = pin4;
//_stepInterval = 20000;
//_speed = 50.0;
//_lastRunTime = 0xffffffff - 20000;
//_lastStepTime = 0xffffffff - 20000 - 10000;
enableOutputs();
}
AccelStepper::AccelStepper(void (*forward)(), void (*backward)())
{
_pins = 0;
_currentPos = 0;
_targetPos = 0;
_speed = 0.0;
_maxSpeed = 1.0;
_acceleration = 1.0;
_stepInterval = 0;
_minPulseWidth = 1;
_dirInverted = false;
_stepInverted = false;
_enablePin = 0xff;
_lastStepTime = 0;
_pin1 = 0;
_pin2 = 0;
_pin3 = 0;
_pin4 = 0;
_forward = forward;
_backward = backward;
}
void AccelStepper::setMaxSpeed(float speed)
{
_maxSpeed = speed;
computeNewSpeed();
}
void AccelStepper::setAcceleration(float acceleration)
{
_acceleration = acceleration;
computeNewSpeed();
}
void AccelStepper::setSpeed(float speed)
{
if (speed == _speed)
return;
if ((speed > 0.0f) && (speed > _maxSpeed))
_speed = _maxSpeed;
else if ((speed < 0.0f) && (speed < -_maxSpeed))
_speed = -_maxSpeed;
else
_speed = speed;
_stepInterval = fabs(1000000.0 / _speed);
}
float AccelStepper::speed()
{
return _speed;
}
// Subclasses can override
void AccelStepper::step(uint8_t step)
{
switch (_pins)
{
case 0:
step0();
break;
case 1:
step1(step);
break;
case 2:
step2(step);
break;
case 4:
step4(step);
break;
case 8:
step8(step);
break;
}
}
// 0 pin step function (ie for functional usage)
void AccelStepper::step0()
{
if (_speed > 0)
_forward();
else
_backward();
}
// 1 pin step function (ie for stepper drivers)
// This is passed the current step number (0 to 7)
// Subclasses can override
void AccelStepper::step1(uint8_t step)
{
digitalWrite(_pin2, (_speed > 0) ^ _dirInverted); // Direction
// Caution 200ns setup time
digitalWrite(_pin1, HIGH ^ _stepInverted);
// Delay the minimum allowed pulse width
delayMicroseconds(_minPulseWidth);
digitalWrite(_pin1, LOW ^ _stepInverted);
}
// 2 pin step function
// This is passed the current step number (0 to 7)
// Subclasses can override
void AccelStepper::step2(uint8_t step)
{
switch (step & 0x3)
{
case 0: /* 01 */
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
break;
case 1: /* 11 */
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, HIGH);
break;
case 2: /* 10 */
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
break;
case 3: /* 00 */
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, LOW);
break;
}
}
// 4 pin step function for half stepper
// This is passed the current step number (0 to 7)
// Subclasses can override
void AccelStepper::step4(uint8_t step)
{
switch (step & 0x3)
{
case 0: // 1010
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, HIGH);
digitalWrite(_pin4, LOW);
break;
case 1: // 0110
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
digitalWrite(_pin3, HIGH);
digitalWrite(_pin4, LOW);
break;
case 2: //0101
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, HIGH);
break;
case 3: //1001
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, HIGH);
break;
}
}
// 4 pin step function
// This is passed the current step number (0 to 7)
// Subclasses can override
void AccelStepper::step8(uint8_t step)
{
switch (step & 0x7)
{
case 0: // 1000
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, LOW);
break;
case 1: // 1010
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, HIGH);
digitalWrite(_pin4, LOW);
break;
case 2: // 0010
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, HIGH);
digitalWrite(_pin4, LOW);
break;
case 3: // 0110
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
digitalWrite(_pin3, HIGH);
digitalWrite(_pin4, LOW);
break;
case 4: // 0100
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, LOW);
break;
case 5: //0101
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, HIGH);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, HIGH);
break;
case 6: // 0001
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, HIGH);
break;
case 7: //1001
digitalWrite(_pin1, HIGH);
digitalWrite(_pin2, LOW);
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, HIGH);
break;
}
}
// Prevents power consumption on the outputs
void AccelStepper::disableOutputs()
{
if (! _pins) return;
if (_pins == 1)
{
// Invert only applies for stepper drivers.
digitalWrite(_pin1, LOW ^ _stepInverted);
digitalWrite(_pin2, LOW ^ _dirInverted);
}
else
{
digitalWrite(_pin1, LOW);
digitalWrite(_pin2, LOW);
}
if (_pins == 4 || _pins == 8)
{
digitalWrite(_pin3, LOW);
digitalWrite(_pin4, LOW);
}
if (_enablePin != 0xff)
{
digitalWrite(_enablePin, LOW ^ _enableInverted);
}
}
void AccelStepper::enableOutputs()
{
if (! _pins)
return;
pinMode(_pin1, OUTPUT);
pinMode(_pin2, OUTPUT);
if (_pins == 4 || _pins == 8)
{
pinMode(_pin3, OUTPUT);
pinMode(_pin4, OUTPUT);
}
if (_enablePin != 0xff)
{
pinMode(_enablePin, OUTPUT);
digitalWrite(_enablePin, HIGH ^ _enableInverted);
}
}
void AccelStepper::setMinPulseWidth(unsigned int minWidth)
{
_minPulseWidth = minWidth;
}
void AccelStepper::setEnablePin(uint8_t enablePin)
{
_enablePin = enablePin;
// This happens after construction, so init pin now.
if (_enablePin != 0xff)
{
pinMode(_enablePin, OUTPUT);
digitalWrite(_enablePin, HIGH ^ _enableInverted);
}
}
void AccelStepper::setPinsInverted(bool direction, bool step, bool enable)
{
_dirInverted = direction;
_stepInverted = step;
_enableInverted = enable;
}
// Blocks until the target position is reached
void AccelStepper::runToPosition()
{
while (run())
;
}
boolean AccelStepper::runSpeedToPosition()
{
if (_targetPos >_currentPos)
_speed = fabs(_speed);
else
_speed = -fabs(_speed);
return _targetPos!=_currentPos ? runSpeed() : false;
}
// Blocks until the new target position is reached
void AccelStepper::runToNewPosition(long position)
{
moveTo(position);
runToPosition();
}
AccelStepper.h
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
// AccelStepper.h
//
/// \mainpage AccelStepper library for Arduino
///
/// This is the Arduino AccelStepper library.
/// It provides an object-oriented interface for 2 or 4 pin stepper motors.
///
/// The standard Arduino IDE includes the Stepper library
/// (http://arduino.cc/en/Reference/Stepper) for stepper motors. It is
/// perfectly adequate for simple, single motor applications.
///
/// AccelStepper significantly improves on the standard Arduino Stepper library in several ways:
/// \li Supports acceleration and deceleration
/// \li Supports multiple simultaneous steppers, with independent concurrent stepping on each stepper
/// \li API functions never delay() or block
/// \li Supports 2 and 4 wire steppers, plus 4 wire half steppers.
/// \li Supports alternate stepping functions to enable support of AFMotor (https://github.com/adafruit/Adafruit-Motor-Shield-library)
/// \li Supports stepper drivers such as the Sparkfun EasyDriver (based on 3967 driver chip)
/// \li Very slow speeds are supported
/// \li Extensive API
/// \li Subclass support
///
/// The latest version of this documentation can be downloaded from
/// http://www.open.com.au/mikem/arduino/AccelStepper
///
/// Example Arduino programs are included to show the main modes of use.
///
/// The version of the package that this documentation refers to can be downloaded
/// from http://www.open.com.au/mikem/arduino/AccelStepper/AccelStepper-1.18.zip
/// You can find the latest version at http://www.open.com.au/mikem/arduino/AccelStepper
///
/// You can also find online help and disussion at http://groups.google.com/group/accelstepper
/// Please use that group for all questions and discussions on this topic.
/// Do not contact the author directly, unless it is to discuss commercial licensing.
//
/// Tested on Arduino Diecimila and Mega with arduino-0018 & arduino-0021
/// on OpenSuSE 11.1 and avr-libc-1.6.1-1.15,
/// cross-avr-binutils-2.19-9.1, cross-avr-gcc-4.1.3_20080612-26.5.
///
/// \par Installation
/// Install in the usual way: unzip the distribution zip file to the libraries
/// sub-folder of your sketchbook.
///
/// This software is Copyright (C) 2010 Mike McCauley. Use is subject to license
/// conditions. The main licensing options available are GPL V2 or Commercial:
///
/// \par Open Source Licensing GPL V2
/// This is the appropriate option if you want to share the source code of your
/// application with everyone you distribute it to, and you also want to give them
/// the right to share who uses it. If you wish to use this software under Open
/// Source Licensing, you must contribute all your source code to the open source
/// community in accordance with the GPL Version 2 when your application is
/// distributed. See http://www.gnu.org/copyleft/gpl.html
///
/// \par Commercial Licensing
/// This is the appropriate option if you are creating proprietary applications
/// and you are not prepared to distribute and share the source code of your
/// application. Contact info@open.com.au for details.
///
/// \par Revision History
/// \version 1.0 Initial release
///
/// \version 1.1 Added speed() function to get the current speed.
/// \version 1.2 Added runSpeedToPosition() submitted by Gunnar Arndt.
/// \version 1.3 Added support for stepper drivers (ie with Step and Direction inputs) with _pins == 1
/// \version 1.4 Added functional contructor to support AFMotor, contributed by Limor, with example sketches.
/// \version 1.5 Improvements contributed by Peter Mousley: Use of microsecond steps and other speed improvements
/// to increase max stepping speed to about 4kHz. New option for user to set the min allowed pulse width.
/// Added checks for already running at max speed and skip further calcs if so.
/// \version 1.6 Fixed a problem with wrapping of microsecond stepping that could cause stepping to hang.
/// Reported by Sandy Noble.
/// Removed redundant _lastRunTime member.
/// \version 1.7 Fixed a bug where setCurrentPosition() did always work as expected. Reported by Peter Linhart.
/// Reported by Sandy Noble.
/// Removed redundant _lastRunTime member.
/// \version 1.8 Added support for 4 pin half-steppers, requested by Harvey Moon
/// \version 1.9 setCurrentPosition() now also sets motor speed to 0.
/// \version 1.10 Builds on Arduino 1.0
/// \version 1.11 Improvments from Michael Ellison:
/// Added optional enable line support for stepper drivers
/// Added inversion for step/direction/enable lines for stepper drivers
/// \version 1.12 Announce Google Group
/// \version 1.13 Improvements to speed calculation. Cost of calculation is now less in the worst case,
/// and more or less constant in all cases. This should result in slightly beter high speed performance, and
/// reduce anomalous speed glitches when other steppers are accelerating.
/// However, its hard to see how to replace the sqrt() required at the very first step from 0 speed.
/// \version 1.14 Fixed a problem with compiling under arduino 0021 reported by EmbeddedMan
/// \version 1.15 Fixed a problem with runSpeedToPosition which did not correctly handle
/// running backwards to a smaller target position. Added examples
/// \version 1.16 Fixed some cases in the code where abs() was used instead of fabs().
/// \version 1.17 Added example ProportionalControl
/// \version 1.18 Fixed a problem: If one calls the funcion runSpeed() when Speed is zero, it makes steps
/// without counting. reported by Friedrich, Klappenbach.
///
/// \author Mike McCauley (mikem@open.com.au)
// Copyright (C) 2009 Mike McCauley
// $Id: AccelStepper.h,v 1.6 2012/01/28 22:45:28 mikem Exp mikem $
#ifndef AccelStepper_h
#define AccelStepper_h
#include <stdlib.h>
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#include <wiring.h>
#endif
// These defs cause trouble on some versions of Arduino
#undef round
/////////////////////////////////////////////////////////////////////
/// \class AccelStepper AccelStepper.h <AccelStepper.h>
/// \brief Support for stepper motors with acceleration etc.
///
/// This defines a single 2 or 4 pin stepper motor, or stepper moter with fdriver chip, with optional
/// acceleration, deceleration, absolute positioning commands etc. Multiple
/// simultaneous steppers are supported, all moving
/// at different speeds and accelerations.
///
/// \par Operation
/// This module operates by computing a step time in microseconds. The step
/// time is recomputed after each step and after speed and acceleration
/// parameters are changed by the caller. The time of each step is recorded in
/// microseconds. The run() function steps the motor if a new step is due.
/// The run() function must be called frequently until the motor is in the
/// desired position, after which time run() will do nothing.
///
/// \par Positioning
/// Positions are specified by a signed long integer. At
/// construction time, the current position of the motor is consider to be 0. Positive
/// positions are clockwise from the initial position; negative positions are
/// anticlockwise. The curent position can be altered for instance after
/// initialization positioning.
///
/// \par Caveats
/// This is an open loop controller: If the motor stalls or is oversped,
/// AccelStepper will not have a correct
/// idea of where the motor really is (since there is no feedback of the motor's
/// real position. We only know where we _think_ it is, relative to the
/// initial starting point).
///
/// The fastest motor speed that can be reliably supported is 4000 steps per
/// second (4 kHz) at a clock frequency of 16 MHz. However, any speed less than that
/// down to very slow speeds (much less than one per second) are also supported,
/// provided the run() function is called frequently enough to step the motor
/// whenever required for the speed set.
class AccelStepper
{
public:
/// Constructor. You can have multiple simultaneous steppers, all moving
/// at different speeds and accelerations, provided you call their run()
/// functions at frequent enough intervals. Current Position is set to 0, target
/// position is set to 0. MaxSpeed and Acceleration default to 1.0.
/// The motor pins will be initialised to OUTPUT mode during the
/// constructor by a call to enableOutputs().
/// \param[in] pins Number of pins to interface to. 1, 2 or 4 are
/// supported. 1 means a stepper driver (with Step and Direction pins).
/// If an enable line is also needed, call setEnablePin() after construction.
/// You may also invert the pins using setPinsInverted().
/// 2 means a 2 wire stepper. 4 means a 4 wire stepper. 8 means a 4 wire half stepper
/// Defaults to 4 pins.
/// \param[in] pin1 Arduino digital pin number for motor pin 1. Defaults
/// to pin 2. For a driver (pins==1), this is the Step input to the driver. Low to high transition means to step)
/// \param[in] pin2 Arduino digital pin number for motor pin 2. Defaults
/// to pin 3. For a driver (pins==1), this is the Direction input the driver. High means forward.
/// \param[in] pin3 Arduino digital pin number for motor pin 3. Defaults
/// to pin 4.
/// \param[in] pin4 Arduino digital pin number for motor pin 4. Defaults
/// to pin 5.
AccelStepper(uint8_t pins = 4, uint8_t pin1 = 2, uint8_t pin2 = 3, uint8_t pin3 = 4, uint8_t pin4 = 5);
/// Alternate Constructor which will call your own functions for forward and backward steps.
/// You can have multiple simultaneous steppers, all moving
/// at different speeds and accelerations, provided you call their run()
/// functions at frequent enough intervals. Current Position is set to 0, target
/// position is set to 0. MaxSpeed and Acceleration default to 1.0.
/// Any motor initialization should happen before hand, no pins are used or initialized.
/// \param[in] forward void-returning procedure that will make a forward step
/// \param[in] backward void-returning procedure that will make a backward step
AccelStepper(void (*forward)(), void (*backward)());
/// Set the target position. The run() function will try to move the motor
/// from the current position to the target position set by the most
/// recent call to this function. Caution: moveTo() also recalculates the speed for the next step.
/// If you are trying to use constant speed movements, you should call setSpeed() after calling moveTo().
/// \param[in] absolute The desired absolute position. Negative is
/// anticlockwise from the 0 position.
void moveTo(long absolute);
/// Set the target position relative to the current position
/// \param[in] relative The desired position relative to the current position. Negative is
/// anticlockwise from the current position.
void move(long relative);
/// Poll the motor and step it if a step is due, implementing
/// accelerations and decelerations to acheive the target position. You must call this as
/// frequently as possible, but at least once per minimum step interval,
/// preferably in your main loop.
/// \return true if the motor is at the target position.
boolean run();
/// Poll the motor and step it if a step is due, implmenting a constant
/// speed as set by the most recent call to setSpeed(). You must call this as
/// frequently as possible, but at least once per step interval,
/// \return true if the motor was stepped.
boolean runSpeed();
/// Sets the maximum permitted speed. the run() function will accelerate
/// up to the speed set by this function.
/// \param[in] speed The desired maximum speed in steps per second. Must
/// be > 0. Speeds of more than 1000 steps per second are unreliable.
void setMaxSpeed(float speed);
/// Sets the acceleration and deceleration parameter.
/// \param[in] acceleration The desired acceleration in steps per second
/// per second. Must be > 0.
void setAcceleration(float acceleration);
/// Sets the desired constant speed for use with runSpeed().
/// \param[in] speed The desired constant speed in steps per
/// second. Positive is clockwise. Speeds of more than 1000 steps per
/// second are unreliable. Very slow speeds may be set (eg 0.00027777 for
/// once per hour, approximately. Speed accuracy depends on the Arduino
/// crystal. Jitter depends on how frequently you call the runSpeed() function.
void setSpeed(float speed);
/// The most recently set speed
/// \return the most recent speed in steps per second
float speed();
/// The distance from the current position to the target position.
/// \return the distance from the current position to the target position
/// in steps. Positive is clockwise from the current position.
long distanceToGo();
/// The most recently set target position.
/// \return the target position
/// in steps. Positive is clockwise from the 0 position.
long targetPosition();
/// The currently motor position.
/// \return the current motor position
/// in steps. Positive is clockwise from the 0 position.
long currentPosition();
/// Resets the current position of the motor, so that wherever the motor
/// happens to be right now is considered to be the new 0 position. Useful
/// for setting a zero position on a stepper after an initial hardware
/// positioning move.
/// Has the side effect of setting the current motor speed to 0.
/// \param[in] position The position in steps of wherever the motor
/// happens to be right now.
void setCurrentPosition(long position);
/// Moves the motor at the currently selected constant speed (forward or reverse)
/// to the target position and blocks until it is at
/// position. Dont use this in event loops, since it blocks.
void runToPosition();
/// Runs at the currently selected speed until the target position is reached
/// Does not implement accelerations.
/// \return true if it stepped
boolean runSpeedToPosition();
/// Moves the motor to the new target position and blocks until it is at
/// position. Dont use this in event loops, since it blocks.
/// \param[in] position The new target position.
void runToNewPosition(long position);
/// Disable motor pin outputs by setting them all LOW
/// Depending on the design of your electronics this may turn off
/// the power to the motor coils, saving power.
/// This is useful to support Arduino low power modes: disable the outputs
/// during sleep and then reenable with enableOutputs() before stepping
/// again.
void disableOutputs();
/// Enable motor pin outputs by setting the motor pins to OUTPUT
/// mode. Called automatically by the constructor.
void enableOutputs();
/// Sets the minimum pulse width allowed by the stepper driver.
/// \param[in] minWidth The minimum pulse width in microseconds.
void setMinPulseWidth(unsigned int minWidth);
/// Sets the enable pin number for stepper drivers.
/// 0xFF indicates unused (default).
/// Otherwise, if a pin is set, the pin will be turned on when
/// enableOutputs() is called and switched off when disableOutputs()
/// is called.
/// \param[in] enablePin Arduino digital pin number for motor enable
/// \sa setPinsInverted
void setEnablePin(uint8_t enablePin = 0xff);
/// Sets the inversion for stepper driver pins
/// \param[in] direction True for inverted direction pin, false for non-inverted
/// \param[in] step True for inverted step pin, false for non-inverted
/// \param[in] enable True for inverted enable pin, false (default) for non-inverted
void setPinsInverted(bool direction, bool step, bool enable = false);
protected:
/// Forces the library to compute a new instantaneous speed and set that as
/// the current speed. Calls
/// desiredSpeed(), which can be overridden by subclasses. It is called by
/// the library:
/// \li after each step
/// \li after change to maxSpeed through setMaxSpeed()
/// \li after change to acceleration through setAcceleration()
/// \li after change to target position (relative or absolute) through
/// move() or moveTo()
void computeNewSpeed();
/// Called to execute a step. Only called when a new step is
/// required. Subclasses may override to implement new stepping
/// interfaces. The default calls step1(), step2(), step4() or step8() depending on the
/// number of pins defined for the stepper.
/// \param[in] step The current step phase number (0 to 7)
virtual void step(uint8_t step);
/// Called to execute a step using stepper functions (pins = 0) Only called when a new step is
/// required. Calls _forward() or _backward() to perform the step
virtual void step0(void);
/// Called to execute a step on a stepper drover (ie where pins == 1). Only called when a new step is
/// required. Subclasses may override to implement new stepping
/// interfaces. The default sets or clears the outputs of Step pin1 to step,
/// and sets the output of _pin2 to the desired direction. The Step pin (_pin1) is pulsed for 1 microsecond
/// which is the minimum STEP pulse width for the 3967 driver.
/// \param[in] step The current step phase number (0 to 7)
virtual void step1(uint8_t step);
/// Called to execute a step on a 2 pin motor. Only called when a new step is
/// required. Subclasses may override to implement new stepping
/// interfaces. The default sets or clears the outputs of pin1 and pin2
/// \param[in] step The current step phase number (0 to 7)
virtual void step2(uint8_t step);
/// Called to execute a step on a 4 pin motor. Only called when a new step is
/// required. Subclasses may override to implement new stepping
/// interfaces. The default sets or clears the outputs of pin1, pin2,
/// pin3, pin4.
/// \param[in] step The current step phase number (0 to 7)
virtual void step4(uint8_t step);
/// Called to execute a step on a 4 pin half-steper motor. Only called when a new step is
/// required. Subclasses may override to implement new stepping
/// interfaces. The default sets or clears the outputs of pin1, pin2,
/// pin3, pin4.
/// \param[in] step The current step phase number (0 to 7)
virtual void step8(uint8_t step);
/// Compute and return the desired speed. The default algorithm uses
/// maxSpeed, acceleration and the current speed to set a new speed to
/// move the motor from teh current position to the target
/// position. Subclasses may override this to provide an alternate
/// algorithm (but do not block). Called by computeNewSpeed whenever a new speed neds to be
/// computed.
virtual float desiredSpeed();
private:
/// Number of pins on the stepper motor. Permits 2 or 4. 2 pins is a
/// bipolar, and 4 pins is a unipolar.
uint8_t _pins; // 2 or 4
/// Arduino pin number for the 2 or 4 pins required to interface to the
/// stepper motor.
uint8_t _pin1, _pin2, _pin3, _pin4;
/// The current absolution position in steps.
long _currentPos; // Steps
/// The target position in steps. The AccelStepper library will move the
/// motor from the _currentPos to the _targetPos, taking into account the
/// max speed, acceleration and deceleration
long _targetPos; // Steps
/// The current motos speed in steps per second
/// Positive is clockwise
float _speed; // Steps per second
/// The maximum permitted speed in steps per second. Must be > 0.
float _maxSpeed;
/// The acceleration to use to accelerate or decelerate the motor in steps
/// per second per second. Must be > 0
float _acceleration;
/// The current interval between steps in microseconds
unsigned long _stepInterval;
/// The last step time in microseconds
unsigned long _lastStepTime;
/// The minimum allowed pulse width in microseconds
unsigned int _minPulseWidth;
/// Is the direction pin inverted?
bool _dirInverted;
/// Is the step pin inverted?
bool _stepInverted;
/// Is the enable pin inverted?
bool _enableInverted;
/// Enable pin for stepper driver, or 0xFF if unused.
uint8_t _enablePin;
/// The pointer to a forward-step procedure
void (*_forward)();
/// The pointer to a backward-step procedure
void (*_backward)();
};
/// @example Random.pde
/// Make a single stepper perform random changes in speed, position and acceleration
/// @example Overshoot.pde
/// Check overshoot handling
/// which sets a new target position and then waits until the stepper has
/// achieved it. This is used for testing the handling of overshoots
/// @example MultiStepper.pde
/// Shows how to multiple simultaneous steppers
/// Runs one stepper forwards and backwards, accelerating and decelerating
/// at the limits. Runs other steppers at the same time
/// @example ConstantSpeed.pde
/// Shows how to run AccelStepper in the simplest,
/// fixed speed mode with no accelerations
/// @example Blocking.pde
/// Shows how to use the blocking call runToNewPosition
/// Which sets a new target position and then waits until the stepper has
/// achieved it.
/// @example AFMotor_MultiStepper.pde
/// Control both Stepper motors at the same time with different speeds
/// and accelerations.
/// @example AFMotor_ConstantSpeed.pde
/// Shows how to run AccelStepper in the simplest,
/// fixed speed mode with no accelerations
/// @example ProportionalControl.pde
/// Make a single stepper follow the analog value read from a pot or whatever
/// The stepper will move at a constant speed to each newly set posiiton,
/// depending on the value of the pot.
#endif
LICENSE
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This software is Copyright (C) 2008 Mike McCauley. Use is subject to license
conditions. The main licensing options available are GPL V2 or Commercial:
Open Source Licensing GPL V2
This is the appropriate option if you want to share the source code of your
application with everyone you distribute it to, and you also want to give them
the right to share who uses it. If you wish to use this software under Open
Source Licensing, you must contribute all your source code to the open source
community in accordance with the GPL Version 2 when your application is
distributed. See http://www.gnu.org/copyleft/gpl.html
Commercial Licensing
This is the appropriate option if you are creating proprietary applications
and you are not prepared to distribute and share the source code of your
application. Contact info@open.com.au for details.
keywords.txt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#######################################
# Syntax Coloring Map For AccelStepper
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
AccelStepper KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
moveTo KEYWORD2
move KEYWORD2
run KEYWORD2
runSpeed KEYWORD2
setMaxSpeed KEYWORD2
setAcceleration KEYWORD2
setSpeed KEYWORD2
speed KEYWORD2
distanceToGo KEYWORD2
targetPosition KEYWORD2
currentPosition KEYWORD2
steCurrentPosition KEYWORD2
runToPosition KEYWORD2
runSpeedToPosition KEYWORD2
runToNewPosition KEYWORD2
disableOutputs KEYWORD2
enableOutputs KEYWORD2
setMinPulseWidth KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
License.txt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
MIT License
Copyright (c) 2010 bildr community
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
README.md
AccelStepper
Arduino code for the Easy Driver step motor controller
For complete hookup and tutorial see: http://adam-meyer.com/arduino/big_easy
The code is provided under the MIT license please use, edit, change, and share.
Before loading any of the examples, or even opening the arduino software, place the AccelStepper folder in your arduino library.
ARDUINO LIBRARY LOCATION
- On your Mac:: In (home directory)/Documents/Arduino/libraries
- On your PC:: My Documents -> Arduino -> libraries
- On your Linux box: (home directory)/sketchbook/libraries
For all my arduino articles: http://adam-meyer.com/arduino/
one_stepper_example.ino
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//This is an example of how you would control 1 stepper
#include <AccelStepper.h>
int motorSpeed = 9600; //maximum steps per second (about 3rps / at 16 microsteps)
int motorAccel = 80000; //steps/second/second to accelerate
int motorDirPin = 2; //digital pin 2
int motorStepPin = 3; //digital pin 3
//set up the accelStepper intance
//the "1" tells it we are using a driver
AccelStepper stepper(1, motorStepPin, motorDirPin);
void setup(){
stepper.setMaxSpeed(motorSpeed);
stepper.setSpeed(motorSpeed);
stepper.setAcceleration(motorAccel);
stepper.moveTo(32000); //move 32000 steps (should be 10 rev)
}
void loop(){
//if stepper is at desired location
if (stepper.distanceToGo() == 0){
//go the other way the same amount of steps
//so if current position is 400 steps out, go position -400
stepper.moveTo(-stepper.currentPosition());
}
//these must be called as often as possible to ensure smooth operation
//any delay will cause jerky motion
stepper.run();
}
two_steppers.ino
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//This is an example of how you would control 2 steppers at the same time
#include <AccelStepper.h>
int motorSpeed = 9600; //maximum steps per second (about 3rps / at 16 microsteps)
int motorAccel = 80000; //steps/second/second to accelerate
int motor1DirPin = 2; //digital pin 2
int motor1StepPin = 3; //digital pin 3
int motor2DirPin = 4; //digital pin 4
int motor2StepPin = 5; //digital pin 5
//set up the accelStepper intances
//the "1" tells it we are using a driver
AccelStepper stepper1(1, motor1StepPin, motor1DirPin);
AccelStepper stepper2(1, motor2StepPin, motor2DirPin);
void setup(){
stepper1.setMaxSpeed(motorSpeed);
stepper2.setMaxSpeed(motorSpeed);
stepper1.setSpeed(motorSpeed);
stepper2.setSpeed(motorSpeed);
stepper1.setAcceleration(motorAccel);
stepper2.setAcceleration(motorAccel);
stepper1.moveTo(32000); //move 32000 steps (should be 10 rev)
stepper2.moveTo(15000); //move 15000 steps
}
void loop(){
//if stepper1 is at desired location
if (stepper1.distanceToGo() == 0){
//go the other way the same amount of steps
//so if current position is 400 steps out, go position -400
stepper1.moveTo(-stepper1.currentPosition());
}
//if stepper2 is at desired location
if (stepper2.distanceToGo() == 0){
//go the other way the same amount of steps
//so if current position is 400 steps out, go position -400
stepper2.moveTo(-stepper2.currentPosition());
}
//these must be called as often as possible to ensure smooth operation
//any delay will cause jerky motion
stepper1.run();
stepper2.run();
}
Additional Information
Finding Your Motors Coil Pairs
This driver only needs 4 wires from your stepper. If you have a 4 wire stepper, awesome! If you have a 6 wire stepper, it will be slightly trickier. But no matter what, we need to find the 2 main coils inside of the motor. And if you get it wrong, the motor will just twitch or not move, but you wont break it.
4 wire motor
Using an ohmMeter, pick one wire at random, and test it with the others until you find a pair that shows resistance of a few ohms (1 - 200ohms most often). Those 2 are your "pair A". Make sure the other 2 wires have the same resistance on them, (if not, it may be broken) and that is your "pair B". With the two pairs of wires, there isnt a backwards, so just plug wires from "pair A" into the "A" on the driver, and "pair B" into "B".
6 wire motor
Checking the documents on the motor is the easiest, but if you dont have it, read on.
6 wire motors have two coils in them just like 4 wire motors. But 6 wire motors also have extra wires that connects to the middle of each coil (centers). So each coil actually has 3 wires, a center and two ends. We don't use coil center wires, we just need the 4 coil ends (2 from each coil).
Basically, We need to find ends of the two coils. The ends of the coils will have twice the resistance as the center to an end. So we need two pairs of wire that have the highest resistance in the group.
The easiest way to find out the right 4 wires is to look at the documentation for the motor, but if you dont have that, you can with some testing, find the right ones.
To find the correct 2 wires, we need to locate the 3 wires from each coil. Start by just picking one at random, and using an ohmMeter, test the resistance with the others until you find the 2 connected to that wire. (3 of them will show no connection because they are part of the other coil). Now, these 3 are for coil "A". Now, take these 3 wires and test the resistance between any 2 of them until find the 2 that have the highest resistance. These are the two ends of that coil "A". Do the same for the other 3 wires to locate the ends of coil "B".
With the two pairs of wires, there isnt a backwards. So just plug wires from coil A into the A on the driver, and the two from coil B into b.
8 wire motor
There is no way to do this without looking at the documentation.
Microstepping
Most stepper drivers offer something called microstepping, and the Big Easy Driver is no exception. As I mentioned before, steppers have that minimum movement called a step. Microstepping breaks down that step into smaller micro steps. Microstepping allows for smoother, quieter, more accurate control, at slower speeds.
When using microstepping, a step motor will require more "step pluses" to move the motor. For instance if you are using 16 microsteps (the default on the Big Easy Driver) per step, a 200 step motor would require 3200 "step pluses" to make a full revolution. Just take note when you wonder why telling it to step 200 steps barely rotates the motor.
Microstepping will reduce the maximum speed / torque of the motor (about 30% less), so it is a trade of speed vs smooth. Because of this, many high end drivers switch to full stepping (no microstepping) at higher speeds, and technically, you could do that with the big easyDriver, but it's too complex for me to figure out, so I wont be covering that.
Article taken from bildr.org with minor changes - I am the original author of this content