Back in the day, you could install a Genuine HP 09872-60066 Digitizing Sight in your Genuine HP 7475A plotter, maneuver the sight to an interesting point on the paper, press the Enter button, send the point’s coordinates through the serial port to the computer, then do whatever you like with the numbers.
Here in the future, I twiddled the demo code that draws Superformula patterns to send a digitization command and await the response at the end of each plot. I can then change the paper, press the Enter button, and get the next plot: exactly what I need for the upcoming Poughkeepsie Mini Maker Faire.
The only gotcha turns out to be that, having hacked the Chiplotle interface to use hardware handshaking, there’s no way to tell when the outgoing buffer has drained. Until that happens, the plotter can’t respond to the digitizing command and, eventually, Chiplotle kvetches about not hearing anything.
The least awful solution seems to be sleeping for 40 seconds (!) while the plotter trudges through the last line of the legend (!!), then continuing apace:
print "Waiting for plotter... ignore timeout errors!" sleep(40) while NoneType is type(plt.status): sleep(5) print "Load more paper, then ..." print " ... Press ENTER on the plotter to continue" plt.clear_digitizer() plt.digitize_point() plotstatus = plt.status while (NoneType is type(plotstatus)) or (0 == int(plotstatus) & 0x04): plotstatus = plt.status print "Digitized: " + str(plt.digitized_point)
When the interface times out, Chiplotle doesn’t set the status
code to anything in particular (which makes sense), so you can’t do anything useful with it. Therefore, the operand order in the last while statement matters: you can’t convert a value of type NoneType
into anything else.
The other change wraps the entire plotting loop with an always-and-forever loop: hit Ctrl-C
to break out at the end of the day.
You can’t change the new plot’s paper size, because the digitizing command preempts the Enter
button that’s part of the Enter+Size
combination. That makes perfect sense, even in retrospect.
Testing that gave me the opportunity to run all the pens, refilled and OEM, through their paces:

The Sakura pens in their adapters continue to work well:

They’re such unique snowflakes…
The complete Python source code:
from chiplotle import * from math import * from datetime import * from time import * from types import * import random def superformula_polar(a, b, m, n1, n2, n3, phi): ''' Computes the position of the point on a superformula curve. Superformula has first been proposed by Johan Gielis and is a generalization of superellipse. see: http://en.wikipedia.org/wiki/Superformula Tweaked to return polar coordinates ''' t1 = cos(m * phi / 4.0) / a t1 = abs(t1) t1 = pow(t1, n2) t2 = sin(m * phi / 4.0) / b t2 = abs(t2) t2 = pow(t2, n3) t3 = -1 / float(n1) r = pow(t1 + t2, t3) if abs(r) == 0: return (0, 0) else: # return (r * cos(phi), r * sin(phi)) return (r, phi) def supershape(width, height, m, n1, n2, n3, point_count=10 * 1000, percentage=1.0, a=1.0, b=1.0, travel=None): '''Supershape, generated using the superformula first proposed by Johan Gielis. - `points_count` is the total number of points to compute. - `travel` is the length of the outline drawn in radians. 3.1416 * 2 is a complete cycle. ''' travel = travel or (10 * 2 * pi) # compute points... phis = [i * travel / point_count for i in range(1 + int(point_count * percentage))] points = [superformula_polar(a, b, m, n1, n2, n3, x) for x in phis] # scale and transpose... path = [] for r, a in points: x = width * r * cos(a) y = height * r * sin(a) path.append(Coordinate(x, y)) return Path(path) # RUN DEMO CODE if __name__ == '__main__': override = False plt = instantiate_plotters()[0] # plt.write('IN;') if plt.margins.soft.width < 11000: # A=10365 B=16640 maxplotx = (plt.margins.soft.width / 2) - 100 maxploty = (plt.margins.soft.height / 2) - 150 legendx = maxplotx - 2600 legendy = -(maxploty - 650) tscale = 0.45 numpens = 4 # prime/10 = number of spikes m_values = [n / 10.0 for n in [11, 13, 17, 19, 23]] # ring-ness 0.1 to 2.0, higher is larger n1_values = [ n / 100.0 for n in range(55, 75, 2) + range(80, 120, 5) + range(120, 200, 10)] else: maxplotx = plt.margins.soft.width / 2 maxploty = plt.margins.soft.height / 2 legendx = maxplotx - 3000 legendy = -(maxploty - 700) tscale = 0.45 numpens = 6 m_values = [n / 10.0 for n in [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]] # prime/10 = number of spikes # ring-ness 0.1 to 2.0, higher is larger n1_values = [ n / 100.0 for n in range(15, 75, 2) + range(80, 120, 5) + range(120, 200, 10)] print " Max: ({},{})".format(maxplotx, maxploty) # spiky-ness 0.1 to 2.0, lower is spiky-er n2_values = [ n / 100.0 for n in range(10, 60, 2) + range(65, 100, 5) + range(110, 200, 10)] plt.write(chr(27) + '.H200:') # set hardware handshake block size plt.set_origin_center() # scale based on B size characters plt.write(hpgl.SI(tscale * 0.285, tscale * 0.375)) # slow speed for those abrupt spikes plt.write(hpgl.VS(10)) while True: # standard loadout has pen 1 = fine black plt.write(hpgl.PA([(legendx, legendy)])) plt.select_pen(1) plt.write(hpgl.LB("Started " + str(datetime.today()))) if override: m = 4.1 n1_list = [1.15, 0.90, 0.25, 0.59, 0.51, 0.23] n2_list = [0.70, 0.58, 0.32, 0.28, 0.56, 0.26] else: m = random.choice(m_values) n1_list = random.sample(n1_values, numpens) n2_list = random.sample(n2_values, numpens) pen = 1 for n1, n2 in zip(n1_list, n2_list): n3 = n2 print "{0} - m: {1:.1f}, n1: {2:.2f}, n2=n3: {3:.2f}".format(pen, m, n1, n2) plt.select_pen(pen) plt.write(hpgl.PA([(legendx, legendy - 100 * pen)])) plt.write( hpgl.LB("Pen {0}: m={1:.1f} n1={2:.2f} n2=n3={3:.2f}".format(pen, m, n1, n2))) e = supershape(maxplotx, maxploty, m, n1, n2, n3) plt.write(e) pen = pen + 1 if (pen % numpens) else 1 plt.select_pen(1) plt.write(hpgl.PA([(legendx, legendy - 100 * (numpens + 1))])) plt.write(hpgl.LB("Ended " + str(datetime.today()))) plt.select_pen(0) plt.write(hpgl.PA([(-maxplotx,maxploty)])) print "Waiting for plotter... ignore timeout errors!" sleep(40) while NoneType is type(plt.status): sleep(5) print "Load more paper, then ..." print " ... Press ENTER on the plotter to continue" plt.clear_digitizer() plt.digitize_point() plotstatus = plt.status while (NoneType is type(plotstatus)) or (0 == int(plotstatus) & 0x04): plotstatus = plt.status print "Digitized: " + str(plt.digitized_point)
2 thoughts on “HP 7475A Plotter: One-Button Demo Madness”
Comments are closed.