@@ 0,0 1,170 @@
+---
+layout: post
+title: "Resurrecting an HP 7440A plotter"
+date: 2019-02-23
+comments: true
+tags: plotter, art, python, hardware, recurse
+---
+
+I finally decided to give in to the FOMO of
+[#plottertwitter](https://twitter.com/hashtag/plottertwitter?lang=en) and bought
+an old plotter off ebay. Me being in batch at [Recurse
+Center](https://recurse.com) helped a lot, from the decision to get one to
+[nerdsnipe](https://xkcd.com/356/) Alex into collaberating with me. All of this
+work below is done with him.
+
+## What is a plotter anyway?
+Plotters are devices that can transfer vector graphics onto to a physical
+medium. Core of a plotter is the arm that can move in 2 axes around the medium,
+and ability to put the pen "Down" (draw) and "Up", to position before starting
+to draw. Versions of plotters exist where paper is replaced with other flat
+materials like vinyl and pen with a knife to cut rather than to draw.
+
+I like to think plotters as the naive solution to the problem that computers
+should be able to draw. Smaller, expensive memory chips (or [magnetic
+cores](https://en.wikipedia.org/wiki/Magnetic-core_memory)) in earlier computers
+made working with raster images hard.
+
+## HP7440A
+HP was on top of the plotter game when they were popular, so much
+that other manufacturers started to support
+[`HP-GL`](https://en.wikipedia.org/wiki/HP-GL) (short for `HP Graphics
+Langauge`) as the way to talk to their plotters as well.
+
+HP7440A _"ColorPro"_ was an affordable plotter produced by HP, it can hold 8
+pens at the same time and switch between them automatically and draw on surfaces
+as large as A4. [HP Museum has a longer post about this
+plotter](http://hpmuseum.net/display_item.php?hw=80)
+
+Ours came pretty unscathed, with the original manuals!
+
+First thing we did was to open it and clean it. I was quite surprised by how
+easy it is to open, take that 2018 tech!
+
+{ width=600px }
+
+Internal mechanism is pretty simple, There is two servos. One for moving paper
+back and forward, and one for moving the pen left and right. There is also a
+solenoid based lever to put the pen down and up.
+
+## Talk To Me
+
+{ width=600px }
+
+However, our plotter didn't come with any cables to either power it or to send
+commands. Power was the biggest mystery <power picture>
+
+After digging through the manuals, and the [hand drawn schematics from HP
+Museum](http://hpmuseum.net/exhibit.php?hwdoc=80), we managed to identify power
+supply to be a `10-0-10` AC to AC. Luckily someone was selling one in ebay, but
+we couldve built one ourselves if not.
+
+Communication turns out be standard serial, however our plotter has a `DB-22`
+adaptor, so we had to use a `DB-22` to `DB-9` and `DB-9` to `usb` adaptor.
+
+.. and finally our plotter moves!
+
+<video width="600" height="450" controls>
+ <source src="/images/7440a_printing.mp4" type="video/mp4">
+</video>
+
+## Gooo 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 just drop the overflow bits and
+stop to respond.
+
+Our first naive solution was to add `1s` sleep between sending subsequent
+commands, however this made drawings really slow and there was ink bleeding on
+the paper when the plotter is waiting for the next command.
+
+Another recurser Francis pointed us at the wait [function in
+hpgl.js](https://djipco.github.io/hpgl/hpgl.js.html#line1535).
+
+It is a clever hack, the idea is to send the HPGL command `OA` as a marker, `OA`
+sends the current pen position back from plotter, so we batch a bunch of
+commands, suffix it with `OA`, and as soon as we see the position on the line,
+we know that the current set is consumed and we can send the next batch again.
+
+The code for it looks like this
+```python
+import serial
+
+# combine command together with maxlen buflen and expose as an iterator
+def stitch(body, buflen=40):
+ start = ["IN;PU;", "SP1;"]
+ end = ["SP0;"]
+ final = start + body + end
+
+ ## read in 20 bytes at a time or boundary
+ count = 0
+ buf = []
+ for ins in final:
+ if count + len(ins) >= buflen:
+ yield "".join(buf)
+ buf = []
+ count = len(ins)
+ else:
+ count += len(ins)
+ 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):
+ port = "/dev/cuaU0"
+ speed = 9600
+
+ body = stitch(cmds)
+ 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
+ plt.write("OA;")
+ c = ""
+ data = ""
+ while c != '\r':
+ c = plt.read()
+ data += c
+ 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 HP sold these functionality as an
+[hardware adaptor board that plugs in the
+bottom](https://support.hp.com/us-en/document/bpp01354), which we don't have.
+
+But everything in computer graphics is a line anyway right? With some [roots of
+unity](https://support.hp.com/us-en/document/bpp01354) we came up with a circle
+drawing routine.
+
+<video width="600" height="450" controls>
+ <source src="/images/7440a_circle.mp4" type="video/mp4">
+</video>
+
+## This is only the beginning
+
+Hardware wise, the only thing remaining to fix is our pens, which expired in
+1996! We are yet to come up with a strategy to refill/replace them.
+
+{ width=600px }
+
+I am also going to leave this plotter at RC, so that other recursers continue
+hacking on it, and get another one for me and actually to some generative art.
+:-)
+
+## Notes
+1. Big thanks for Amy and Francis and Alex S for their help at various points.
+2. All of our python code is here: [https://github.com/dbalan/plotter-scripts](https://github.com/dbalan/plotter-scripts)