| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | --- | 
					
						
							|  |  |  | layout: post | 
					
						
							| 
									
										
										
										
											2019-03-09 14:43:32 -05:00
										 |  |  | title: "Resurrecting an old plotter" | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | date: 2019-02-23 | 
					
						
							|  |  |  | comments: true | 
					
						
							|  |  |  | tags: plotter, art, python, hardware, recurse | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | I finally decided to give in to FOMO on | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | [#plottertwitter](https://twitter.com/hashtag/plottertwitter?lang=en) and bought | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | an old plotter off *ebay*. Being in batch at the [Recurse | 
					
						
							|  |  |  | Center](https://recurse.com) helped a lot: the old hardware laying around inspired the purchase, and a successful | 
					
						
							|  |  |  | [nerdsnipe](https://xkcd.com/356/) of [Alex](https://github.com/wildconceits) gave me a willing | 
					
						
							|  |  |  | collaborator. All of the work below was done with him. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## What is a plotter anyway?
 | 
					
						
							| 
									
										
										
										
											2019-03-12 20:40:36 -04: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 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | axes (w.r.t the medium) and the ability to pick up or place down the pen to draw. | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04: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 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | I like to think of plotters as the naive solution to the problem that computers | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 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-10 22:19:27 -04:00
										 |  |  | made working with raster images hard, and plotters didn't need much operating | 
					
						
							|  |  |  | memory. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | ## HP7440A
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | HP7440A _"ColorPro"_ was an affordable plotter manufactured by HP, it can hold | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | and switch between 8 pens simultaneously, and draw on surfaces as large as A4. | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | [HP Museum has a longer post about this | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | plotter](http://hpmuseum.net/display_item.php?hw=80) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | Ours came pretty unscathed, with original manuals! | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | First thing we did was to open and clean it. I was quite surprised by how | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | easy it is to open, take that 2018 tech! | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | { width=600px } | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | The internal mechanism is pretty simple. There are two servos. One for moving | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | the paper back and forward, and the other for moving the pen left and right. | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | There is also a solenoid-based lever to move pens to and from the paper. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Talk To Me
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | { width=600px } | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Our plotter didn't come with any cables to either power it or to send it | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | commands. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Puzzling out the power supply was the biggest mystery. After digging through the manuals and | 
					
						
							|  |  |  | [hand drawn schematics from the HP | 
					
						
							|  |  |  | Museum](http://hpmuseum.net/exhibit.php?hwdoc=80), we managed to identify it as | 
					
						
							|  |  |  | a `10-0-10` AC to AC. Luckily someone was selling one on *ebay*. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Communication turned out to be done using standard serial over a | 
					
						
							|  |  |  | `DB-22` adapter. We solved this by chaining a `DB-22` to `DB-9` adapter to a `DB-9` to | 
					
						
							|  |  |  | `usb` adapter. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | The final step was writing in the only language the plotter can understand, | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | [`HP-GL`](https://en.wikipedia.org/wiki/HP-GL) or `HP Graphics Language`. Lucky | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | 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-12 20:40:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | ...and finally our plotter moves! | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | <video width="600" height="450" controls> | 
					
						
							|  |  |  |   <source src="/images/7440a_printing.mp4" type="video/mp4"> | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | </video> | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 20:40:36 -04:00
										 |  |  | ## Goooooooo faster.
 | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | HP7440A has a limited amount of buffer space (about `60 bytes`), so if we send a | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | longer command list to the interface, it will drop all bits after 60 and crash. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Our first solution was to add `1s` sleep between sending subsequent | 
					
						
							|  |  |  | commands, however this made drawings really slow, and led to artifacts from | 
					
						
							| 
									
										
										
										
											2019-03-12 20:40:36 -04:00
										 |  |  | ink bleeding while the plotter is waiting for the next command. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Another Recurser, Francis, pointed us to a clever hack in the [wait function] | 
					
						
							|  |  |  | from [hpgl.js]. This function uses the HPGL command `OA;` to block execution | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | and append `OA;`; once we read the position from the serial, | 
					
						
							|  |  |  | we know that the previous batch is consumed and we can send the next batch. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 20:40:36 -04:00
										 |  |  | [wait function]: https://djipco.github.io/hpgl/hpgl.js.html#line1535 | 
					
						
							|  |  |  | [hpgl.js]: https://github.com/djipco/hpgl | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | The code for this trick looks like: | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05: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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | A re-reading of the manual made us realize that HP sold this functionality as a | 
					
						
							|  |  |  | [hardware adapter board that plugs into the | 
					
						
							|  |  |  | bottom](https://support.hp.com/us-en/document/bpp01354). Our plotter did not arrive with this board. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | But everything in computer graphics is a line anyway, right? Using some [root of | 
					
						
							| 
									
										
										
										
											2019-03-09 14:43:32 -05:00
										 |  |  | unity](http://mathworld.wolfram.com/RootofUnity.html) math, we came up with a circle | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | drawing routine. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <video width="600" height="450" controls> | 
					
						
							|  |  |  |   <source src="/images/7440a_circle.mp4" type="video/mp4"> | 
					
						
							| 
									
										
										
										
											2019-03-13 15:28:02 -04:00
										 |  |  | </video> | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## This is only the beginning
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | Hardware wise, the only thing left to fix is our pens, which expired in | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 1996! We are yet to come up with a strategy to refill/replace them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { width=600px } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | I am also going to leave this plotter at RC (so that other Recursers can | 
					
						
							|  |  |  | continue hacking on it), and buy another one for me to actually do some | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | generative art. :-) | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Notes
 | 
					
						
							| 
									
										
										
										
											2019-03-10 22:19:27 -04:00
										 |  |  | 1. Big thanks to Amy and Francis and Alex S for their help at various points. | 
					
						
							| 
									
										
										
										
											2019-03-09 14:40:18 -05:00
										 |  |  | 2. All of our python code is here: [https://github.com/dbalan/plotter-scripts](https://github.com/dbalan/plotter-scripts) | 
					
						
							| 
									
										
										
										
											2019-03-15 17:00:47 -04:00
										 |  |  | 3. Thanks to all who proof read this post. |