How I Designed (and built) My Own Pen Plotter

For the last few months, af­ter read­ing Preslav Rachev’s book Generative Art in Go, I have been play­ing around with writ­ing al­go­rithms that cre­ate in­ter­est­ing graph­ics. I even­tu­ally ended up build­ing a mod­u­lar can­vas li­brary for Rust to make that eas­ier to do, for me and other peo­ple.

After mak­ing a few al­go­rithms and post­ing them to the web, I started look­ing around for more in­spi­ra­tion. I hap­pened upon a video with this pen plot­ter:

A screencap of a pen plotter from Reddit

I was amazed. A ro­bot that could draw vec­tor graph­ics? I had been nerd sniped.

XKCD Comic #356

The Math

The math­e­mat­ics in­volved in­ter­ested my es­pe­cially. How do you trans­late [xy]\begin{bmatrix} x & y \end{bmatrix} to ro­ta­tions of mo­tors? It in­tim­i­dated me a lit­tle at first, but once I sat down and worked it out, I re­al­ized it was sur­pris­ingly sim­ple.

A diagram of the math involved to create the plotter

We con­sider that the two mo­tors are sim­ply length­en­ing or short­en­ing each string a spe­cific amount. Here are the equa­tions that dic­tate the length of each string, given a point [xy]\begin{bmatrix} x & y \end{bmatrix}, and a dis­tance mm be­tween the two mo­tors.

x2+y2=r0\sqrt{x^2+y^2} = r_0 (xm)2+y2=r1\sqrt{(x-m)^2+y^2} = r_1

Is This Actually Going to Happen?

I ini­tially sat down and did the math out of cu­rios­ity. I was­n’t plan­ning on build­ing any­thing. After re­al­iz­ing the el­e­gant sim­plicty of the math, I falt em­pow­ered to go through with it. I threw to­gether a parts list.

A visual of all the parts needed for the plotter

Materials

  • Whiteboard
  • Expo Marker
  • 2 Stepper Motors
  • 3D Printer Timing Belt
  • Arduino
  • Adafruit Motor Shield
  • 12V 2A Power Adapter
  • Duct Tape (as any pro­ject re­quires)

I wanted to build this from scratch, with­out us­ing any­one else’s de­signs or soft­ware.

I or­der the ma­te­ri­als off Amazon and soon enough, I had every­thing I needed.

Putting It All Together

The first step was to sol­der the mo­tor shield onto the Arduino, and wiring up step­per mo­tors. I used my school’s laser cut­ter to make a lit­tle bracket.

The stepper motors mounted to a bracket

I am us­ing weights to bal­ance the belts on the mo­tors. I mounted it to a white­board so I can it­er­ate in soft­ware faster/​eas­ier.

Everything taped onto an old whiteboard. It's super rough, but that's OK

I ini­tially did­n’t have the tim­ing belt, so I pro­to­typed with an old length of wire. This is the last pic­ture be­fore I wrote all the soft­ware, which I want to talk about be­fore I show you that ver­sion.

The Software

There are two, sep­a­rate pro­grams that, to­gether, make the plot­ter work. The first is run­ning on the Arduino, ac­cept­ing com­mands over se­r­ial from the sec­ond, which is run­ning on a USB-connected com­puter (my lap­top).

There are three main rea­sons there needs to be a lap­top in the sys­tem:

  1. The Arduino does­n’t have enough pro­gram mem­ory
  2. The Arduino can­not eas­ily ac­cept files (like SVGs)
  3. It takes for­ever for an Arduino pro­gram to com­pile and up­load, which makes it­er­a­tion frus­trat­ing.

Arduino

The Arduino is run­ning a very sim­ple loop:

  1. Receive two 32 bit signed in­te­gers over se­r­ial (one for each mo­tor)
  2. Linear in­ter­po­late the step­per mo­tors to po­si­tions de­scribed by re­ceived in­te­gers

That’s it. It’s im­por­tant that the time it takes for each mo­tor to reach it’s des­ti­na­tion is the same.

Laptop

The lap­top is do­ing all the math.

I am used my can­vas li­brary Denim to do all the vir­tual draw­ing. I just added a ren­derer that:

  1. Converts all points to a se­quence of belt-lengths
  2. Converts belt-lengths to se­quence of mo­tor move­ments

And sent the re­sult­ing mo­tor move­ments over se­r­ial to the Arduino.

I also wrote a quick lit­tle parser us­ing nom to parse and ex­e­cute the math com­mands you can find in­side SVG <path> el­e­ments.

Final Results

The first drawing on the plotter: the letter A

As you can see, I also made a big, rec­tan­gu­lar box, to hold the marker. It worked al­right, but not great. You also prob­a­bly no­ticed the main lim­i­ta­tion of my de­sign: it can­not lift the marker off the white­board.

I fig­ured the rough­ness was mainly due to un­bal­anced weights and the slant of the white­board. I ad­justed every­thing and tried again.

Take Two

A slightly improved letter A

This one is much bet­ter. The lines are crisp, and ex­actly where they are sup­posed to be. At this point I wanted to try some­thing a lit­tle more ad­vanced out. Something a lit­tle more gen­er­a­tive.

The First Hilbert Curve

An attempt at drawing a hilbert curve

After see­ing the plot­ter draw a Hilbert Curve, I felt proud and a lit­tle dis­ap­pointed. The cor­ners aren’t crisp, the lines aren’t straight. Frankly, it looks like it was drawn by a two-year old.

Solving the Issue

The final attempt at a Hilbert Curve

It worked! Now all the lines are pre­cise, crisp, smooth. The biggest is­sue is that the marker it­self ro­tates as it moves. That would­n’t nor­mally be an is­sue, but the marker is chis­eled, so it re­sults in vary­ing lev­els of pres­sure on the white­board.

Conclusion

This was a re­ally cool pro­ject. I learned a lot. I am not very ex­pe­ri­enced with ro­bot­ics, so this re­ally chal­lenged me. I in­tend on con­tin­u­ing work­ing on it. I want to add the abil­ity for the pen to lift off the can­vas, and re­ally so­lid­ify the marker holder. Most of all, I look for­ward to tak­ing my pro­jects into the real world.