StepperScript Arduino Sketch

This Arduino sketch provides the simplest example of driving three stepper motors through a fixed motion script. It uses the AccelStepper library to manage stepper driver signal generation. It is configured to use the pin assignments of the CNC Arduino Shield.

The AccelStepper library can be installed from within the Arduino IDE by opening the Library Manager via the Sketch/Include Library/Manage Libraries... menu option.

Top-Level Functions

void setup(void)

Configure the hardware once after booting up. This runs once after powering up the board, pressing reset, or connecting to the console serial port.

void poll_steppers(void)

Call the run() function for each stepper driver object, which will recalculate speeds and generate step pulses as needed.

bool is_moving(void)

Return true if any one of the drivers are still moving.

void move(long x, long y, long z, long a)

Move a relative displacement at the current speed, blocking until the move is done.

void loop()

Run one iteration of the main loop. The Arduino system will call this function over and over forever. This implementation is a script which will generate a series of movements, waiting for each to complete.

Main Source Code

The main top-level code is in StepperScript.ino.

  1
  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
// StepperScript - drive three or four stepper motors through a sequence of poses
//
// Written in 2018 by Garth Zeglin <garthz@cmu.edu>.  To the extent possible
// under law, the author has dedicated all copyright and related and neighboring
// rights to this software to the public domain worldwide.  This software is
// distributed without any warranty.  You should have received a copy of the CC0
// Public Domain Dedication along with this software.  If not, see
// <http://creativecommons.org/publicdomain/zero/1.0/>.

// This program assumes that:

//  1. three or four A4988 stepper motor drivers are connected following the CNC Shield pin conventions.
//  2. the AccelStepper library is installed
//  3. if the fourth A axis stepper is used, jumpers are installed to connect
//     A-DIR to D13 (also SpinDir) and A-STEP to D12 (also SpinEnable).

// ================================================================================
// Output pin assignments to control the A4988 stepper motor drivers.  The step
// inputs are triggered on a rising edge, with a minimum 1 microsecond HIGH and
// LOW pulse widths.
#define X_AXIS_STEP_PIN 2
#define Y_AXIS_STEP_PIN 3
#define Z_AXIS_STEP_PIN 4
#define A_AXIS_STEP_PIN 12     // requires an optional jumper

#define X_AXIS_DIR_PIN 5
#define Y_AXIS_DIR_PIN 6
#define Z_AXIS_DIR_PIN 7
#define A_AXIS_DIR_PIN 13      // requires an optional jumper

#define STEPPER_ENABLE_PIN 8  // active-low (i.e. LOW turns on the drivers)

// ================================================================================
// Import the third-party AccelStepper library.
#include <AccelStepper.h>

// Declare three AccelStepper objects to manage the output timing.
AccelStepper xaxis(AccelStepper::DRIVER, X_AXIS_STEP_PIN, X_AXIS_DIR_PIN);
AccelStepper yaxis(AccelStepper::DRIVER, Y_AXIS_STEP_PIN, Y_AXIS_DIR_PIN);
AccelStepper zaxis(AccelStepper::DRIVER, Z_AXIS_STEP_PIN, Z_AXIS_DIR_PIN);
AccelStepper aaxis(AccelStepper::DRIVER, A_AXIS_STEP_PIN, A_AXIS_DIR_PIN);

// ================================================================================
/// Configure the hardware once after booting up.  This runs once after powering
/// up the board, pressing reset, or connecting to the console serial port.
void setup(void)
{
  // set up the CNC Shield I/O
  digitalWrite(STEPPER_ENABLE_PIN, HIGH); // initialize drivers in disabled state
  pinMode(STEPPER_ENABLE_PIN, OUTPUT);

  xaxis.setMaxSpeed(4000.0);
  xaxis.setAcceleration(8000.0);

  yaxis.setMaxSpeed(4000.0);
  yaxis.setAcceleration(8000.0);

  zaxis.setMaxSpeed(4000.0);
  zaxis.setAcceleration(8000.0);

  aaxis.setMaxSpeed(4000.0);
  aaxis.setAcceleration(8000.0);

  // set up the serial port for debugging output
  Serial.begin(115200);

  // enable the drivers, the motors will remain constantly energized
  digitalWrite(STEPPER_ENABLE_PIN, LOW);
}
/****************************************************************/
/// Call the ``run()`` function for each stepper driver object, which will
/// recalculate speeds and generate step pulses as needed.
void poll_steppers(void)

{
  xaxis.run();
  yaxis.run();
  zaxis.run();
  aaxis.run();
}
/// Return true if any one of the drivers are still moving.
bool is_moving(void)
{
  return (xaxis.isRunning() || yaxis.isRunning() || zaxis.isRunning() || aaxis.isRunning());
}

/// Move a relative displacement at the current speed, blocking until the move is done.
void move(long x, long y, long z, long a)
{
  Serial.print("Moving to ");
  Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(z); Serial.print(", ");
  Serial.println(a);
  
  xaxis.move(x);
  yaxis.move(y);
  zaxis.move(z);
  aaxis.move(a);

  do {
    poll_steppers();
  } while(is_moving());
}

/****************************************************************/
/// Run one iteration of the main loop.  The Arduino system will call this
/// function over and over forever.  This implementation is a script which will
/// generate a series of movements, waiting for each to complete.
void loop()
{
  Serial.println("Starting the movement script.");
  move(200, 200, 200, 200);
  delay(500);

  Serial.println("Returning to home axis by axis.");
  move(-200, 0, 0, 0);
  delay(500);

  move(0, -200, 0, 0);
  delay(500);

  move(0, 0, -200, 0);
  delay(500);

  move(0, 0, 0, -200);
  delay(500);
}
/****************************************************************/