Introduction: CNC Dual Arm Plotter

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

This instructable describes an A4 plotter made from four plastic rulers , two NEMA17 stepping motors, and an SG90 servo pen-lift. The plotting area may be scaled to any size by increasing the length of each arm.

The plotter has an on-board interpreter that recognizes the g-code output from "Inkscape".

Construction is simple. All you need is a wood saw, three twist drills, a screw-driver, a "rat-tail" file, and a soldering iron.

While the software only supports point-to-point plotting [1], the plotter resolution and accuracy is more than sufficient for its intended purpose of creating water-color outlines.

The image was created using the "canny" edge detector in

The gcode was sent to the plotter using


Line and arc plotting is now supported ... see "Step 11"

Step 1: Parts

Very few parts are required to build this plotter.

A list of parts, and the suppliers, is attached.

Step 2: Circuit

The wiring diagram is shown above together with a photo showing how the modules are inter-connected.

Pins D8, D9 are connected to motor1 (M1).

Pins D10, D11 are connected motor2 (M2)

Power to the Arduino is obtained via the USB cable attached to your computer.

Power to the NEMA stepper motors is obtained from an external 6 volt supply.

The 5 volt output from one of the EasyDriver modules is used to power the servo. This keeps the USB current to a minimum.

Step 3: Calculations

The blue "arms" L in the above diagram may be regarded as a 2DOF (degrees of freedom) robotic arm with motor M1 acting as the "shoulder" motor.

Instead of attaching a heavy "elbow" motor to this arm, a separate motor M2 is connected to the pen by means of a series of light-weight linkages. The final pen position is determined by the resulting parallelogram of forces.

Motor choice is not critical other than each motor must be able to resist the "push" from the opposite motor.

Maximum plotting area, for a given set of arms, is obtained when motor M2 is mounted directly above motor M1, Construction, however, is greatly simplified if the motors are placed close together as shown.


"Plotter Calculations 1" show the required calculations when the input (x) is less than the offset distance for motor1.

"Plotter Calculations 2" show the required calculations when the input (x) is greater than the offset distance for motor2.

A combination of these calculations are required when the input (x) is positioned between offset1 and offset2.


The plotter resolution varies with distance d1.

Assume that the angle between arm L (185mm) and d1 is 45 degrees then distance d1 equals 2*185*cos(45) = 261.63mm

Each motor has a resolution of 360/1600 degrees_per_step when the EasyDriver controller is set to 8-times microstepping. The decrease in distance d1 for a +0.5 step error is therefore 261.63 - 2*185*cos(45 + 360/(1600*2)) = 0.512mm

A motor controller supporting 16-times micro-stepping would improve the resolution.


The plotter has one unfortunate characteristic ... lines between any two points are slightly curved as the pen-distance from each motor is NOT proportional to motor rotation [1]

In practice this non linearity is small and easily masked by introducing extra plotting points.


[ The included-angle between the fixed-arm (L) and distance (d1) is given by the formula acos(d1/(2*L)). Rearranging this formula we get d1=2*L*cos(included-angle). Solving for angles of 0, 45, 90 degrees we get distances (d1) of 2*L, 1.5*L, and 0 respectively. Ideally d1 should be length L, NOT 1.5*L, when the angle is 45 degrees. ]

Step 4: Shoulders

The plotter "base" was made from 6mm composition board.

Two NEMA17 motors were placed close together such that the ruler-ends do not touch when the motors rotate. Drilling templates were made by doing a pencil "rubbing" of each motor. 3mm holes were drilled for each corner and a 6mm clearance-hole was drilled for the shaft.

Shaft-extenders were attached to each shaft once the motors were positioned. The rims from two R/C (radio control) wheels were then fitted over the shaft-extenders and locked in place by means of a 4mm bolt through each ruler.

Step 5: Elbows

3mm holes were drilled in each ruler for the "elbow" joints.

The 3mm bolts should barely be finger-tight.

A second nut is used to lock each bolt in position.

Step 6: Pen Lift Assemby

The pen holder

The centre spigot, made from an old CD (compact disk) container, was used for the pen holder. A hollow tube is formed when the spigot-tip is removed.

There are two ways of adjusting the pen height. One method is to wrap approximately 150mm of masking tape around the pen-barrel until a friction fit is obtained.

Another method is shown above. Drill a 3mm hole through the side of the spigot and, with help of tweezers, position a 3mm nut inside the spigot to engage with the bolt. The bolt only has to be "finger-tight" to hold the pen firmly in position.

Small diameter "spigot" holes through the rulers were enlarged using a "rat-tail" file. Make the bottom hole a firm fit around the spigot and lock in place with a piece of reinforced "packaging" tape as shown above.

The hole for the top ruler should be slightly larger such that it spins freely without any side motion. Lock this ruler in place with a cable-tie as shown.

[ Plastic is brittle. I recommend reinforcing the rulers with a strip of "packaging" tape BEFORE drilling the spigot holes. ]

The pen lift

The flexible "pantograph" assembly is raised (lowered) by the SG90 servo-horn.

A piece of "double-sided" tape was placed between the ruler and the servo motor before they were cable-tied together. The tape prevents the motor from twisting.

Step 7: Plotter Adjustments

Supply voltage

There is a delicate balance between applied voltage, motor current and EasyDriver heat dissipation.

The NEMA 17HS2408 motor specifies 0.6 amps through a coil resistance of 8 ohms for a "holding-torque" of 12 N-cm. This equates to a voltage drop of 4.8 volts across the motor windings.

The minimum input voltage to an EasyDriver controller is 6 volts which means that the EasyDriver chips are dissipating (6 - 4.8)*0.6 = 0.72 watts.

Raising the input voltage to 9 volts will not increase the coil current (which is current limited) but simply inceases the heat dissipation to (9 - 4.8) * 0.6 = 2.52 watts ... the chips will get almost too hot to touch.

A supply voltage of 6 volts seems to work well.

[ You may wish to consider NEMA 17HS4630 motors which have a coil resistance of 30 ohms and a motor current of 0.4 amps for a "holding-torque" of 28 N-cm. In this case a supply voltage of 12 volts will be required but the dissipation should be less. I have not tried this ...

12 July 2017: With a 12 volt 400mA motor the EasyDriver module runs a lot cooler. The motor, however, feels warmer due to the increase in motor dissipation from 2.88 watts (4.8V x 0.6A) to 4.8 watts (12V x 0.4A).]

Adjusting the motor current(s)

Set your CPS-3205 power supply to 6 volts.

Attach each motor to an EasyDriver module and apply powDriverer, in turn, to each motor assemby. Now adjust the small potentiometer on the associated EasyDriver module for a current reading of 0.6 amps on the CPS-3205 power supply.

Plotter Speed

The DELAY_MIN code parameter controls the plotter speed.

Decreasing DELAY_MIN increases the plotter speed but you may start to notice speed-wobbles and over-shoot due to inertia from the arms .

Increasing DELAY_MIN decreases the plotter speed, improves the lines, and reduces the over-shoot.

Currently DELAY_MIN is set to 20000 microseconds.

Step 8: The Code

The (annotated) code for this plotter is contained within the attached file "CNC_dual_arm_plotter_v1.ino".

Copy the contents of this file to a new arduino sketch and "save as" "CNC_dual_arm_plotter_v1.ino".

Finally, connect your PC to the arduino via a USB cable and upload the code.

Step 9: Connect Your Plotter

Apply 6 volts to your plotter.

Connect a USB cable between your PC and the Arduino.

Run a terminal emulation program such as and the above menu should appear on your screen.

The menu

The menu is not case sensitive. Typing :-

  • MENU brings up the menu
  • G00 allows you to send the pen to a specific XY co-ordinate with the pen raised.
  • G01 allows you to send the pen to a specific XY co-ordinate with the pen lowered.
  • T1 allows you to position your pen over your 0,0 co-ordinate. Type 'E' to exit.
  • T2 allows you to scale your drawiing. For example "T2 S2.5" will scale your drawing 250%. The default scale is 100%.All pen moves use the drawing scale last set using this menu option
  • T3 and T4 allow you to raise or lower the pen.
  • T5 draws an "ABC" test pattern.
  • T6 draws a "target".
  • T7 draws a set of radial lines

[ Some terminal emulation programs will display the "Xon" and "Xoff" handshake codes from the arduino as the numbers "17:" and "19:" rather than the small hollow squares shown above]


The micros() timer is used for stepping the motors which means that the maximum plot time, before the timer overflows, is 70 minutes.

Do NOT pause the plotter once plotting has commenced as the motors rely on the system time for stepping.

Step 10: Results

This is a fun plotter to use as it is:

  • simple
  • fast
  • reasonably accurate
  • repeatable
  • cheap

Sample test plots

The outline for the "iris" was created using Inkscape. There are only three plotting-points along the left-hand border which explains the curvatures.

The "Hello World !" test plot was created using the attached Inkscape file (hello_world.ngc).

Step 11: Code Update

A software update "CNC_dual_arm_plotter_v2.ino" is attached.

Three new software routines have been introduced:

  • "drawline()" masks the natural tendency of the plotter to distort straight lines by inserting extra plotting co-ordinates at 1mm intervals.
  • "draw_arc_cw()" inserts extra plotting points whenever the clockwise arc-length exceeds ARC_MAX (currently set to 2mm).
  • "draw_arc_ccw()" inserts extra plotting points whenever the counter-clockwise arc-length exceeds ARC_MAX (currently set to 2mm).

The theory behind each of the above functions is fully explained in my instructable

Before and after comparison

An Inkscape test file ("target.ngc") was sent to the plotter. If you examine the file contents with a text editor you will see that it contains very few plotting points.

The "Before" photo shows the plotter output when running the original code "CNC_dual_arm_plotter_v1.ino" .

The "After" photo shows a significant improvement when the plotter is running the code update "CNC_dual_arm_plotter_v2.ino"

  Click here   to view my other instructables.