The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Author: Ed

  • HP 7475A Plotter: SuperFormula Demo Madness!

    A gallery of SuperFormula plots, resized / contrast stretched / ruthlessly compressed (clicky for more dots):

    The gray one at the middle-bottom suffered from that specular reflection; the automagic contrast stretch couldn’t boost the paper with those burned pixels in the way.

    Those sheets all have similar plots on the back, some plots used refilled pens that occasionally bled through the paper, others have obviously bad / dry pens, and you’ll spot abrupt color changes where I swapped out a defunct pen on the fly, but they should give you an idea of the variations.

    The more recent plots have a legend in the right bottom corner with coefficients and timestamps:

    SuperFormula Plot - legend detail
    SuperFormula Plot – legend detail

    Limiting the pen speed to 10 cm/s (down from the default 38.1 cm/s = 15.00 inch/s) affects only the outermost segments of the spikes; down near the dense center, the 9600 b/s serial data rate limits the plotting speed. Plotting slowly helps old pens with low flow rates draw reasonably dense lines.

    Each plot takes an hour, which should suffice for most dog-and-pony events.

    I fill a trio of Python lists with useful coefficient values, then choose random elements for each plot: a single value of m determines the number of points for all six traces, then six pairs of values set n1 and n2=n3. The lists are heavily weighted to produce spiky traces, rather than smooth ovals, so the “random” list selections aren’t uniformly distributed across the full numeric range of the values.

    Because the coefficient lists contain fixed values, the program can produce only a finite number of different plots, but I’m not expecting to see any duplicates. You can work out the possibilities by yourself.

    The modified Chiplotle demo code bears little resemblance to the original:

    from chiplotle import *
    from math import *
    from datetime 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__':
       paperx = 8000
       papery = 5000
       tscale = 0.45
       numpens = 6
       m_list = [n/10.0 for n in [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]];   # prime/10 = number of spikes
       n1_list = [n/100.0 for n in range(15,75,1) + range(80,120,5) + range(120,200,10)]  # ring-ness 0.1 to 2.0, higher is larger diameter
       n2_list = [n/100.0 for n in range(10,50,1) + range(55,100,5) + range(110,200,10)]  # spike-ness 0.1 to 2.0, lower means spiky points
       paramlist = [[n1,n2] for n1 in random.sample(n1_list,numpens) for n2 in random.sample(n2_list,numpens)]
       if  not False:
         plt=instantiate_plotters()[0]
         plt.write('IN;')
    #     plt.write(chr(27) + '.H200:')   # set hardware handshake block size
         plt.set_origin_center()
         plt.write(hpgl.SI(tscale*0.285,tscale*0.375))    # scale based on B size characters
         plt.write(hpgl.VS(10))                           # slow speed for those abrupt spikes
         pen = 1
         plt.select_pen(pen)
         plt.write(hpgl.PA([(paperx - 3000,-(papery - 600))]))
         plt.write(hpgl.LB("Started " + str(datetime.today())))
         m = random.choice(m_list)
         for n1, n2 in zip(random.sample(n1_list,numpens),random.sample(n2_list,numpens)):
            n3 = n2
            print "m: ", m, " n1: ", n1, " n2=n3: ", n2
            plt.write(hpgl.PA([(paperx - 3000,-(papery - 500 + 100*(pen - 1)))]))
            plt.select_pen(pen)
            plt.write(hpgl.LB("Pen " + str(pen) + ": m=" + str(m) + " n1=" + str(n1) + " n2=n3=" + str(n2)))
            e = supershape(paperx, papery, m, n1, n2, n3)
            plt.write(e)
            if pen < numpens: 
                pen += 1
            else:
                pen = 1
         pen = 1
         plt.select_pen(pen)
         plt.write(hpgl.PA([(paperx - 3000,-(papery - 500 + 100*numpens))]))
         plt.write(hpgl.LB("Ended   " + str(datetime.today())))
         plt.select_pen(0)
       else:
         e = supershape(paperx, papery, 1.9, 0.8, 3, 3)
         io.view(e)
    
  • HP 7475A Plotter: Ceramic Tip Pen Autopsy

    It turns out that the ceramic-tip plotter pens don’t come apart at the top of the flange as I expected. Instead, there’s a snug-fitting plug with a tapered top and an invisible joint at the end of the body tube:

    HP7475A Plotter - ceramic pen - disassembled
    HP7475A Plotter – ceramic pen – disassembled

    Refilling a pair of defunct black ceramic pens didn’t bring them back to life: an ample supply of fresh black ink never made it from the fluff to the nib. Soaking the nibs + fiber shafts in 10% ethanol for a day created an unappetizing black vodka shot that did nothing to get the ink where it needed to be.

    The right time to refill those pens would have been, oh, probably a decade or two ago…

    Some stuff, you just gotta throw out!

  • DC Motor Mounting Plate

    The Squidwrench Power Wheels Racer needed a mounting bracket for its DC motor, so Matt handed me a precut steel slab and some drawings. I did a manual layout to get a feel for the sizes:

    Motor Mount - dye layout
    Motor Mount – dye layout

    Yes, it’s slightly rhomboid & irregular on the sides; it’ll be welded to a U-channel. The front edge is the straightest and I scribed a perpendicular datum line over on the right, from which to measure the motor center point.

    But then, realizing I’d have to mill the central hole anyway, I did what I should have done from the beginning and lined it up on the Sherline:

    Motor Mount - Sherline laser centering
    Motor Mount – Sherline laser centering

    With the part zeroed at the center, everything has polar coordinates. The bolt holes are #10 on a 50 mm BCD, which is G0 @25^[45+90*i]. Rather than writing & debugging a program, I did it all by feeding manual instructions into the interpreter; the i gets typed as 0, 1, 2, and 3 by clicking on a previous command, backspacing, and retyping, which is both faster and easier than it sounds. The holes are drill cycles: G81 Z-7 R1 F30

    This being steel on a Sherline, the rule of thumb that says you can drill at 100x the drill diameter (in inch/min or mm/min, as appropriate) at 3000 RPM gets derated by at least factor of 10. I settled on 30 mm/min for a #10 drill (0.194 inch = 4.9 mm → 500 mm/min = hogwash) after trying the first hole at 50 mm/min:

    Motor Mount - bolt holes
    Motor Mount – bolt holes

    The least horrible way to cut out the hole for the motor mounting boss involved chain drilling to excavate the most steel with the least effort. These center drill points are at G0 @14 ^[15*i] with i in [0..23]:

    Motor Mount - chain center drilling
    Motor Mount – chain center drilling

    I drilled every even hole #27, then every odd hole #28, both at 50 mm/min, to get a thin web:

    Motor Mount - chain drilled
    Motor Mount – chain drilled

    Then helix-mill downward with a 1/8 inch end mill at 1 mm per pass:

    Motor Mount - helix milling
    Motor Mount – helix milling

    That started at 14 mm from the origin to match the hole circle: G3 I-14 F100 Z-1

    Then I switched to a 3/8 inch = 9.5 mm end mill to bring the hole up to size, ending with G3 I-12.75 F300

    Motor Mount - center hole milled
    Motor Mount – center hole milled

    A trial fit showed the hole was slightly off-round, probably due to a few mils of backlash in both axes, and slightly too small, because that’s how I wanted it. Flipped back-to-front, reclamped, recentered, ran the cutter around at 12.75 mm to clear the ovalness, then crept out to 12.8 mm, and it was all good:

    Motor Mount - test fit
    Motor Mount – test fit

    That’s an easy fit with maybe 0.1 mm = 4 mil radial play around the boss. Better than that, I cannot do.

    Lacquer thinner stripped the layout dye and it’s ready for welding:

    Motor Mount - with motor
    Motor Mount – with motor

    Reminders for next time…

    The drill feed on a rigid machine with plenty of spindle power is 100 x (drill dia) @ 3000 RPM. On the Sherline, in steel, 10 x dia is optimistic. Aluminum feeds run higher, but don’t get stupid.

    Re-centering to the accuracy required for this job is a matter of noting the coordinates where the cutter kisses the perimeter across a diameter along each axis, adding the coordinates, dividing by two, moving to that position, and zeroing the origin. Do that in X, Y, X, and Y and it’s good enough. You could automate that with a touch probe, of course. Hand-turning the spindle with the cutter in place to feel it kiss the workpiece is fine, but use the same cutting edge on both sides of the diameter.

    Figure the chain drill diameter thusly:

    • Pick a reasonable drill diameter; #10 is about as large as you want on a Sherline
    • Drill circle dia = final milled hole diameter – drill dia – 2 mm, round down to lower integer
    • # holes = π x DCD / drill dia, rounded down to lower integer
    • Hole angle = 360 / # holes
    • Hole radius = DCD / 2

    Wisely is it written that a man with a CNC milling machine has many friends.

  • HP 7475A Plotter: Refilled Pen Performance

    Squirting brightly colored CMY ink mixes into an assortment of not-quite-dead-yet plotter pens produced reasonable results:

    CMYK Refilled Pens - plot overview
    CMYK Refilled Pens – plot overview

    The blotches on the legend in the lower left corner show that a refilled plotter pen can accumulate a droplet of ink around its nib, which should come as no surprise. I wiped off the excess immediately after refilling each pen, let the assortment sit for a few hours to (presumably) let the new ink reach the nib, and wiped them off before inserting them in the plotter’s pen carousel. All I can say is that I used up a bunch of paper towels in the process…

    A closer look at the plot shows Pretty Good If You Ask Me results:

    CMYK Refilled Pens - plot detail
    CMYK Refilled Pens – plot detail

    The two blue-ish pens have less flow than the others, resulting in dotted lines that should be continuous. As nearly as I can tell, that’s a function of how much OEM ink has solidified in the fiber nib and, most likely, the fiber rod that draws ink from the sponge reservoir inside the body.

    And, of course, the colors produced by adding CMY printer ink to the surviving OEM ink aren’t found in any catalog. I’m also blithely ignoring the difference between the inks inside plotter pens intended for paper and those for overhead transparencies; at this late date, that’s defined to Not Matter.

  • Rail Trail Riding, With Road Rash

    The Dutchess Rail Trail sits atop a pipeline carrying water from the treatment plant in the City of Poughkeepsie to the GlobalFoundries (neé IBM East Fishkill) complex. For good engineering reasons, the mid-line pumping station (equipment yard visible to our left) in Page Industrial Park sits directly athwart the pipe, which forced an abrupt S-curve on a relatively steep slope into the rail trail layout.

    T=0.000 s — The lead cyclist just cut in front of her companion and isn’t leaning into the turn, at which point Mary and I both realize this isn’t going to end well:

    Road Rash 2015-08-15 - 131
    Road Rash 2015-08-15 – 131

    T=0.750 s — Newton grabs control of her bike and he’s not gonna let go:

    Road Rash 2015-08-15 - 176
    Road Rash 2015-08-15 – 176

    T=1.633 s — The rear wheel locks as she passes Mary, she’s far off-center and falling to her left, the bike has gone inertial, and it’s obvious we’re about to arrive at the same place at the same time:

    Road Rash 2015-08-15 - 229
    Road Rash 2015-08-15 – 229

    T=2.100 s — Collision Alarm! I’m veering off the pavement, which is the only reason we didn’t have an offset frontal collision:

    Road Rash 2015-08-15 - 257
    Road Rash 2015-08-15 – 257

    T=2.333 s — Impact! I’m stopped and balanced on the bike, with my left foot out of the pedal cleat and heading for the ground. She’s sliding past me, pivoting around her bike’s left pedal skidding on the asphalt:

    Road Rash 2015-08-15 - 271
    Road Rash 2015-08-15 – 271

    She ended up sprawled atop her bike, facing up the slope, with the front wheel just beside the rear wheel of my bike; her foot or some part of her bike whacked my left-side underseat bag in passing, but there was no bike-on-bike collision. No injuries for her, other than perhaps a bit of road rash, but only by sheer raw good fortune.

    Reviewing the video shows she lost control at the transition from the trail to the downward S-curve, a few seconds before the first picture here and about five seconds before she stopped sliding past my bike, but the problem wasn’t obvious until the scene in the first picture. Mary never had a chance to react and, with less than two seconds until the not-quite-collision, my gross-motor reaction time just barely got me out of the way.

    Brake early and always wear a helmet.

  • Invisible Asterisk: Motorized Sidewalk Traffic

    From the NYS DMV:

    You cannot register or operate any of the motorized devices from the list below on any street, highway, parking lot, sidewalk or other area in New York State that allows public motor vehicle traffic. You may be arrested if you do.

    [List of things]

    Golf Cart (also referred to as Golf Car or Neighborhood Electric Vehicle) – a small motorized device with four wheels designed to carry people.  You can’t register a golf cart as an ATV.  Many low speed vehicles are similar in appearance to a golf cart, and can be registered and driven on New York State highways. 1

    [More things]

    1. For a low speed vehicle to be registered in New York

    • it must meet federal motor vehicle safety standard 500 (49 CFR 571.500)
    • its maximum performance speed must be certified by the manufacturer
    • it must appear on the list of approved limited use vehicles

    With that in mind, here’s a fairly common sight along Raymond Avenue…

    Vassar College regards as Raymond as its private driveway, with its fleet of golf-cart-class and tiny-pickup vehicles traveling the web of sidewalks and pedestrian crossings on and off campus. In point of fact, Vassar does own all of the property on both sides of Raymond from Hooker to Collegeview, but Raymond itself unquestionably has “public motor vehicle traffic”.

    Vassar’s Annual Sidewalk Sodding Week occurs shortly before their graduation / alumnae homecoming ceremonies. The sidewalks and paths obviously weren’t designed for shared vehicular & pedestrian use, so the cart tires gouge unsightly ruts along the pavement edges; the sod prevents those muddy strips from marring the festivities.

    The concrete sidewalks along Raymond take a beating from the vehicles, too, but the overall concrete quality (or lack thereof) may have something to do with that.

    This spiffy tiny-pickup golf cart used by the NYS OPRHP sports a Limited Use Auto plate:

    Limited Use Auto 2015-08-21
    Limited Use Auto 2015-08-21

    It’s sucking a socket at the west end of the Walkway Over the Hudson.

  • HP 7475A Plotter: Pen Refilling Station

    A place to store your vials of blended inkjet juice, plus a workstation for the plotter pen you’re refilling and that ink vial up front:

    HP7475A Plotter Pen Refilling Station
    HP7475A Plotter Pen Refilling Station

    The two pen holders accommodate ordinary fiber-tip pens and ceramic-tip pens. The slot along the front lets you keep track of the ink level, not that there’s much danger of running dry at 0.05 ml per refill from a vial holding 1 ml of blended ink. The big flange makes it harder for me to knock the damn thing over; avoiding an ink spill, even when you have a towel underneath, is a Good Thing.

    The Slic3r tool path preview shows off the Hilbert Curve top & bottom infill:

    Plotter Pen Refill Vial Holder - Slic3r preview
    Plotter Pen Refill Vial Holder – Slic3r preview

    The OpenSCAD source code:

    // HP7475A Plotter Pen Refill Station
    // Ed Nisley KE4ZNU - August 2015
    
    //- Extrusion parameters - must match reality!
    
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;
    
    HoleWindage = 0.2;
    
    module PolyCyl(Dia,Height,ForceSides=0) {			// based on nophead's polyholes
    
      Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    
      FixDia = Dia / cos(180/Sides);
    
      cylinder(r=(FixDia + HoleWindage)/2,
               h=Height,
    	   $fn=Sides);
    }
    
    
    //------
    // Dimensions
    
    WallThick = 6*ThreadWidth;
    BaseThick = IntegerMultiple(1.0,ThreadThick);
    
    VialOD = 8.0;
    VialOC = VialOD + WallThick;
    
    VialArray = [4,4];			// number of vials in each direction
    
    PenOD = [14.7,11.7];			// regular fiber pen body, ceramic *cap* dia
    NumPens = len(PenOD);			// really works for just two pens...
    PenLength = 38;
    FlangeOD = 18;
    
    echo(str("Max pen OD: ",max(PenOD)));
    echo(str("Number of pens: ",len(PenOD)));
    
    Holder = [(VialOC*VialArray[0] + WallThick),(VialOC*VialArray[1] + 2*FlangeOD + WallThick),(3*VialOD + BaseThick)];
    HolderRound = 5.0;
    
    //- Build it
    
    	difference() {
    
    		union() {
    			hull() {
    				for (i=[-1,1], j=[-1,1]) {
    					translate([i*(Holder[0]/2 - HolderRound),j*(Holder[1]/2 - HolderRound),0])
    						cylinder(r=HolderRound,h=Holder[2],$fn=8*4);
    				}
    			}
    			
    			hull() {
    				for (i=[-1,1], j=[-1,1]) {
    					translate([i*Holder[1]/2,j*(Holder[1]/2 - HolderRound),0])
    						cylinder(r=HolderRound,h=BaseThick,$fn=8*4);
    				}
    			}
    			
    			for (i=[0:len(PenOD) - 1])
    				translate([(i*Holder[0]/2 - Holder[0]/4),-Holder[1]/4,BaseThick]) {		// spacing is a total hack
    					rotate(180/12)
    						cylinder(d=FlangeOD,h=PenLength,$fn=3*4);
    				}
    		}
    		
    		for (i=[0:VialArray[0] - 1] , j=[0:VialArray[1] - 1]) {
    			vx = i*VialOC - (VialOC*(VialArray[0] - 1)/2);
    			vy = j*VialOC - (VialOC*(VialArray[1] - 1)/2) + FlangeOD;
    			translate([vx,vy,BaseThick])
    				rotate(180/8)
    					PolyCyl(VialOD,Holder[2],8);
    		}
    		
    		translate([0,(VialOD/2 - Holder[1]/2),BaseThick])
    			rotate(180/8)
    				PolyCyl(VialOD,Holder[2],8);										// edges along open side => snug fit
    		
    		for (i=[0:len(PenOD) - 1])
    			translate([(i*Holder[0]/2 - Holder[0]/4),-Holder[1]/4,BaseThick]) {		// spacing is a total hack
    				rotate(180/12)
    					PolyCyl(PenOD[i],(PenLength + Protrusion),3*4);
    			}
    		
    	}
    

    Mostly because I can…