171 lines
6.3 KiB
Markdown
171 lines
6.3 KiB
Markdown
|
---
|
||
|
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 <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.
|
||
|
|
||
|
![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)
|