arduino-cnc-plotter-dibujante

How to Build a CNC Plotter with Arduino and GRBL

  • 8 min

So far, our robots moved “more or less” towards where we wanted. If a wheeled robot slips a little, it’s no big deal. But if we want a machine to draw a blueprint or a printed circuit board, error is not an option.

Welcome to the world of CNC (Computer Numerical Control).

In this project we are going to build an XY Plotter: a machine that moves a pen in two axes (X and Y) to draw any vector we design on the computer.

This project is the foundation for later building 3D printers, laser cutters, or CNC milling machines. The control logic (G-Code) is exactly the same.

Stepper Motors and Open Loop

To achieve precision, we leave DC motors and continuous servos behind. We move to Stepper Motors.

A stepper does not spin freely. Its rotation is divided into discrete steps (usually 200 steps per revolution, i.e., 1.8º per step). This allows us to move the axis exactly as much as we want without needing position sensors.

If we tell it “advance 100 steps”, we know it has turned exactly 180º.

This is called Open Loop Control. We blindly trust that the motor has not lost steps. That’s why, if you force the machine and a motor “stalls,” all subsequent drawing will be offset.

G-code and GRBL

Here a paradigm shift occurs. We are not going to write a custom Arduino sketch from scratch that says digitalWrite(motor, HIGH). That would be reinventing the wheel and would be very inefficient.

We will use Grbl 1.1, an open-source firmware for CNC control that can run on an Arduino Uno and acts as a G-code interpreter.

  • We send: G1 X10 Y20 F100 (Go to coordinate 10,20 at speed 100).
  • GRBL translates: Calculates accelerations, decelerations, and sends thousands of precise electrical pulses to the motors to perform that movement smoothly.

Components

  • [1x|blue] Arduino Uno | Plotter brain
  • [1x|orange] CNC Shield v3 | Board that plugs onto the Arduino
  • [2x|red] A4988 or DRV8825 Drivers | Stepper motor controllers
  • [2x|green] NEMA 17 Stepper Motors | X and Y axes
  • [1x|purple] Micro Servo SG90 | Z axis (raise/lower pen)
  • [1x|red] Power Supply 12V 2A | For motors {external}

We can make this project by recycling old DVD drives (which have small step mechanisms) or with standard 3D printing components. We recommend the latter for ease.

Connection Diagram

The CNC Shield makes connecting this as easy as LEGO.

Axis Drivers

The A4988 or DRV8825 drivers are inserted into the X and Y sockets of the CNC Shield. Pay close attention to the orientation of the EN pin, because a driver placed backwards can burn out when the board is powered.

[ { “from”: “A4988 Driver X axis”, “to”: “CNC Shield X Socket”, “color”: “orange”, “note”: “Respect EN orientation” }, { “from”: “A4988 Driver Y axis”, “to”: “CNC Shield Y Socket”, “color”: “orange”, “note”: “Respect EN orientation” }, { “from”: “X/Y Microstepping Jumpers”, “to”: “CNC Shield”, “color”: “gray”, “note”: “Configure steps per revolution” } ]

Stepper Motors

The NEMA 17 motors connect to the four-wire outputs of each axis. If an axis rotates in the wrong direction, simply inverting one coil or adjusting the GRBL configuration usually suffices.

[ { “from”: “NEMA 17 Motor X axis”, “to”: “Motor X Output”, “color”: “green” }, { “from”: “NEMA 17 Motor Y axis”, “to”: “Motor Y Output”, “color”: “green” } ]

Pen Servo

Official Grbl does not directly control a servo as a Z axis. You need a specific plotter variant; use the pin and commands documented by that exact variant, because in Grbl 1.1 pin D11 is normally used for the spindle PWM output and the Z-limit assignment changes.

[ { “from”: “Servo signal”, “to”: “Pin defined by GRBL variant”, “color”: “purple”, “note”: “Do not assume D11 without checking documentation” }, { “from”: “Servo VCC”, “to”: “Regulated 5V”, “color”: “red” }, { “from”: “Servo GND”, “to”: “Common GND”, “color”: “black” } ]

Power Supply

Motor power enters through the terminal block on the CNC Shield. Also adjust the current limit of the drivers before demanding real work from them.

[ { “from”: “12V Supply (+)”, “to”: “VMOT + Terminal”, “color”: “red” }, { “from”: “12V Supply (-)”, “to”: “GND Terminal”, “color”: “black” }, { “from”: “Arduino Uno”, “to”: “CNC Shield”, “color”: “blue”, “note”: “The shield is plugged on top” } ]

Software Flow

Here the process is different from a normal “upload”. We have three steps:

Firmware

Install Grbl 1.1 if the pen is actuated via a spindle-compatible output, or choose a maintained variant for the servo. Do not mix instructions from different forks: check its version, pin map, servo range, and supported commands before wiring.

Then open the upload example indicated by the chosen repository and upload it to the board.

After uploading, the board will behave as a CNC controller as long as it keeps that firmware.

Design and Path Generation

We need to generate the G-code. You can draw the vector in Inkscape and export it with a compatible extension, or use another CAM tool that generates code supported by your firmware.

  1. Draw your vector (text, logo…).
  2. Convert it to a path.
  3. Save the file as .gcode or .nc.

The resulting file looks like this if you open it with a text editor:

G21 (Units in mm)
G90 (Absolute coordinates)
M3 S90 (Activate output; effect depends on variant)
G1 X10 Y10 F1000 (Move diagonally)
M5 (Deactivate output)
Copied!

G-code Sender

We need a program on the PC that sends that file line by line to the Arduino. We recommend Universal G-Code Sender (UGS) or CNCjs. Connect the Arduino to USB, open the port in UGS, and you will see the machine status.

Calibration of Steps per Millimeter

This is the crucial mathematical part. GRBL needs to know: “To move 1 mm, how many pulses (steps) should I send?”.

The formula is:

  • StepsPerRevolution: 200 (in standard 1.8º motors).
  • Microstepping: Set by the jumpers under the driver (typically 1/16).
  • Transmission: If using standard GT2 belt, it’s usually 2mm pitch and 20-tooth pulleys -> 40mm per revolution.

In the UGS console, we send the command to configure the X axis: $100=80 (Sets X to 80 steps/mm).

Testing One Axis Without GRBL

If you want to test a motor without installing GRBL, you can use the AccelStepper library:

#include <AccelStepper.h>

// Definition for a A4988 type driver (Interface 1)
// CNC Shield pins for X Axis
const int xStep = 2;
const int xDir = 5; 

AccelStepper stepperX(AccelStepper::DRIVER, xStep, xDir);

void setup() {
  // Maximum speed and acceleration
  stepperX.setMaxSpeed(1000);
  stepperX.setAcceleration(500);
  
  // Tell it we want to go to position 2000 steps
  stepperX.moveTo(2000);
}

void loop() {
  // In the loop we must call run() as fast as possible
  // It will decide if it's time to take a step now or not
  if (stepperX.distanceToGo() == 0) {
    // If it arrived, go back to the start
    stepperX.moveTo(-stepperX.currentPosition());
  }
  
  stepperX.run();
}
Copied!

This code only checks that the motor rotates. To draw, use GRBL or another firmware that coordinates the axes, manages accelerations, and interprets G-code.

Next Steps

Once your plotter draws with a pen:

  1. Vinyl Cutter: Replace the pen with a drag knife and you can make stickers.
  2. End Stops: Add homing to establish a repeatable origin and travel limits.
  3. More Precision: Measure the actual drawing, correct the steps per millimeter, and reduce play before increasing the machine’s size.

CNC is a discipline that requires patience, but watching your machine draw your name by itself in perfect calligraphy is hypnotic.