diff --git a/blog/2019-02-23-resurracting-an-hp-7440a-plotter.markdown b/blog/2019-02-23-resurracting-an-hp-7440a-plotter.markdown new file mode 100644 index 0000000..ea10511 --- /dev/null +++ b/blog/2019-02-23-resurracting-an-hp-7440a-plotter.markdown @@ -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! + +![7440 open](/images/7440a_open.jpg){ 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 + +![7440 interface](/images/7440a_interface.jpg){ width=600px } + +However, our plotter didn't come with any cables to either power it or to send +commands. Power was the biggest mystery + +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! + + + +## 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. + + + +## 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. + +![Plotter Pen](/images/7440a_pens.jpg){ 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) diff --git a/images/7440a_circle.mp4 b/images/7440a_circle.mp4 new file mode 100644 index 0000000..e7439be Binary files /dev/null and b/images/7440a_circle.mp4 differ diff --git a/images/7440a_interface.jpg b/images/7440a_interface.jpg new file mode 100644 index 0000000..ad007d3 Binary files /dev/null and b/images/7440a_interface.jpg differ diff --git a/images/7440a_open.jpg b/images/7440a_open.jpg new file mode 100644 index 0000000..811ee52 Binary files /dev/null and b/images/7440a_open.jpg differ diff --git a/images/7440a_pens.jpg b/images/7440a_pens.jpg new file mode 100644 index 0000000..dd5f192 Binary files /dev/null and b/images/7440a_pens.jpg differ diff --git a/images/7440a_printing.mp4 b/images/7440a_printing.mp4 new file mode 100644 index 0000000..e2c5bad Binary files /dev/null and b/images/7440a_printing.mp4 differ