4.4. Exercise: G-Code Stepper Motor Motion

A stepper motor provides precise open-loop motion control at reasonable cost. These motors are the actuator of choice for many low-cost 3D printers, desktop CNC mills, inkjet printers, and small robots. For our purposes, stepper motors generally provide a ‘machine-like’ quality of movement: precise, repeatable, and with a recognizable acoustic signature. This can be modified somewhat by the dynamics of the driven mechanism, but the typical application will invoke machine precision.

A stepper motor uses a toothed rotor and multiple drive coils to create motion in discrete steps. The fundamental angular size of the steps is determined by the physical spacing of the internal magnetic teeth. Stepper motors are open-loop since there is no sensor involved in controlling position. The driver simply cycles the coil currents and assumes the motor moves synchronously. If the motor encounters too high a torque, the magnetic forces can be overcome and the rotor will slip to a different position. The microcontroller has no means of detecting this error.

This exercise uses a stepper motor driver module which takes care of cycling the currents appropriately through the two coils of a bipolar stepper motor. The primary inputs to the driver are direction and step. Each pulse on step moves the motor one unit in the direction specified by the direction input. The additional inputs control the unit subdivision of the physical steps (fractional stepping) and the overall driver power state.

With careful mechanical design, stepper motors can reliably move sophisticated mechanisms. With the addition of sensing and low-latency control computation, they can even function as output actuators for feedback-controlled closed-loop systems.

Steppers can produce complex expressive movement purely through open-loop actuation and software. The quickest way for us to get started is to use the grbl firmware for Arduino CNC motion and program the system by issuing G-code commands to it. This has the secondary benefit of teaching basic G-code programming for use with the CNC router.

This firmware is typically used to run a fixed part-cutting program in CNC applications, but it is possible to feed G-code commands in real time to build a system with dynamic behavior. The latency can be limited to the duration of single movements so with care the resulting effect can be quite responsive by stringing together many short movements.

4.4.1. Objectives

Interactively operate a stepper motor system, learn a few basic G-code commands, and choreograph a simple movement sequence.

4.4.2. Materials

  1. An Arduino Uno or equivalent.
  2. A Protoneer CNC shield (or equivalent breadboard wiring).
  3. One to three A4988 Stepper Motor Drivers.
  4. One stepper motor: I recommend the Automation Technology KL17H248-15-4A NEMA17 motors we have in the lab.
  5. A 12V power supply.
  6. A computer on which to run a terminal emulator.
  7. A digital multimeter for checking the driver current limits.

4.4.3. Getting Started

  1. Please make sure that your CNC driver package is assembled as per the description in the CNC Arduino Shield section.
  2. Please verify that the X-axis driver current limit is set for your chosen stepper motor as described in the Current Limiting section.
  3. Please attach the stepper motor to the X axis driver (upper left position).
  4. Check that the firmware is installed:
    1. connect your Arduino to a computer
    2. start the Arduino IDE, choose the correct Arduino type and port
    3. open the Serial Monitor, set to 115000 baud
    4. look for the grbl startup banner
  5. If it is a fresh Arduino or not running grbl, please install grbl on your Arduino as described in the grbl firmware for Arduino CNC motion section.

4.4.4. Experiments Command Line Interaction

The easiest way to try out movements is to use a terminal program as a text console. Three options should be available on the IDeATe cluster Macs: you may use the Serial Monitor built into the Arduino IDE, the venerable curses-based minicom, or the GUI-based CoolTerm.

Whichever you choose, determine on which port your Arduino is enumerating, then configure the terminal emulator to use that port at 115200 baud, 8 bits, no parity, one stop bit. If you use the Arduino IDE, be sure that the ‘line ending’ dropdown is set to Newline or Carriage Return.

When you connect with the terminal emulator, the Arduino should reset and then show the grbl prompt:

Grbl 0.9j ['$' for help]

Entering $ will show a short list of commands. Entering $$ will show a long list of parameters. Typing a single ? without a return will show a status readout including the current position of all axes:


After you succeed in seeing the grbl prompt, apply the 12V motor power and issue the following motion command:

G91 G0 X100

You should observe the stepper motor accelerate smoothly to a constant rotation rate, spin for a few seconds, then decelerate. Detailed G-code references are linked from the grbl resource page, but a quick explanation follows:

G91 set incremental distance mode
G0 rapid positioning command
X100 movement distance along X axis

To move back to the start, you can issue another G0 command:

G0 X-100

Since the G0 command is modal, this could also be accomplished simply by issuing another axis word:


Note that each command fully completes before the next begins, even though grbl may let you type ahead. Try entering two movements in quick succession:

X50 Calibration and Scaling

An inspection of the default machine parameters will explain exactly how far and fast the G0 X100 command is supposed to move. If you enter $$ you will see the following values among the parameters:

$100=250.000 (x, step/mm)
$110=500.000 (x max rate, mm/min)
$120=10.000 (x accel, mm/sec^2)

grbl defaults to interpreting coordinates in millimeters; this may also be explicitly set with a G21 command. With these parameters, G91 G0 X100 represents a 100 mm move at the maximum speed of 500 mm/min, with an initial and final acceleration of 10 mm/sec^2.

The $100=250.000 parameter shows an assumption of 250 steps/mm; in actuality, the physical scaling depends upon the specific stepper motor geometry and whether the A4988 has microstepping enabled. The A4988 is a microstepping driver which can accept multiple control pulses for each physical motor step. Assuming the A4988 is set to the finest 16 microsteps/step jumper configuration, and you are using a typical 200 step/rotation stepper motor, this leads to the following distance and speed calculation for G0 X100:

100 mm * (250 microsteps/mm) * (1 motor step/16 microsteps) * (1 revolution / 200 motor steps) = 7.8125 rotations
500 mm/min * (250 microsteps/mm) * (1 motor step/16 microsteps) * (1 revolution / 200 motor steps) = 39.0625 rev / min

Note that the default parameters are conservatively slow for our unloaded stepper motors, but can be changed and stored in the Arduino non-volatile memory. For example, the maximum speed at which grbl can emit stepping pulses is 30 kHz, so the maximum possible speed with the default configuration is as follows:

(30000 microsteps/second) / (250 microsteps/mm) = 120 mm/sec
(120 mm/sec) * (60 seconds/min) = 7200 mm/min

So parameter $110 could be set to 7200 for the X axis motor to operate at the maximum possible speed as follows:


The default grbl configuration turns off the motor drivers whenever the program is done, which can be inconvenient if you are expecting the motors to hold something in position when idle. If it makes more sense to keep all axes always enabled, you may set the ‘step idle delay’ as follows:

$1=255 Streaming

For CNC machining, grbl is operated by continuously streaming a G-code program to it. We can take advantage of these same streaming tools to create simple motion choreography.

The grbl package includes two simple Python scripts for sending a file of G-code blocks to the driver, located in the script folder. These scripts require the optional pySerial package which should already be installed on the IDeATe cluster Macs; on these laptops, the specific python version /opt/local/bin/python2.7 includes the pySerial module.

Prepare a simple G-code file to start; these conventionally have the file extension .nc. These are plain ASCII text files and should be edited with a text editor. (If you use the Apple TextEdit app, be sure to apply Format/Make Plain Text.) Here is a sample to start:

G21 G91 G94
G0 X10

First identify the enumerated name of your Arduino (e.g. similar to /dev/tty.usbmodem1411 on a Mac, or COM4: on Windows). Then from the command line, navigate to the script folder:

cd Arduino/grbl/doc/script/

And issue a command of the following form, substituting the name of your G-code file for sample.nc, and your particular serial port name:

/opt/local/bin/python2.7 stream.py sample.nc /dev/tty.usbmodem1411

The command is written specifically for the IDeATe cluster Mac with MacPorts. The standard Apple python /usr/bin/python does not include the pySerial module.

If all goes well, you should see output similar to the following:

Initializing grbl...
SND: 1 : G21 G91 G94 BUF: 12 REC:
SND: 2 : G0 X10 BUF: 19 REC:
SND: 3 : X-10 BUF: 24 REC:
SND: 4 : X20 BUF: 28 REC:
SND: 5 : X-20 BUF: 33 REC:
SND: 6 :  BUF: 34 REC:
G-code streaming finished!

WARNING: Wait until grbl completes buffered g-code blocks before exiting.
  Press <Enter> to exit and disable grbl. Choreography

For the final stage of this exercise, create a tiny single-axis performance. Attach a simple puppet to the motor shaft, then write a motion sequence to animate it. Be sure to record a brief video of your results.

Your puppet may be as simple as a paper cutout taped onto the shaft, a found object, or anything which can show some movement and provide a rationale for your animation.

You may use any G-code features you like. Further references can be found on the grbl resource page. In particular, you may wish to issue G1 linear move commands which include a feed rate to set speed. In this example, the F100 word specifies a speed in the current units per minute (the power-on default is mm/minute):

G1 X50 F100

For animations, a programmed pause (G4, “dwell”) may be useful. For example, the block G4 P1.0 specifies a 1.0 second delay.

You may prefer to operate in absolute coordinates using G90 rather than the incremental displacement. And if you using two motors, multiple axes may be specified by including additional coordinate words as follows:

G0 X50 Y50

That also may lead to experimentation with circular interpolation modes G2 and G3.

4.4.5. Deliverables

Please prepare a short video documenting your performance. Please limit to no more than two minutes duration; one minute is ideal. All videos should be uploaded to an online server and submitted as a URL. If working in a pair, please include both student names and the URL in a single email to the instructor.