Resurrecting an old plotter
I finally decided to give in to FOMO on #plottertwitter and bought an old plotter off ebay. Being in batch at the Recurse Center helped a lot: the old hardware laying around inspired the purchase, and a successful nerdsnipe of Alex gave me a willing collaborator. All of the work below was done with him.
What is a plotter anyway?
Plotters are graphics devices that can transfer vector images onto a physical medium. The core mechanism of a plotter is an arm that can move a pen in 2 axes (w.r.t the medium) and the ability to pick up or place down the pen to draw. Versions of plotters exist where paper is replaced with other flat materials like vinyl or pen with a knife to make it a cutting plotter.
I like to think of plotters as the naive solution to the problem that computers should be able to draw. Smaller, expensive memory chips (or magnetic cores) in earlier computers made working with raster images hard, and plotters didn’t need much operating memory.
HP7440A
HP7440A “ColorPro” was an affordable plotter manufactured by HP, it can hold and switch between 8 pens simultaneously, and draw on surfaces as large as A4. HP Museum has a longer post about this plotter
Ours came pretty unscathed, with original manuals!
First thing we did was to open and clean it. I was quite surprised by how easy it is to open, take that 2018 tech!
The internal mechanism is pretty simple. There are two servos. One for moving the paper back and forward, and the other for moving the pen left and right. There is also a solenoid-based lever to move pens to and from the paper.
Talk To Me
Our plotter didn’t come with any cables to either power it or to send it commands.
Puzzling out the power supply was the biggest mystery. After digging through the manuals and
hand drawn schematics from the HP
Museum, we managed to identify it as
a 10-0-10
AC to AC. Luckily someone was selling one on ebay.
Communication turned out to be done using standard serial over a
DB-22
adapter. We solved this by chaining a DB-22
to DB-9
adapter to a DB-9
to
usb
adapter.
The final step was writing in the only language the plotter can understand,
HP-GL
or HP Graphics Language
. Lucky
for us, HP was on top of the plotter game when plotters were popular, so HP-GL
has become a de facto standard for talking to plotters.
…and finally our plotter moves!
Goooooooo faster.
HP7440A has a limited amount of buffer space (about 60 bytes
), so if we send a
longer command list to the interface, it will drop all bits after 60 and crash.
Our first solution was to add 1s
sleep between sending subsequent
commands, however this made drawings really slow, and led to artifacts from
ink bleeding while the plotter is waiting for the next command.
Another Recurser, Francis, pointed us to a clever hack in the wait function
from hpgl.js. This function uses the HPGL command OA;
to block execution
until the plotter is finished with the current instruction. When the plotter
executes OA;
it sends the current pen position, but it first needs to
wait until the pen has stopped moving. Thus we can batch a bunch of commands
and append OA;
; once we read the position from the serial,
we know that the previous batch is consumed and we can send the next batch.
The code for this trick looks like:
import serial
# combine command together with maxlen buflen and expose as an iterator
def stitch(body, buflen=40):
= ["IN;PU;", "SP1;"]
start = ["SP0;"]
end = start + body + end
final
## read in 20 bytes at a time or boundary
= 0
count = []
buf for ins in final:
if count + len(ins) >= buflen:
yield "".join(buf)
= []
buf = len(ins)
count else:
+= len(ins)
count
buf.append(ins)
# send rest of the code
yield "".join(buf)
# cmds is a list with semicolon attached to the command
def exec_hpgl(cmds):
= "/dev/cuaU0"
port = 9600
speed
= stitch(cmds)
body with serial.Serial(port, speed, timeout=None) as plt:
for ins in body:
# size (Esc-B) returns bufferlen
plt.write(ins)# For block sent, end with OA, which reports back current
# position on the pen
"OA;")
plt.write(= ""
c = ""
data while c != '\r':
= plt.read()
c += c
data print("read: {}".format(map(ord, c)))
print("OA return: {}".format(data))
# We got data, mean OA got executed, so the instruction buffer
# is all consumed, ready to sent more.
This made the plotter super fast!!!
Everything’s a line anyway!
After initial success we quickly realized our plotter does not respond to any
commands that involved HP-GL instructions to draw basic geometry, like CI
for
circle.
A re-reading of the manual made us realize that HP sold this functionality as a hardware adapter board that plugs into the bottom. Our plotter did not arrive with this board.
But everything in computer graphics is a line anyway, right? Using some root of unity math, we came up with a circle drawing routine.
This is only the beginning
Hardware wise, the only thing left to fix is our pens, which expired in 1996! We are yet to come up with a strategy to refill/replace them.
I am also going to leave this plotter at RC (so that other Recursers can continue hacking on it), and buy another one for me to actually do some generative art. :-)
Notes
- Big thanks to Amy and Francis and Alex S for their help at various points.
- All of our python code is here: https://github.com/dbalan/plotter-scripts
- Thanks to all who proof read this post.