Built-in project · Arduino Uno R3

Two steppers on a CNC shield, on an Arduino Uno

A CNC shield v3 with A4988 drivers on an Uno: the X and Y NEMA 17s turn a quarter turn each way, stepped on pins 2 and 3, turned on 5 and 6, enabled by pin 8. The whole build, an Arduino Uno and 4 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 20 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $63. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • STEP and DIR signals for a stepper driver
  • Microstepping and steps per turn
  • An enable pin that is active low
  • Separate motor power from logic power
  • Difficulty: Intermediate
  • Time: About 20 minutes
  • Board: Arduino Uno R3
  • Parts: 5

How it works

A CNC shield v3 sits on the Uno with A4988 stepper drivers. Each driver turns two signals into motor moves: a pulse on STEP moves the motor one microstep, and the level on DIR picks the direction. The X driver uses pins 2 and 5, the Y driver pins 3 and 6.

The motor power comes from a separate DC source on VM+ and VM-. The shield holds pin 8 high, which keeps the drivers off, so the sketch drives pin 8 low to enable them.

The jumpers set 1/16 microstepping, so a full turn is 3200 steps. The loop turns both NEMA 17 motors a quarter turn, with X and Y going opposite ways, pauses, and then reverses.

Parts list

5 parts, plus the jumper wires. They retail for about $63; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
CNC shield v3 with A4988s pin D8Arduino Uno R3 pin 8
CNC shield v3 with A4988s pin D6Arduino Uno R3 pin 6
CNC shield v3 with A4988s pin D5Arduino Uno R3 pin 5
CNC shield v3 with A4988s pin D3Arduino Uno R3 pin 3
CNC shield v3 with A4988s pin D2Arduino Uno R3 pin 2
CNC shield v3 with A4988s pin 5VArduino Uno R3 pin 5V
CNC shield v3 with A4988s pin GNDArduino Uno R3 pin GND
DC voltage source pin V+CNC shield v3 with A4988s pin VM+
DC voltage source pin V-CNC shield v3 with A4988s pin VM-
Stepper motor, NEMA 17 (1) pin B2CNC shield v3 with A4988s pin X2B
Stepper motor, NEMA 17 (1) pin B1CNC shield v3 with A4988s pin X2A
Stepper motor, NEMA 17 (1) pin A1CNC shield v3 with A4988s pin X1A
Stepper motor, NEMA 17 (1) pin A2CNC shield v3 with A4988s pin X1B
Stepper motor, NEMA 17 (2) pin B2CNC shield v3 with A4988s pin Y2B
Stepper motor, NEMA 17 (2) pin B1CNC shield v3 with A4988s pin Y2A
Stepper motor, NEMA 17 (2) pin A1CNC shield v3 with A4988s pin Y1A
Stepper motor, NEMA 17 (2) pin A2CNC shield v3 with A4988s pin Y1B

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Two stepper motors on the CNC shield v3, X and Y.
//
//   X: STEP 2, DIR 5     Y: STEP 3, DIR 6     enable (all drivers): 8, LOW = on
//
// The shield pulls pin 8 high, so the drivers stay off until the sketch
// drives it low. Its jumpers set 1/16 microstepping: 3200 steps a turn.

const uint8_t X_STEP = 2, Y_STEP = 3, X_DIR = 5, Y_DIR = 6, ENABLE = 8;
const int STEPS_PER_TURN = 3200;

void steps(int count, unsigned int us) {
  for (int i = 0; i < count; i++) {
    digitalWrite(X_STEP, HIGH);
    digitalWrite(Y_STEP, HIGH);
    delayMicroseconds(5);
    digitalWrite(X_STEP, LOW);
    digitalWrite(Y_STEP, LOW);
    delayMicroseconds(us);
  }
}

void setup() {
  pinMode(X_STEP, OUTPUT);
  pinMode(Y_STEP, OUTPUT);
  pinMode(X_DIR, OUTPUT);
  pinMode(Y_DIR, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  digitalWrite(ENABLE, LOW);
}

void loop() {
  // A quarter turn one way, X and Y opposite...
  digitalWrite(X_DIR, HIGH);
  digitalWrite(Y_DIR, LOW);
  steps(STEPS_PER_TURN / 4, 300);
  delay(300);
  // ...and back.
  digitalWrite(X_DIR, LOW);
  digitalWrite(Y_DIR, HIGH);
  steps(STEPS_PER_TURN / 4, 300);
  delay(300);
}

Code walkthrough

The key functions of the sketch, and what each one does.

steps sketch.ino

Sends count pulses to both STEP pins at once. Each pulse is high for 5 microseconds, then low for us microseconds. A longer us means slower motors. Both motors move together because both pins are switched in the same loop.

void steps(int count, unsigned int us) {
  for (int i = 0; i < count; i++) {
    digitalWrite(X_STEP, HIGH);
    digitalWrite(Y_STEP, HIGH);
    delayMicroseconds(5);
    digitalWrite(X_STEP, LOW);
    digitalWrite(Y_STEP, LOW);
    delayMicroseconds(us);
  }
}

setup sketch.ino

Sets the STEP, DIR and ENABLE pins as outputs, then drives ENABLE low. The shield holds that pin high, so without this the drivers stay off and the motors do not move.

void setup() {
  pinMode(X_STEP, OUTPUT);
  pinMode(Y_STEP, OUTPUT);
  pinMode(X_DIR, OUTPUT);
  pinMode(Y_DIR, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  digitalWrite(ENABLE, LOW);
}

loop sketch.ino

Sets the two DIR pins to opposite levels, then calls steps for STEPS_PER_TURN / 4 steps at 300 microseconds each, a quarter turn. After a 300 ms pause it flips both directions and steps the same amount back.

void loop() {
  // A quarter turn one way, X and Y opposite...
  digitalWrite(X_DIR, HIGH);
  digitalWrite(Y_DIR, LOW);
  steps(STEPS_PER_TURN / 4, 300);
  delay(300);
  // ...and back.
  digitalWrite(X_DIR, LOW);
  digitalWrite(Y_DIR, HIGH);
  steps(STEPS_PER_TURN / 4, 300);
  delay(300);
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The motors do not move at all This project
    Check that pin 8 is driven low in setup and that the DC source is wired to VM+ and VM-.
  • The motors move the wrong amount This project
    STEPS_PER_TURN assumes 1/16 microstepping. If you change the jumpers, change that constant too.
  • The driver or the Arduino dies when you plug in a stepper motor. CNC shield v3 with A4988s
    Never connect or disconnect motors while the shield has power. Add a 100 uF capacitor across the motor supply. Supply is typically 12 to 24 V, and the A4988 limit is 35 V.
  • Motors hum, stall, or run hot. CNC shield v3 with A4988s
    Set the current limit with the Vref trimmer on each A4988 before use, to about the motor's rated current. Wire each coil to its own output pair. Cool the drivers with a heatsink.
  • The motor buzzes, shudders, or only vibrates instead of turning. Stepper motor
    Coils are swapped. Find the two coil pairs by measuring resistance with a meter (a few ohms between wires of one coil). Connect each pair to one driver coil output, A to A and B to B.
  • The motor stalls or loses steps when you speed up. Stepper motor
    A stepper cannot jump to a high speed. Start with slow step pulses and ramp up gradually. Check the driver current limit (Vref) and give the supply enough voltage, such as 12 V.
  • The circuit sees no voltage or the wrong amount. DC voltage source
    Make sure V+ and V- go to the right nodes. The source floats, so tie one side to your circuit ground. Check the set voltage matches what your parts allow.
  • A part gets too much voltage. DC voltage source
    Check the rating of every part before raising the supply. Use series resistors with LEDs, and do not connect the source straight across a short.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.