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
|
|
|
|
|
|
|
## 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 00:40:36 +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-11 02:19:27 +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 00:40:36 +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-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">
|
|
|
|
</video>
|
|
|
|
|
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]
|
|
|
|
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,
|
|
|
|
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">
|
|
|
|
</video>
|
|
|
|
|
|
|
|
## 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!
|