Introduction: Servo Plotter

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

This instructable explains how to make an A4 plotter using three servo motors and an Arduino UNO R3.

Construction is simple ... all you require is a hacksaw, a sharp knife, and a 3mm drill.

Two plotters are described:

  • The first version, shown in photo 2, uses MG 996R metal gear servos.
  • A second lightweight version using SG90 servos is shown in photo 5

Both plotters use the same software which features an onboard g-code interpreter that is Inkscape compatible. [1]

The MG 996R plotter features a vacuum hold-down and a simple pen-lift. The reason that the sample plot in photo 6 looks weird is that servo1 is faulty ... I have some replacements on order. [2]

While waiting for the replacement servos to arrive I built a lightweight plotter from two SG90 servos to verify the inverse kinematics discussed further on. The sample plot for the SG90 plotter using these equations is shown in photo 7.

The plotters work ... but not as well as my digital versions.

I am publishing my results in the hope that the construction details and solutions to issues that I have encountered are of help to others.

The estimated cost for the MG 996 plotter is less than $100.


  • the first video shows the SG90 plotter in operation
  • the second video shows the RDS3225 plotter in operation[3]
  • photo 1 is the cover image
  • photo 2 shows the assembled plotter
  • photo 3 shows the plotter dissassembled.
  • photo 4 shows the electronic components.
  • photo 5 shows an SG90 plotter made to the same dimensions
  • photo 6 shows a sample plot from the MG 996R plotter ... unfortunately servo1 is faulty.
  • photo 7 shows a sample plot from the SG90 plotter. The code is the same for both plotters.

Warning : Keep clear of the servo arms when using this plotter as the motors are extremely powerful and capable of rapid movement.



The software for this plotter has been adapted from the following instructables:


For a servo plotter to work, each motor must resist the torque from the opposite motor.

An ideal servo should hold its position if it experiences an external torque ... in practice there is a slight movement or “dead-band” until the servo resists.

The dead-band for each my MG 996R servos is shown in photo 6. To obtain these curves I simply pressed against each servo arm until I felt resistance and the servo started to vibrate.

Ideally we should only see a very small trace which is not the case for servo1


14 December 2020

  • The faulty MG 996 servos have been replaced with RDS 3225 servos.
  • See Step 9: Addenda ... for photos and alternate software

Step 1: Parts List

The following parts were obtained from

  • 1 only Arduino UNO R3 with USB cable
  • 2 only MG996R metal gear servos (optionally RDS3225 ... see Step 9)
  • 2 only 25T (tooth) metal disc stents for MG996R servos
  • 1 only Tower Pro SG90 servo
  • 1 only Prototype PCB Expansion Board For Arduino ATMEGA328P UNO R3 Shield FR-4 Fiber PCB Breadboard 2mm 2.54mm Pitch
  • CPS-3205 II 160 w (110Vac / 220Vac) 0-32 v / 0-5A, compact digitally adjustable DC power supply

The following parts were obtained locally:

  • 1 only plastic dual suction_cup (photo 1)
  • 1 meter 25mm x 1mm aluminium extrusion
  • 1 only MBR735 Schottky 35V 7A diode [1]
  • 1 only 28 pin arduino header terminal strip
  • 1 only SPST switch
  • 1 only 2-way PCB mount screw terminals -5mm
  • 1 only pkt M3 nuts
  • 1 only pkt M3*10mm bolts
  • 8 only 25mm x M3 bolts
  • 2 only cable ties

The estimated cost for this plotter is less than $100.

This diode protects your servos should you accidentally reverse your battery connections and may be omitted if you are confident that your wiring is correct.

Step 2: Inverse Kinematics

Photo 1 shows the construction lines for calculating the servo angles. [1]

Photo 2 shows an alternate solution if both servo arms are the same length (Isosceles triangle). Since the internal angles of a triangle equal PI radians (180 degrees) there is no need to calculate angleA ... just subtract angleB from PI and halve the result.

The absolute XY coordinates are shown in blue.

The internal angle for the blue triangle at the (0,0) coordinate is

  • atan2(y,x)

Pythagoras is used to calculate the length of ‘b’

  • b=sqrt(sq(X) + sq(Y))

The servo arms AB and BC (shown in red) form a triangle ABC.

The the internal angles of triangle ABC are calculated using the “Law of Cosines”:

  • Cos(A) = (b^2 + c^2 – a^2)/(2*b*c)
  • Cos(B) = (c^2 + a^2 – b^2)/(2*c*a)

From which we get:

  • Servo1_angle = acos((b^2 + c^2 – a^2)/(2*b*c)) + atan(y,x)
  • Servo2_angle = acos((c^2 + a^2 – b^2)/(2*c*a))

Each of these Arduino servo angles are in radians. [2]

The pulse-widths to each servo must be adjusted to get the correct angles. Details for doing this are explained in this instructable.



For practical reasons an X offset is added to each gcode X value to prevent the servo arms colliding.

Avoid using a Y offset as that causes servo arm1 to operate near 180 degrees ... some servos don’t rotate a full 180 degrees.


To convert these angles to degrees they must each be multiplied by

  • 180/PI = 57.295779513082320876798154814105

Step 3: Schematic

Photo1 shows the circuit schematic [1]

Photo 2 shows the matching shield

Photo 3 shows how the components fit together.



The plotter works with any 5 volt .. 6 volt servo with a stall current of less than 2 amps.

Step 4: Construction

MG 996R Plotter

A plastic suction cup and metal bracket are used to support the servo arms.

  • Photo 1 shows the original double suction cup for lifting glass.
  • Photo 2 shows the handle sawn off one cup.
  • Photo 3 shows the bracket dimensions for a "Trojan" suction cup. Alternate suction cups may be substituted ... just check their dimensions first.
  • Photo 4 shows the bracket attached to the suction cup [1]
  • Photo 5 shows a drop-in servo insert.

Suction cups have the advantage that:

  • they can be attached to any flat surface without scratching. [2]
  • they have a small footprint when storing.

SG90 Plotter

Each of the servos has been hot-glued, 200mm apart, onto a 3mm x 12mm x 220 length of aluminium extrusion.

The pen is cable-tied to a length of 1mm x 12mm aluminium and bent into an L-shape such that the pen-tip is 200mm from the servo.

The SG-90 plotter has no pen-lift as it was built to verify the inverse kinemetics.



Insert a length of 3mm aluminium extrusion between the suction cup and the bracket when drilling the four mounting holes. This allows for a drop-in servo bracket should that be needed

The servo bracket was made from a short length of 30mm x 3mm aluminium extrusion. The end was bent in a vice using a hammer.

Since taking these photos the servo bracket has been inverted and bolted to the outside of the suction cup bracket.


Suctions cups have enormous gripping power. The “Trojan” suction cup has a 4 inch diameter cup which means it can hold PI * 2in * 2in * 14psi = 176 lb ( approx. 80Kg).

Step 5: Servo Arm 1

The servo1 arm comprises two MG-996R servos clamped between two 25mm x 1mm lengths of aluminium extrusion (photo 1). Servo1 has since been inverted [1]

Photo 2 shows the drilling template (not to scale) for servo arm 1

The distance between each servo is 200mm.

Double-sided tape prevents the motors from slipping.



My original design subtracted the desired angle from 180 degrees should a servo(s) rotate in the opposite direction. The downside to this is that many servos can’t rotate a full 180 degrees.

In my final design I have inverted servo1 so that it is operating at shorter pulse-widths.

Step 6: Servo Arm 2

The dimension for servo arm2 are shown in photo1.

The arm is made from a length of 1mm x 25mm aluminium extrusion.

The 25mm width prevents the arm moving sideways.

The 1mm thickness is sufficiently flexible for the servo horn to lift the pen off the paper

Slide the pen downwards until the tip doesn’t quite touch the paper with the SG90 servo-horn extended.

Step 7: Software

The software for this plotter comprises three packages:

  • “servo_plotter.ino”
  • “myServo.h”
  • “myServo.cpp”


  • Download and copy “servo_plotter.ino” into a new Arduino sketch
  • Save the sketch as “servo_plotter” but without the quotes.
  • Download and copy “myServo.h” into the “servo_plotter” folder created in step 2 above
  • Download and copy “myServo.cpp” into the “servo_plotter” folder created in step 2 above

Installation is complete

15 January 2022

Alternate software using a PCA9685 servo shield has been posted here

Step 8: Hardware Adjustment

The top (yellow) trace in photo 1 shows a 500uS pulse which represents 0 degrees rotation.

The bottom (blue) trace in photo 1 shows a 2500uS pulse which represents 180 degrees rotation.

My theory is that the time difference (2000uS) between these two traces represents 180 degrees. I therefore use the following formula to set the servo angle:

  • pulse_width = 500 + servo_angle* 2000/180


Step 1

  • separate (disconnect) the servo arms from each other and the base
  • attach a pointer similar to that in photo 2 to servo 1
  • check that servo 1 points downwards and servo 2 point upwards
  • run servo_plotter.ino
  • set your Serial Monitor to 115200 BAUDS
  • select option “T5 .... set all servos to 90 degrees”
  • position the pointer such that it is close to 90 degrees counter-clockwise to the servo arm when the servo1 motor is pointing downwards
  • now adjust the 500uS pulse width in the servo_plotter_v1.ino header until you get exactly 90 degrees.

My values are shown below:

 // ----- set servo1 limits
  float zero1 = 550.0;
  float scale1 = (float)(2000 / 180.0);
  servo1.calibrate(zero1, scale1);

Step 2

  • select menu options T4, T5, and T6 in turn ... your pointer should move between 0, 90, and 180 degrees. (Note: some servos wont rotate a full 180 degrees)
  • adjust the 2000uS until 180 degrees is obtained or a lesser angle if the servo won't go any further
  • repeat step 1 if necessary

Step 3

  • attach the pointer to servo motor 2 such that the pointer is 90 degrees to the servo arm
  • repeat step 1 and step 2 for this servo

My values are shown below:

// ----- set servo2 limits
  float zero2 = 550.0;
  float scale2 = (float)(2000 / 180.0);
  servo2.calibrate(zero2, scale2);

Step 4

  • Remove the power when the servos are in their 90 degree positions.
  • Attach the servo1 arm pointing away from the mounting base.
  • Attach the servo2 arm at 90 degrees to the servo1 arm
  • The plotter is ready to go

Warning: Do not use menu option “T4 ....... calibrate ... all servos 0 degrees” while the plotter is assembled as the arms will collide.

Step 5

  • Keep clear of the servo arms
  • Apply power ... the servo arms should now move to their home (0,0) position

Step 6

Manually test the plotter by entering T3 or the following gcode instructions

G01 X100 Y0	// pen down ... move 100mm to the right
G01 X100 Y100	// pen down ... move upwards 100mm
G01 X0   Y100	// pen down ... move 100mm to the left
G01 X0   Y0	// pen down ... move downwards 100mm
G00 X0   Y0     // Pen up

All going well you should have drawn a box

Inkscape g-code files may be sent to the plotter using any terminal software ... I recommend “CoolTerm.exe” from

Step 9: Addenda

12 December 2020

This step record the results obtained with RDS3255


  • Photo1 shows the RDS3225 servos
  • Photo 2 shows the extra button s on the shield.
  • Photo 3 shows the "Menu" for plotter 2
  • Photo 4 shows a clockwise plot
  • Photo 5 shows a counter-clockwise plot
  • Photo 6 shows an overlay of the clockwise and counter-clockwise plots. Each direction has been plotted three times. Note that the peripheral curves lie on top of each other, whereas the diagonal plots are separated.

The diagonal line separation is a mystery as there is virtually no unwanted mechanical movement of the servo arms. A possible cause is the 3uS deadband for each servo + plus any backlash in the gears? If you study the video in the Intro section you will see that one servo arm always moves more than the other when plotting the peripheral lines ... whereas both arms must move to plot the diagonals. Plotting in opposite directions accentuates any errors.


  • The distance between the two RDS3225 motor shafts is 200mm.
  • The RDS3225 servo arm comprises a U-shaped length of 25mm x 3mm aluminium extrusion
  • The SG90 pen-lift arm is described in "Step 6: Servo Arm 2"
  • Two normally-open push buttons have been added ... one between pin 7 and ground ... the other between pin 8 and ground


The software for this plotter version is attached to this step

Changes include :

  • a new servo library that refreshes all servos simultaneously rather than in sequence
  • a "home" option
  • two test files (clockwise/counter-clockwise test squares)
  • four calibration options (described below)

Calibration sequence

  • manually rotate each servo to 90 degrees
  • now attach the servo horns
  • open your serial monitor at 115200 bauds
  • press menu item T6 ... numbers will apear on the screen and plotter arm 1 will move
  • pressing the buttons will cause the numbers to increase/decrease
  • press both buttons when plotter arm 1 is pointing directly away from the suction cap (along the Y-axis)
  • ecord the last number in the appropriate header location (_servo1_90)
  • press menu item 7 and repeat the process for servo arm2 such that servo arm 2 is pointing along the X-axis
  • press both buttons to exit and record the last number in the header (_servo2_90)
  • press menu item T8 ... servo arm 1 will move towards the 45 degree position
  • adjust the numbers using the push buttons ... use a 45 degree plastic set-square to determine the angle.
  • press both buttons to exit and record the last number in the header (_servo1_45)
  • press menu item T9 ... servo arm 2 will move.
  • adjust the numbers until servo arm 2 is 45 degrees relative to its original position
  • press both buttons to exit and record the last number in the header (_servo2_45)
  • finally, recompile and upload your changes to your arduino
  • calibration now complete.


  • think before you change the above button sequence ... will the arms collide?
  • watch your fingers ... the servos are capable of buckling the aluminium extrusion if you get things wrong

23 December 2020

See for software and hardware improvements to this plotter.

Step 10: Summary

This instructable explains how to make an A4 plotter using three servos and an Arduino Uno R3.

Two plotters are described:

  • One plotter uses MG 996R metal gear servos.
  • The other plotter uses light-weight SG90 servos

The Arduino is powered from your USB port.

An external 6 volt power supply capable of 5 amps peak is required for the servos.

The layout diagram for a wiring shield is provided along with the circuit diagram

The MG 996R plotter is mechanically sturdy:

  • The first arm comprises a light-weight box section
  • The second arm has no sideways movement but is able to flex up and down for the pen-lift
  • The pen is raised by pressing the SG90 servo horn against the paper.
  • The suction cup has an estimated holding force of 80Kg

The motor for the second servo arm is mounted on the first arm.

  • This reduces the inertia by bringing the mass of the second motor closer to the mounting point.
  • A side effect of mounting both motors on the same arm is that the first arm rotates in the wrong direction.

There are two solutions:

  • subtract the first angle from 180 degrees
  • invert the motor ... this is my preferred option as the servo angles appear more accurate.

The servo current for the MG 996R plotter is 18 milliamps (mA) when all servos are idling and 400 mA when all servos are operating.

The software for this plotter has been adapted from the following instructables:

Both plotters work ... but not as well as the above digital versions.

12 December 2020 ... Deadband appears to be an issue ... see Step 9

I am publishing my results in the hope that the construction details and solutions to issues that I have encountered are of help to others.

The estimated cost for MG 996 plotter is less than $100.

WARNING: Keep clear of the servo arms when using these plotters as the motors are extremely powerful and capable of rapid movement.

  Click here   to view my other instructables.

1000th Contest

Participated in the
1000th Contest