XY table: MDF

The MDF version end result looks like this:

Hardware / construction


The base plate is an MDF plate, 40cm x 50cm large and 12mm thick:

Base plate with axles in place

This picture shows a top view of the base plate, with only the axles mounted in place. In the plate, 6mm wide ridges have been cut out. In those, vertical “runners” of about 4cm high are pressed and glued in place. These hold the axle bearings (the same ones as for the Lego prototype), as well as serving as lateral stabilizers for the X-bridge; the X-bridge has bearings that run against these runners so it is lodged in place laterally.

(The plate also has 13mm wide cutouts, these were used in an earlier version of the MDF prototype as tracks for wheels for the X-bridge. After switching to ball bearings to carry the X-bridge, these do not have a function any more.)

The X-bridge

The X-bridge carries the head, and also holds the drive mechanism for the head. I call it “X-bridge” because the head that rides in this bridge, rides along the X axis. It is basically a top-less box made from 6mm MDF, that has a cutout in the bottom through which the pen (or other device) can reach the material.

Top view of X-bridge with head in place Top view of the X-bridge with axles and belt in place.
Early belt mount on the side of the X-bridge Definitive belt mount on the side of the X-bridge

Early on, the belts were attached to the X-bridge with a simple zig-zag between 3 bolts. It provided enough friction to make it work. In the final version, the zig-zag was cut out in a piece of MDF securely bolted to the X-bridge. Drive mechanisms

The axle bearings are laser-cut from plexiglass. They have mounting holes for M4 bolts. The axle hole is just wide enough to allow the axle to turn freely, without noticeable play. The lower end of the motor mount has the same dimensions as the axle bearings, to make sure the axle hole lines up with a regular bearing on the other end. The top end has cutouts for mounting the motor. These are elongated so the motor can slide up and down, depending on the gear size.

The motor has a slotted axle, with 2 flat sides. The motor gear has a rectangular cut-out, so that it fits nicely onto the motor axle. On the drive axle, the gear fits using a press-fit: the center hole is small enough to require a decent amount of pressure to slip it onto the axle. This keeps it in place by friction.

Axle bearing close-up Close-up of gears and
motor mount, frontal view
Close-up of gears and motor mount,
side view


Electronics: motor controller shield + arduino

This is the electronics: the controller shield (2 stepper sections and a servo connector), with the arduino mounted on top of it. The PCB is mounted on a 6mm thick plate that can be fit a in a 6mm ridge cut into the base plate.

Head carriage Pen plotter head, side view
Pen plotter head, front view Plotter and drill heads

The carrier is separate from the actual head, to make it (relatively) easy to change heads. There is a pen-plotter head, and a micro-drill head.

The carrier “wheels” (bearings) are mounted at an angle, because they serve both as wheels, and lateral stabilization. They run against the sides of the X-bridge to keep the carrier perfectly centered on the X-bridge.

Laser-cut parts: axle bearings, motor mounts, gears, spacers; plastic bearing

These are the laser-cut parts, clockwise from the top left (excluding the plastic bearing on the right):

  • Gear with a rectangular cut-out: this fits onto the motor axle
  • Gear with a round hole: this fits onto the drive axle
  • Axle bearing: the center hole holds the axle, the four other holes are mounting holes for M4-size bolts.
  • Spacers: for the motor axles (5mm inner diameter) and the drive axles (4mm inner diameter)
  • Motor mount: the left half of the motor mount is the same as the axle bearing; this will hold the drive axle. The right half has slots in which the motor can be mounted. The motor can be moved left and right, depending on the center distance of the gears.


Comparison of on-screen drill preview and actual
drilled hardboard. They look very much alike...
Close-up of drill result: 296 holes drilled in
approx. 1 hour's time.


The first version of the software was “all relative”, meaning that all commands were relative to the current position of the head. This worked especially well for the letter drawing software. However, the limits of this approach became clear quickly. The new version of the software works with a home position and an absolute coordinate system.

The source code is here: https://gitlab.com/jvanloov/simple-plotter

The new version of the software addresses several issues:

  • Controlling both axes simultaneously. The original software first moved one axis to its new position, and only after that the other axis was moved. Drawing tilted lines is awkward in that system, so I wrote a “move-to” method that calculates the required movements for both axes at the same time.

  • I looked at GRBL to use for the Arduino firmware, but that requires PWM-controlled stepper motor drivers, and my controller board doesn’t have those.

  • The Arduino firmware can draw rectangles and circles as well, which was used for testing using the Arduino serial monitor. This was removed later, to simplify the firware code. The translator program only sends move commands and up/down commands.

  • Controller software in Python. Initial testing was done using the Arduino serial monitor, but for long sequences of commands this is not ideal. I wrote a program in Python to send sequences of commands.

  • The program reads paths from SVG files, and translates these into “pen-up”, “pen-down” and “move-to” commands for the plotter. This makes it possible to make simple drawings in Inkscape or a similar program, and plot them on paper.

  • The program also has a module to read coordinate from PCB drill files exported from Eagle. This will make it possible to drill PCBs more accurately than is possible by hand.

Another issue that had to be fixed is the communication between computer and Arduino. It worked, but regularly commands did not come through. This was solved by adding a very short delay (5ms) between reading each character from the serial port. It turned out that the arduino was reading quicker than the computer was sending characters.