CNC Actuator Plotter




Introduction: CNC Actuator Plotter

About: 55+ years in electronics, computers, and teaching ... now retired.

This instructable explains how to make a CNC plotter using an Arduino Uno R3, an SG90 servo, two NEMA 17 stepper motors, a few pulleys, and a short length of aluminium extrusion.

Construction is simple ... all you need are a few drills, a sharp knife, and a hacksaw.

The plotter has an on-board interpreter that recognises the g-code output from “Inkscape”. All that is required is an XON XOFF terminal that can send text-files one line at a time.

The plotter may also be controlled using a cell-phone or tablet as explained in my instructable

Specific XY coordinates for this plotter are reached by varying the angle and length of a linear actuator. Print sizes greater than A4 are possible by increasing the length of the actuator arm.

The plotter produces excellent watercolour outlines but is not a precision instrument as the resolution varies across the print area. Best-case resolution is 80 steps/mm ... worst-case resolution is 5 steps/mm when the actuator arm is extended to 400mm.

The estimated cost to build this plotter, excluding the power supply, is less than $80 USD


The opening photo shows a closeup of the actuator mechanism.

The video demonstrates the plotter in action.

Sample plots are shown in photo 2.

Eye Hazard

Keep clear of the plotter when it is working, especially the rear, as the actuator can suddenly extend to its full length.

Step 1: Theory

All incoming XY g-code coordinates are converted into angle-distance values.

The required calculations are derived in photo 1.

A straight-line between coordinates is obtained if both motors start and stop together. This is achieved by assigning a different inter-step delay to each motor.

Smooth line are obtained by subdividing all lines and arcs into a series of closely spaced coordinates.

A characteristic of this plotter is that its plotting speed is a function of the minimum inter-step delay and the maximum number of steps between points ... simple moves are faster than complex moves.

This plotter has a number of design issues which have been resolved as follows:


An arc is traced whenever a fixed-length arm is rotated. Such arcs are eliminated by subdividing each line into smaller straight-line segments before printing.

The following software routines achieve this:

“Bresenham’s” straight-line algorithm is used to subdivide each line into a series of closely spaced coordinates.

My “plot()” routine then calculates the number of motor steps, and inter-step delays, to move from one coordinate to the next. This effectively linearises the plotter.

Pen-lift Inertia

Attach a servo pen-lift to the end of a long rod and we immediately have an inertia problem that gets worse with distance.

Inertia is controlled by slowing the angular rotation.


The angular resolution decreases as the actuator is extended.

There is no satisfactory solution to this problem other than to restrict the print size to say A4 or smaller.


An "open" length of GT2 belt is used to position the actuator. The 200 steps/rev motor is fitted with a GT2-20 pulley which has exactly 20 teeth at 2mm intervals for one rotation. This equates to a linear distance of 20*2=40mm for each revolution of the motor.

To improve the actuator resolution I have connected the motor to a 16x micro-stepping controller ... this means the final actuator resolution is 200*16/40=80 steps/mm.

The angular resolution is 35.55 steps/deg. This is achieved using a 200 steps/rev motor, a 16x micro-stepping controller, and 4:1 gearing comprising a GT-200 closed-loop belt timing belt and two GT-80 and a GT-20 pulleys. (200*16*4/360=35.55 steps/deg.)

Step 2:

The circuit diagram fro this plotter is shown in photo 1.

The matching shield is shown in photo 2.

The circuit works equally well with a USB cable or an HC-06 Bluetooth module [1]


Disconnect the Bluetooth module when uploading the Arduino code ... otherwise you will have the USB and Bluetooth module competing for the same serial connection.

Step 3: Parts List

The following parts were obtained from

  • 1 only UNO R3 for arduino MEGA328P with USB Cable
  • 1 only Arduino UNO R3 ATMEGA328P prototype shield board
  • 1 only SG90 Micro Servo 9g For Arduino
  • 1 only HC-06 Bluetooth module (optional)
  • 2 only NEMA 17HS2408 4 lead hybrid stepping motors, 600mA, 8 ohms
  • 2 only 2A phase Big Easy Driver boards v1.2 A4988
  • 4 only V6244 V-groove roller bearings, sealed ball bearings
  • 2 only GT2 aluminium idler pulley for 6mm width GT2 belt, 20 teeth, 5mm bore
  • 2 only GT2 aluminium idler pulleys for 6mm width GT2 belt, passive, no teeth, 4mm bore
  • 1 only GT2 aluminium timing pulley, 80 teeth, bore 5mm
  • 1 only 600mm length GT2 timing belt, open, 6mm width
  • 1 only GT2-200 timing belt, closed-loop, endless, 6mm width, 200mm length
  • Arduino jumper wire

The following parts were obtained locally :

  • 1 only AC110-240V 9 volt 2 amp DC charger [1]
  • 1 only 1N9004 power diode
  • 1 only SPST miniature switch
  • 1 only M6 x 60mm bolt
  • 2 only M6 nuts
  • 2 only M6 x 30mm flat washers
  • 4 only M3 x 10mm bolts
  • 2 only M3 x 30mm bolts
  • 2 only M3 nuts
  • 4 only M4 x 25mm bolts
  • 18 only M4 nuts
  • 1 only 500mm length 10mm x 10mm aluminium “U-tube” extrusion
  • 1 only small piece 18 gauge (1mm) sheet aluminium
  • 1 only piece 6mm composition board (dimensions to suit)

The estimated cost to build this plotter, excluding the power supply, is less than $80 USD


Alternately use a CPS-3205 adjustable DC power supply, 0-32V, 0-5A, AC110-240V

Step 4: The Actuator

The actuator bracket (photo 1) is made from a piece of 18 gauge (1mm) aluminium sheet that was cut and folded using the method described in my instructable

The actuator arm is made from a length of 10mm U-shaped aluminium extrusion.

The extrusion edges fit into four V-groove roller bearings ... this prevents sideways movement,

The top (back) of the extrusion rests against two GT-2 toothless idler bearings ... this prevents lift.

Forward and backwards movement is obtained by threading a length of GT-2 timing belt the full length of the actuator arm.

The belt slides under the idler bearings and loops over the GT2-20 pulley attached to the motor as shown in the above photos. It then passes through the U-channel on the under-side to form a loop. The two belt ends are joined, and the belt is tensioned, by means of cable ties.

The idler pulleys have two M4 nuts either side to act as spacers. The V-groove pulleys are separated by a single M4 nut and one M4 nut either side.

The bolt holes for the V-groove pulleys are elongated ... this allows optimum adjustment of the roller spacing for minimum side-play when the actuator is extended.

Vertical play is of no consequence as we are using a pen-lift.

Step 5: The Base

The baseboard is made from a sheet of 6mm composition board. The board dimensions are not critical ... the dimensions for my board are 350mm x 450mm.

The actuator assembly is supported by a 6mm diameter headless bolt as shown in photo 2. The hole for this bolt is positioned along the center-line of the board and 40mm from the top.

The motor is positioned such that the GT2-200 closed loop belt is taut when fitted to the actuator. Tensioning the belt is easy if the 6mm bolt hole is elongated slightly.

A 6mm “drill collet” prevents the actuator lifting off the bolt. This collet is visible in the cover photo.

The dimensions of the pencil square is A4 x A4 to accommodate portrait and landscape drawings.

Step 6: The Pen Lift

The pen lift comprises a U-shaped piece of 18 gauge (1mm) aluminium sheet bolted to the actuator arm as shown in photo 2. The dimensions are not critical ... just custom fit the holes so that your pen slides freely without wobbling.

The SG90 servo is cable-tied to the pen-lift bracket. I placed a piece of double-sided tape under the SG-90 to prevent it slipping.

The pen-lift “collar “was fashioned from a plastic disk (the end off a copper-wire spool) glued to the brass center of a large radio knob.

Step 7: Motor Controller Adjustments

  • Unplug the shield from the Arduino
  • Rotate the motor controller potentiometers fully clockwise (CW)
  • Disconnect one of the motors
  • Apply 9 volts to the shield
  • Adjust the motor current to 600mA by rotating the potentiometer slowly CCW
  • Switch off the 9 volt supply
  • Unplug the first motor
  • Plug the second motor into its controller
  • Apply 9 volts to the shield
  • Adjust that motor current for a reading of 600mA
  • Switch off the 9 volt supply
  • Plug the shield into your Arduino
  • Done

Step 8: Software Installation

  • Unplug the shield from the Arduino
  • Download and copy the contents of the attached file “cnc_actuator_plotter.ino” into an Arduino sketch.
  • Change the header “YAXIS” and “OFFSET” values to match your plotter
  • Save the sketch as “cnc_actuator_plotter” (without the quotes).
  • Now upload the sketch to your arduino
  • Done

Step 9: Testing Your Plotter

  • Switch off the 9 volt supply
  • Remove the HC-06 Bluetooth module from the shield
  • Plug the shield into your arduino
  • Position the pen over the lower left corner of the plotting area ... this is coordinate (0,0).
  • Apply 9 volts to your shield
  • Run your Arduino Serial Monitor at 9600 bauds ... a menu similar to photo 1 should appear
  • Type either T4, T5, or T6 to run one of the internal test programs.

Step 10: Sending an External File to Your Plotter

External files require a terminal program that:

  • supports the XON XOFF protocol,
  • is able to send text files, and
  • can be configured to pause after each linefeed character [1]

Suitable terminal software includes:

Installation instructions for CoolTerm follow:

  • Download "CoolTerm" for Windows from
  • Unzip the file ""
  • Copy the entire folder "CoolTermWin" to your "desktop"
  • Copy the attached "" into the "CoolTermWin" folder [1]
  • Copy the attached "square.gcode.txt" into the "CoolTermWin" folder [2]
  • Unplug the Bluetooth module from your plotter. [3]
  • Connect a USB cable to your plotter.
  • Double "left-click" the file "CoolTerm.exe" within the "CoolTermWin" folder to run.
  • Left_click "Connect" ... a menu (photo 1) should appear.
  • Experiment with the menu options

Sending a g-code file to the plotter:

  • Run “CoolTerm”
  • Click “Connection|Send Textfile” and select the file “square.gcode.txt”
  • Click “open” and your plotter should start working.
  • The plot is finished when the progress-bar reaches 100%


The "" file contains the Omni wheel plotter settings that I use. My default port when using a USB cable is COM4 ... you may need to change this.


Adding a .txt file extension to each of your gcode files makes the filenames visible when clicking "Send a text file" ... otherwise you will have to type the g-code filenames in full.


To avoid data conflict the Bluetooth module MUST be disconnected when a USB cable is connected to your Arduino.

Step 11: Bluetooth Operation

Bluetooth operation requires that the USB cable be disconnected and the HC-06 Bluetooth module fitted to the shield.

Instructions for “pairing” your HC-06 Bluetooth to your PC and sending external g-code files to the plotter using “CoolTerm” are given in Step 10 of my instructable

Step 12: Summary

The output from this plotter is satisfactory for drawing watercolor outlines.

Construction is simple ... metal-work has been kept to a minimum ... only a few hand tools are required

The armature resolution is 80 steps/mm whereas the angular resolution is 35.56 steps/degree. Worst case resolution with a 400mm actuator is therefore (PI*800)/(360*35.56)=0.2 mm/step or 5 steps/mm

The natural tendency of this angle-distance plotter to draw curves instead of straight lines is masked in software.

In theory a small foot-print may be obtained by discarding the baseboard and clamping the actuator assembly to the edge of a table while the plotter is in use.

  Click here   to view my other instructables.

Be the First to Share


    • Game Design: Student Design Challenge

      Game Design: Student Design Challenge
    • Big and Small Contest

      Big and Small Contest
    • Make It Bridge

      Make It Bridge



    3 years ago

    Very nice I like it.
    I had issues with accuracy with one of my projects.
    I would like to help if I can. (if you already know this, I apologize)
    I looked at your code.
    Your constants have a lot of digits. Have you read this?
    The float data type has only 6-7 decimal digits of precision. (that's digits not decimal places)
    To get around this, on my project I worked out my current position using actual steps the motors have actually moved (have a variable that keeps track of number of steps the motor has taken from origin ) use these steps to calculate actual current angle and distance.
    Every thing is calculated from origin, then one taken from the other.
    I hope that made sense :)


    Reply 3 years ago

    Thank you for your interest in my project :)

    My code uses the approach that you suggest:

    // ----- absolute plotter coordinates
    THIS_X = 0, // this X co-ordinate (rounded)
    THIS_Y = 0, // this Y co-ordinate (rounded)
    LAST_X = 0, // last X co-ordinate (rounded)
    LAST_Y = 0, // last Y co-ordinate (rounded)
    CURRENT_STEPS1, // motor1 step counter
    CURRENT_STEPS2; // motor2 step counter

    Stepping motors use integer steps which means there is always an angular/positional error. I track this error using the THIS_X, THIS_Y, LAST_X, LASY_Y variables. The actual number of motor steps are counted using CURRENT_STEPS1, and CURRENT_STEPS2

    It is not possible to draw a straight diagonal line using a fixed length actuator arm ... the result is always a curve. My code divides the desired linear path into a series of small line segments. The end coordinates for each of these line segments are then calculated and the motors stepped to the nearest coordinate .... this effectively eliminates the curves.

    "Before" and "After" photos using this technique are shown in Step 11.


    Reply 3 years ago

    Ah soo sorry I see it now, I was looking at the wrong part of the code.