blogng/blog/2019-02-23-resurracting-an-hp-7440a-plotter.markdown

179 lines
6.7 KiB
Markdown
Raw Normal View History

2019-03-09 19:40:18 +00:00
---
layout: post
2019-03-09 19:43:32 +00:00
title: "Resurrecting an old plotter"
2019-03-09 19:40:18 +00:00
date: 2019-02-23
comments: true
tags: plotter, art, python, hardware, recurse
---
2019-03-11 02:19:27 +00:00
I finally decided to give in to FOMO on
2019-03-09 19:40:18 +00:00
[#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
2019-03-11 02:19:27 +00:00
[nerdsnipe](https://xkcd.com/356/) [Alex](https://github.com/wildconceits) into
2019-03-13 00:40:36 +00:00
collaborating with me. All of the work below is done with him.
2019-03-09 19:40:18 +00:00
## What is a plotter anyway?
2019-03-13 00:40:36 +00:00
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 ability to pick up or place down the pen to draw.
2019-03-11 02:19:27 +00:00
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.
2019-03-09 19:40:18 +00:00
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
2019-03-11 02:19:27 +00:00
made working with raster images hard, and plotters didn't need much operating
memory.
2019-03-09 19:40:18 +00:00
2019-03-13 19:28:02 +00:00
## HP7440A
2019-03-11 02:19:27 +00:00
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
2019-03-09 19:40:18 +00:00
plotter](http://hpmuseum.net/display_item.php?hw=80)
2019-03-11 02:19:27 +00:00
Ours came pretty unscathed, with original manuals!
2019-03-09 19:40:18 +00:00
2019-03-11 02:19:27 +00:00
First thing we did was to open and clean it. I was quite surprised by how
2019-03-09 19:40:18 +00:00
easy it is to open, take that 2018 tech!
2019-03-11 02:19:27 +00:00
![7440A Top cover open](/images/7440a_open.jpg){ width=600px }
2019-03-09 19:40:18 +00:00
2019-03-13 19:28:02 +00:00
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 switch pen down and up.
2019-03-09 19:40:18 +00:00
## Talk To Me
2019-03-11 02:19:27 +00:00
![7440A Interfaces](/images/7440a_interface.jpg){ width=600px }
2019-03-09 19:40:18 +00:00
However, our plotter didn't come with any cables to either power it or to send
2019-03-13 19:28:02 +00:00
commands.
2019-03-09 19:40:18 +00:00
2019-03-11 02:19:27 +00:00
Power supply 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 it to
be a `10-0-10` AC to AC. Luckily someone was selling one in ebay, but we could've
built one ourselves if not.
2019-03-09 19:40:18 +00:00
2019-03-11 02:19:27 +00:00
Communication turned out be just standard serial, however our plotter has a
`DB-22` adaptor, so we had to use a `DB-22` to `DB-9` adpator and then `DB-9` to
`usb` adaptor.
2019-03-09 19:40:18 +00:00
2019-03-13 19:28:02 +00:00
The final step was writing in the only language the plotter can understand,
[`HP-GL`](https://en.wikipedia.org/wiki/HP-GL) or `HP Graphics Langauge`. 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.
2019-03-13 00:40:36 +00:00
2019-03-09 19:40:18 +00:00
.. and finally our plotter moves!
<video width="600" height="450" controls>
<source src="/images/7440a_printing.mp4" type="video/mp4">
2019-03-13 19:28:02 +00:00
</video>
2019-03-09 19:40:18 +00:00
2019-03-13 00:40:36 +00:00
## Goooooooo faster.
2019-03-09 19:40:18 +00:00
2019-03-11 02:19:27 +00:00
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 bits after 60 and crash.
2019-03-09 19:40:18 +00:00
Our first naive solution was to add `1s` sleep between sending subsequent
2019-03-13 00:40:36 +00:00
commands, however this made drawings really slow and added 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]
2019-03-13 19:28:02 +00:00
in [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 it with `OA;`. As soon as we see the position over the serial,
2019-03-13 00:40:36 +00:00
we know that the previous batch is consumed and we can send the next batch of commands.
2019-03-09 19:40:18 +00:00
2019-03-13 00:40:36 +00:00
[wait function]: https://djipco.github.io/hpgl/hpgl.js.html#line1535
[hpgl.js]: https://github.com/djipco/hpgl
2019-03-09 19:40:18 +00:00
2019-03-13 00:40:36 +00:00
The code for it looks like this:
2019-03-09 19:40:18 +00:00
```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.
2019-03-11 02:19:27 +00:00
But everything in computer graphics is a line anyway, right? With some [root of
2019-03-09 19:43:32 +00:00
unity](http://mathworld.wolfram.com/RootofUnity.html) math, we came up with a circle
2019-03-09 19:40:18 +00:00
drawing routine.
<video width="600" height="450" controls>
<source src="/images/7440a_circle.mp4" type="video/mp4">
2019-03-13 19:28:02 +00:00
</video>
2019-03-09 19:40:18 +00:00
## This is only the beginning
2019-03-11 02:19:27 +00:00
Hardware wise, only thing remaining to fix is our pens, which expired in
2019-03-09 19:40:18 +00:00
1996! We are yet to come up with a strategy to refill/replace them.
![Plotter Pen](/images/7440a_pens.jpg){ width=600px }
2019-03-11 02:19:27 +00:00
I am also going to leave this plotter at RC, so that other recursers can
continue hacking on it, and get another one for me and actually do some
generative art. :-)
2019-03-09 19:40:18 +00:00
## Notes
2019-03-11 02:19:27 +00:00
1. Big thanks to Amy and Francis and Alex S for their help at various points.
2019-03-09 19:40:18 +00:00
2. All of our python code is here: [https://github.com/dbalan/plotter-scripts](https://github.com/dbalan/plotter-scripts)
2019-03-11 02:19:27 +00:00
3. Thanks Tom for proof reading this post!