Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
Tag: Improvements
Making the world a better place, one piece at a time
20 oz Starbucks City Mug (got ’em cheap at a tag sale)
Preparation
Microwave the generous cup o’ milk for 1 minute
Mix dry ingredients in the giant mug
Stir in just enough cold milk to make a thick mud (*)
Add peppermint drops using 1/4 tsp measure
Rinse 1/4 tsp measure with vanilla
Blend the extracts into the mud (*)
Stir in warm milk, scraping mud off the mug
Microwave for another 45 s or so
Stir to blend
What’s going on:
More cocoa = more flavor, pure & simple
Less sugar = more cocoa bite
Vietnamese cinnamon adds the aroma & zip of those old Atomic Fireballs
Vanilla smooths the taste
Peppermint reminds you it’s winter
Sipping a cup in the afternoon banishes the urge to power-nosh anything else until suppertime…
* Update: non-alkalized / non-Dutch-process cocoa doesn’t blend well. Mix up the mud, let it set for 15 minutes, blend again, pause for 5 minutes, then proceed. Wonderfully smooth with no powder bombs.
The upper-left tab broke off this “knob” shortly after we got the leaf shredder:
Throttle knob – broken original
But it worked well enough that, following my usual course of action, I could ignore the problem. Until a few days ago, that is, when the remaining tab on that end pulled out of the slot on the engine and the whole affair bent into uselessness.
It’s a $10 item from eBay (with free shipping), $8 from Amazon ($4, not eligible for Prime, so plus $4 shipping), out of stock at my usual online small engine source, and not worth biking a few dozen miles here & there to see if anybody has one. I know better than to look for repair parts at Lowe’s / Home Depot. It’s Tecumseh Part 36638, which may come in handy some day.
So, we begin…
It’s one of those pesky injection-molded miracle plastic doodads that can’t be printed in one piece, so I designed the tabs as separate parts and glued them in place. The solid model shows the intended assembly, with a bit of clearance around the tabs for tolerance and glue slop:
Tecumseh Throttle Knob – solid model – show view
External clearances aren’t an issue, so I made the base plate longer, wider, and thicker, which gave the tabs something to grab onto. The half-round knob is bigger, more angular, and uglier than the OEM knob, because I had trouble holding onto the original while wearing work gloves.
Printing a few extra tabs allows the inevitable finger fumble:
Throttle knob – on platform
The tabs stand on edge to properly orient the printed threads around the perimeter: a great force will try to rip that triangular feature right off the tab, so wrapping the thread as shown maximizes the strength. Laying them flat on their backs would put the force in shear, exactly parallel to thread-to-thread bonds; I wouldn’t bet on the strength of those layers.
The brim provides enough platform footprint around the tabs to keep them upright, but obviously isn’t needed around the knob. Although you could wrap a modifier mesh around one or the other, trimming the brim off the knob with a precision scissors seemed more straightforward.
Slobbering generous drops of of IPS #4 solvent adhesive into the slots and over the tabs softened the PETG enough that I could ram the tabs into place, using a big pliers to overcome their feeble resistance:
Throttle knob – glued latches
With the plastic still dazed from the fumes, I force-fit the knob into the slot on the engine:
Throttle knob – installed
The tabs eased back into position and seem to be holding the knob in place. Worst case: make a new knob, butter up the tabs with slow epoxy, ram knob into slot, then poke a screwdriver inside to realign the tabs against the slot edges.
The solvent had a few cloudy days to evaporate before the next shredding session, whereupon the throttle once again worked exactly the way it should.
The OpenSCAD source code:
// Tecumseh 36638 Throttle Knob
// Ed Nisley KE4ZNU November 2015
Layout = "Build"; // Build Show Tab Base
//- Extrusion parameters must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
inch = 25.4;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
//----------------------
// Dimensions
BaseSize = [40,14,3.0]; // overall base plate outside engine controller slot
Knob = [18,BaseSize[1],17];
TabSize = [7.5,1.6,6.0]; // ovarall length, minimum width, overall height
TabSocket = [8.0,2.0,BaseSize[2] - 2*ThreadThick]; // recess in base plate for tab
TabOuterSpace = 30.0; // end-to-end length over tabs - sets travel distance
SlotWidth = 7.75; // engine controller slot width
SlotThick = 1.5; // engine controller slot thickness
TabShape = [
[0,0],
[BaseSize[2] + TabSize[2],0],
[BaseSize[2] + TabSize[2],ThreadWidth],
[BaseSize[2] + SlotThick,2*TabSize[1]],
[BaseSize[2] + SlotThick,TabSize[1]],
[0,TabSize[1]]
];
CapBaseOpening = [11,7.5,15]; // opening in base plate, Z = clearance from controller plate
//----------------------
// Useful routines
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);
}
//----------------------
// Pieces
module Tab() {
linear_extrude(height=TabSize[0]) {
polygon(points=TabShape);
}
}
module Base() {
CornerRad = BaseSize[1]/8;
difference() {
union() {
linear_extrude(height=BaseSize[2])
hull()
for (i=[-1,1], j=[-1,1])
translate([i*(BaseSize[0]/2- CornerRad),j*(BaseSize[1]/2 - CornerRad)])
circle(r=CornerRad,$fn=4*4);
translate([Knob[0]/2,0,BaseSize[2] - Protrusion])
rotate([0,-90,0])
linear_extrude(height=Knob[0])
hull() {
translate([Knob[2] - Knob[1]/2,0])
circle(d=Knob[1],$fn=8*4);
translate([0,-Knob[1]/2,0])
square([Protrusion,Knob[1]]);
}
}
translate([-CapBaseOpening[0]/2,-CapBaseOpening[1]/2,-Protrusion])
cube(CapBaseOpening + [0,0,-CapBaseOpening[1]/2 + Protrusion],center=false);
translate([0,0,CapBaseOpening[2] - CapBaseOpening[1]/2])
rotate([0,90,0]) rotate(180/8)
cylinder(d=CapBaseOpening[1]/cos(180/8),h=CapBaseOpening[0],center=true,$fn=8);
for (i=[-1,1], j=[-1,1])
translate([i*(TabOuterSpace/2 - TabSocket[0]/2),j*(SlotWidth/2 - TabSocket[1]/2),TabSocket[2]/2 - Protrusion])
cube(TabSocket + [0,0,Protrusion],center=true);
}
}
//----------------------
// Build it
if (Layout == "Base")
Base();
if (Layout == "Tab")
Tab();
if (Layout == "Show") {
Base();
for (i=[-1,1], j=[-1,1])
translate([i*(TabOuterSpace/2 - TabSocket[0]/2),j*(SlotWidth/2 - TabSocket[1]/2),0])
translate([j < 0 ? TabSize[0]/2 : -TabSize[0]/2,j < 0 ? TabSize[1]/2 : -TabSize[1]/2,BaseSize[2] - 2*ThreadThick])
rotate([0,90,j < 0 ? -180 : 0])
Tab();
}
if (Layout == "Build") {
Base();
for (i=[0:5]) // build a few spares
translate([-7*TabSocket[1] + i*3*TabSocket[1],BaseSize[1],0])
rotate(90)
Tab();
}
The original doodle showing the OEM knob dimensions and some failed attempts at fancy features:
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:
A defunct desk lamp emerged from the clutter and cried out for bright, new LEDs. This adapter puts a small LED ring and nine white LEDs on the original lamp head:
Ring Light Mount – in operation
Peering into the business end, before mounting it on the lamp, shows some abrasive adjustment on the inside layer:
Ring Light Mount – LEDs installed
That layer printed over a quick-and-easy support spider:
Ring Light Mount – solid model – bottom
The Slic3r preview looking down through the layer just over the support shows that the perimeter of those LED holes doesn’t have much support:
Ring Light Mount – Slic3r preview – bridge layer
The obvious threads drooped in the predictable way, so I just clipped them off, sanded the high spots into submission, and epoxied everything in place:
Ring Light Mount – LED wiring
That nice Hilbert Curve infill is completely wasted inside the OEM shade, but the smooth curve around the rim had to be on the top surface.
Rather than beefing up the support, you should print the bottom ring (or the top rim) separately, then glue it back on, but I wanted to see how well simple support worked with PETG.
It came out reasonably well:
Ring Light Mount – support spider
That’s far more hair than usual, even for PETG, because I made the spider’s legs exactly three thread widths wide. Slic3r reduced the single infill thread to, literally, a hair that didn’t stick to the platform; the model now has four-thread-wide legs.
Slic3r’s automatic support would do a better job of holding up the underside, albeit with more plastic and printing time:
Ring Light Mount – Slic3r preview – auto support
The top view looks about like you’d expect:
Ring Light Mount – solid model – top
Those two solid models show the small hole for the LED ring wiring, which I drilled into the as-printed plastic. The original layout included just the LED ring, with the wire through a big central hole, but then I realized the wall wart had enough moxie for a few more LEDs. So it goes.
Anyhow, the lamp provides just enough illumination below my big monitors to suffice. The gooseneck might not be quite long enough, but that’ll be another project…
The OpenSCAD source code:
// LED Ring Light Mount
// Ed Nisley KE4ZNU October 2015
DoSupport = true;
//- Extrusion parameters must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
inch = 25.4;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
//----------------------
// Dimensions
NumSides = 8*4; // number of sides on each "cylinder"
LENGTH = 0;
ID = 1;
OD = 2;
Shade = [6.0,45.2,47.5]; // threaded end of OEM lamp shade
RingLED = [4.5,36.0,51.0];
SpotLED = [2.0,0,5.0]; // discrete LEDs in center
NumSpots = 8; // discrete LEDs around the one in the middle
Support = [(RingLED[LENGTH] - 1*ThreadThick),0,(RingLED[OD] - 4*ThreadWidth)];
NumSupports = NumSides/2;
ThreadBase = RingLED[LENGTH] + SpotLED[LENGTH];
OAHeight = ThreadBase + Shade[LENGTH];
//----------------------
// Useful routines
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);
}
//----------------------
// Build it
difference() {
union() { // overall shape
translate([0,0,ThreadBase])
rotate_extrude(convexity = 2, $fn=NumSides)
translate([Shade[OD]/2,0])
circle(r=Shade[LENGTH],$fn=NumSides);
cylinder(d=(Shade[OD] + 2*Shade[LENGTH]),h=ThreadBase,$fn=NumSides);
translate([0,0,ThreadBase])
cylinder(d=Shade[OD],h=Shade[LENGTH],$fn=NumSides);
}
translate([0,0,ThreadBase - Protrusion])
cylinder(d=(Shade[ID] + HoleWindage),h=(Shade[LENGTH] + 2*Protrusion),$fn=NumSides); // opening for shade thread
translate([0,0,-Protrusion])
cylinder(d=(RingLED[OD] + HoleWindage),h=(RingLED[LENGTH] + Protrusion),$fn=NumSides); // opening for LED ring
rotate(180/NumSides) // LED ring power wire
translate([RingLED[ID]/2,0,0])
rotate(180/6)
PolyCyl(2.5,OAHeight,6);
rotate(180/8 - 180/NumSides)
PolyCyl(SpotLED[OD],OAHeight,8); // central LED SpotLED
for (i=[0:NumSpots-1]) // surrounding spots
rotate(i*360/NumSpots - 180/NumSides)
translate([(RingLED[ID] - 2*SpotLED[OD])/2,0,0])
rotate(180/8)
PolyCyl(SpotLED[OD],OAHeight,8);
}
//-- Support structure
if (DoSupport)
color("Yellow")
rotate(180/NumSides) // align bars to flat internal faces
for (i=[0:NumSupports/2 - 1]) {
rotate(i * 360 / NumSupports)
translate([0,0,Support[LENGTH]/2])
cube([Support[OD],4*ThreadWidth,Support[LENGTH]],center=true);
}
In 1991 we lived in Tolland CT, where I took one picture of a maple twig every week:
This slideshow requires JavaScript.
That was with a film camera, of course, with negatives. I assembled the printed images into a poster and eventually (perhaps in 2001) scanned / digitally photographed them four-at-a-time, saved the result as a 330 MB Photoshop file with one 2×2 group in each of 13 layers (there are 50 images, probably because vacations), and burned that to a CD.
All I can say: it must have made sense at the time.
Anyhow, here in the future, I found that CD in a pile destined for the shredder, which shouldn’t ought to happen without some attention.
Here’s how I extracted the separate images from that file into standalone JPEGs, cropped them to a uniform size, and smushed them to suitably low quality:
convert A\ Year\ in\ the\ Life\ of\ Tolland\ CT\ -\ 1991.psd -quality 95 Tolland-1991-%02d.jpg
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+0+0" img-$f-0.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+1212+0" img-$f-1.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+0+1775" img-$f-2.jpg ; done
for f in {01..13} ; do convert Tolland-1991-$f.jpg -crop "1212x1775+1212+1775" img-$f-3.jpg ; done
for f in {01..13} ; do for g in {0..3} ; do convert img-$f-$g.jpg -crop "1100x1650+50+50" out-$f-$g.jpg ; done ; done
sn=1 ; for f in {01..13} ; do for g in {0..3} ; do printf -v dn 'Tolland-1991-Maple-%02d.jpg' "$(( sn++ ))" ; convert img-$f-$g.jpg -crop "1100x1650+50+50" +repage -rotate 90 -define jpeg:extent=200KB $dn ; done ; done
Then WordPress assembles the 50 images into a slide show.
Of course, it didn’t go quite as smoothly as all that, but it took maybe half an hour of fiddling to get it right by iterating on the commands until I liked the results. One might tweak the exposures and suchlike, but that’s in the nature of fine tuning.
Although it’s rated to 500 V, it violates the fundamental principle of high-voltage electronics debugging:
Always keep one hand in your pocket!
The scorched and truncated probe tip on the “ground wire” shows Phil slipped at least once:
Beckman DM73 – probe tip
After far too long, I sacrificed a black multimeter probe from the heap, soldered an alligator clip on the end, and, henceforth, will use it appropriately. Mostly, I never do any high-voltage work, but you never know.
I suppose I should splice that nice black probe onto the end of the Beckman wire for low-voltage work…
The Sony HDR-AS30V has extremely high audio gain, which is precisely what you need for the mic on an action camera. It sends that audio, along with the video, through its HDMI output, so when you drive a display from the camera in enclosed space, the audio is REALLY LOUD and causes severe feedback. For obscure reasons, given the staggering cost of the venue’s AV system, there’s no way to mute the audio channel of the video input when you’re also using a mic attached to someone giving a presentation.
The obvious solution, a shorted jumper (formerly an earbud plug) in the external mic jack, looked like this:
Sony HDR-AS30V – Dummy external mic
Contrary to what I expected, the camera doesn’t disable the internal mic with the jumper in place. The amp probably uses an analog multiplexer, rather than a mechanical switch, and even an off-channel isolation of, say, 76 dB (from the MAX4544 spec, for example) isn’t enough to completely mute the mic. You could, given sufficient motivation, measure the actual isolation, but the surviving audio isn’t subtle at all.
The not-obvious solution turned out to be putting the camera into either single or interval photo mode, rather than the movie mode I use for bike rides. It seems that when the video format doesn’t require audio, the camera either disables the audio inputs or (more likely) just doesn’t include audio data in the HDMI output.
Which produces exactly what I want: a video output with no accompanying audio.