CNC Dual Arm Plotter




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.

Be the First to Share


    • Rice & Grains Challenge

      Rice & Grains Challenge
    • CNC and 3D Printing Contest

      CNC and 3D Printing Contest
    • Lamps Challenge

      Lamps Challenge


    Leelaprasad P
    Leelaprasad P

    Question 2 years ago

    Can we get the images of machine in top and bottom view and to view wheel stepper connections


    Question 3 years ago on Step 5

    what is the maximum angle for the elbow should be?


    Answer 3 years ago

    The angles for each arm are determined by their length, and the distance each motor is from the "Y" axis.

    Photo 4 , in the "Intro" section, shows a square pencil outline drawn on the the baseboard. The pen is able to plot anywhere inside this square. For mechanical reasons the pen cannot plot outside this area.

    The maximum height occurs when the two center rulers form a straight line.

    The lowest limit is when each set of two rulers form a straight line.


    4 years ago

    How difficult would it be to disconnect this from the computer and run preset drawings from an SD card?


    Reply 4 years ago

    One way to disconnect your computer would be to use the SD card slot on your PC and add bluetooth as described in my instructable

    But if you want a completely self contained plotter you will need to add an SD card reader module to the plotter and write the necessary code. An LCD display would also be helpful.

    A self contained plotter is plausible but if I were to go down this track I would modify my plotter as
    - that plotter is significantly more accurate [1]
    - plus the paper is easier to load and unload
    - and the design is scalable

    [1] See my comment to DejayRezme in the comment section for which is also an angle-distance plotter.


    5 years ago

    I'm curious whether this design would work on a vertical surface, or would it be too heavy for the steppers? Have you tried?


    Reply 5 years ago

    The "pen drop" is accomplished by gravity, it seems. The servo horn swings out of the way and the pen drops onto the paper. So I'd say vertical wouldn't work unless you could apply some tension against your vertical surface. Why not plot horizontally, then transfer your plotted document to your vertical surface?


    Reply 5 years ago

    A great suggestion ...

    Tension against a vertical surface is possible if you replace the shoulder arms with thick aluminium flat bar and the elbow arms with thin aluminium flat bar as shown in

    Tension is then obtained by bending the thin flexible elbow arms slightly downwards until the servo (without the pen) just touches the drawing surface.

    The weight of the arms would require some form of counter-balance to prevent them dropping.


    Reply 5 years ago

    My ultimate goal is a dry erase board plotter that I could affix magnetically in a classroom. I'd been leaning toward "v-plotter" or "polargraph" design, but wondered if a design like this one might work.


    Reply 5 years ago

    It may work vertically if you were to attach a strong (lightweight) magnet to one of the arms and use a magnetic whiteboard ... just a thought.


    Reply 5 years ago

    Stronger motors, or some method of counter-balancing, would be needed for vertical plotting. The existing motors lift the mechanism but don't prevent the mechanism dropping (due to gravity) past the target location when the pen is being lowered.


    5 years ago

    My servo is a Turnigy TGY90S Metal Gear Servo 1.8kg / 13.4g / 0.10sec. I just happened to find them in a 2nd hand market, so they were by no means hand picked for this project. I guess the stepper motor approach is way better.
    I picked the 1:1 ratio for simplicity, too. But then I realised that the maths are not that harder for any ratio! A² = B² + C² - 2BCcos(a) where A is the elbow-pen-arm and a its opposite angle you want to find.
    I have yet to "calibrate" my servos. They don't turn a full 180 degrees, though my code expects them to do so. But my tests show that the servos (with minimal load) rotate each time very precise to same position for any given angle.
    To minimise friction at the elbow joints, I've thought of using flat bearings. And neodym magnets 1 mm from each other to keep the joints together. No bolts! No contact point other than the bearing balls. This I'll let wait until I get hands on a 3D printer. With the printer I will create 1:2 or even 1:3 arms with perfectly fits for the servo horns, the bearing beds, the magnets etc.


    Reply 5 years ago

    Thank you for the servo info :)

    And fine on the cosine formula. It is definitely the way to go for arm ratios other than 1:1. The cosine formula simplifies down to angle=acos(distance/(2*arm-length)) if the arms have a 1:1 ratio.

    The problem you have with the joints can be eliminated by drilling the joints to 3/16 inches (4.76mm) and inserting a tubular 3/16 inch radio spacer. Cut the spacer length to suit by placing it to the correct depth in an electric drill and holding a hacksaw blade or fine pitch file against the spacer ... works like magic. Now sandwich the spacer between two 3mm washers and a 3mm nut and bolt. The finished result is a low friction joint with no sideways play.


    5 years ago

    I'm working on a similar project. I use servos instead of stepper motors. My prototype has four arms of equal lengths as yours. My first drawings show a precision not far from yours. The servos can turn to fractions of a degree.

    Then I got the great advice to shorten the primary arms. In my case it was for making it possible to use the whole 180 degree sector of the servo, increasing the accuracy. Meantime it increases the push and pull force of the elbow.


    Reply 5 years ago

    Thank you for your comment :)

    I looked at 1:2 shoulder:elbow ratios but opted for equal length arms as the maths was simpler and making "Offset1=Offset2" allows for 360 degrees rotation should that be required.

    The accuracy of the "dual-arm" plotter configuration can be improved by attaching GT2-20 pulleys to each of the motors and repositioning them sideways. Now fix each of the shoulder arms to a GT2-80 pulley that is free to spin about 6mm bolts located where the motors were originally positioned. GT2-200 timing belts linking each of the pulley pairs creates a 4:1 gear ratio.

    Replacing the "EasyDriver" with a "Big EasyDriver" set to 16 times microstepping increases the total resolution by a factor of 4(gear)x2(microstepping)=8.

    The lines shown in the "After" photo in step 11 are now perfectly straight.

    Would be interested to know what servos you are using?


    5 years ago

    I like the simplicity. Why not have both motors on the same axis. Wouldn't this increase accuracy by decreasing line curvature?


    Reply 5 years ago

    The lines would still be curved.

    There is an inherent distortion whenever you convert XY co-ordinates into angle-distance. The maths behind this is explained in step 3.

    The good news is that this distortion can be masked by introducing addition plotting points as demonstrated in step 11.


    5 years ago

    The code for this plotter has been udated to support lines and arcs.

    See Step 11 of this instructable for "CNC_dual_arm_plotter_v2.ino"


    5 years ago

    Thanks. It's nice to see other retirees being imaginative. I like minimalist designs (the MacGyver in me?).

    I noticed that the code included "arc" versions of the "move to" commands identical to their linear counterparts that weren't in the menu. What were your ideas on implementing an "arc" for them? Was this for those long moves that you indicated may be arced accidentally (so if you inverse arc them, the lines are straight)?Otherwise It seems they need another parameter to specify curvature (like splines).

    I'm curious to know how the design's parts usage evolved. Was it mainly because "they were around"?


    Reply 5 years ago

    The "interpreter" commands to which you refer do not appear on the menu as they are only required when plotting the output from Inkscape.

    The only commands that an Inkscape plotter must recognise are G00 (linear move with the pen up), G01 (linear move with the pen down), G02 (clockwise arc with the pen down), and G03 (counter-clockwise arc with the pen down). All other commands may be safely ignored.

    For proof-of-concept testing I have converted all G02, and G03 commands to G01 (linear move with pen down). For the purpose of transferring watercolor outlines to paper this is accurate enough as points that are close together approximate a straight line.

    Code for generating perfect lines and true XY arcs are detailed in my instructable

    To implement true arcs for this plotter the XY co-ordinates from the above code must be converted into angle-distance co-ordinates before being sent to the move_to() function.

    Regarding the parts ... the BYJ48 stepper motors that I have used in all of my other projects couldn't withstand the "push" from each other so I searched the internet for the cheapest parts that would be suitable.