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.

Category: Home Ec

Things around the home & hearth

  • Technical Excellence Clock: New Movement

    IBM Tech Excellence Award Desk Clock
    IBM Tech Excellence Award Desk Clock

    Long ago, in a universe far away, IBM gave Mary a desk clock as part of that Technical Excellence Award:

    The double-stick foam tape holding the plate on the front aged out a few years later, at which point I cleaned off the solidified goo, drilled 2-56 clearance holes in the plate and tapping holes in the clock base, installed four pan head stainless screws, and neatly aligned the slots. That’s what it should have looked like from the beginning; this was, after all, a Technical award…

    The clock movement failed recently and I got a drop-in clock insert from Klockit to put it back in operation. The fit wasn’t quite solid, but two wraps of silicone tape around the case under the ribbed friction-fit band solved that problem.

    One new movement cost just about as much as the shipping, so I bought a pair with black and white faces.  Mary picked the white face for this clock, which left the black movement as a spare.

    Tomorrow: what to do with a spare clock insert.

  • MTD Chipper-Shredder Screen: Replacement Thereof

    It’s leaf-shredding season again and our MTD Chipper-Shredder began shredding not nearly as well as it had in years gone by. Last season I laid in a stock of replacement parts, so I swapped in a new Shredder Screen (781-0457):

    MTD Chipper-Shredder screen
    MTD Chipper-Shredder screen

    The flail blades (719-0329) on the massive rotating impeller assembly protrude through the parallel openings in the screen, which is where most of the shredding action happens. The old red screen bent outward enough so that the blades pushed the leaves against the screen, rather than through it, producing frequent clogs.

    Now it works fine again… although I’ve had just about as much fun shredding leaves as any one person should experience in one month.

  • Garden Valve Corrosion

    The Vassar Farm Garden requires fairly heavy watering, because it’s in full sun all day long, so we lay in a set of drip lines connected through Y valves to a main feeder line running down one end of the plot. Plastic valves tend to be overly fragile, so this year I tried a few much larger full-flow ball valves with a metallic housing:

    Corroded Garden Y Valve
    Corroded Garden Y Valve

    This valve lay on the ground (as they all do) just inside the gate and served as an occasional supply for a short hose with the hand sprinkler head. I don’t know what’s driving this corrosion, but it’s eating the external threads as well as the valve bore.

    Overall, I’m unimpressed…

  • Automated Cookie Cutters: Plastic!

    The jellyfish cookie cutter and press look about the way you’d expect:

    Jellyfish Cookie Cutter and Press - separate
    Jellyfish Cookie Cutter and Press – separate

    They’re a bit more impressive on the build platform, where the skirt thread around the perimeter extends slightly beyond the usual 100 mm width limit into the no-go zone behind the nozzle wiper. The bizarre lighting from the warm-white front LEDs and the cool-white overhead LED ring emphasizes the 3D features:

    Jellyfish Cookie Cutter - on build platform
    Jellyfish Cookie Cutter – on build platform

    Somewhat to my surprise, the gritty nature of the bitmap source image didn’t cause a problem. The perimeters consist of many tiny segments, but most of the time goes to filling the interior (20% density, square pattern) and covering the flat surfaces, so the whole thing chugs along at a pretty good pace. Overall, it took something over an hour.

    So, given a height-map grayscale image:

    Manually tweaked jellyfish-high.png
    Manually tweaked jellyfish-high.png

    I (and you!) can automatically create the solid model of a matched cookie cutter and press:

    jellyfish-high - Cutter and Press - top view
    jellyfish-high – Cutter and Press – top view

    And then we can produce as many chunks of plastic as needed for our baking session!

    Printing that huge block of plastic did, however, uncover two longstanding mechanical problems. More tomorrow…

  • Return and Conquest of the Freezer Dog

    As expected, my crude bearing repairs on our Whirlpool refrigerator’s freezer fan didn’t last forever; the freezer dog crept back inside over the course of a few months. I recently ordered another replacement fan (yes, sixty bucks for an open-frame fan!), installed it, and have some interesting data points.

    The OEM fan in the Whirlpool refrigerator was made by FSP and has no country of origin. The date code on the winding insulation reports 1993 and it lasted for the better part of a dozen years.

    The replacement fan, which never sounded quite right and failed in short order, was made by Exact Replacement Parts and has no country of origin. I scrawled 2006 on it, although the bearing noise caused me to remove it almost immediately and re-fix the OEM fan bearings.

    The new fan is once again made by FSP, comes with Whirlpool logos on the screw-and-bushing kit bag, and sports Made In Mexico on the winding insulation. So far, it’s sounded OK, although the normal fan whir seems a bit louder & growlier than before. No howls, though, and that counts for a lot.

    I infer that the ERP fans weren’t entirely satisfactory, but that’s just a guess.

  • Ed’s High-Traction Pizza

    Our Larval Engineer, evidently planning to serve some genuine home-style pizza to her compadres, asked for the Official Recipe.

    It goes a little something like this…

    T minus 2.5 hours

    Blend (manually!) in mixer bowl:

    • 1 Tbsp    yeast (that’s two packets = crazy spendy → buy in bulk)
    • 1 Tbsp    brown sugar (or whatever sweet you have)
    • 1-1/2 C    warm water (1 minute in our microwave)

    Add on top of liquid:

    • 3 C    whole wheat flour
    • 1 C    white flour
    • 1 tsp    salt

    The original recipe called for:

    • 4 Tbsp    olive oil (or safflower, not vegetable / canola)
    • 1/2 C    additional flour only if you add oil

    Don’t stir, just pause 5 minutes until the yeast gets up & running.

    Run mixer until dough becomes rubbery and cleans the bowl.

    No mixer? Stir, stir, stir, then knead, knead, knead.

    Ed & Karen kneading bread dough - Raleigh 1995-ish
    Ed & Karen kneading bread dough – Raleigh 1995-ish

    (As you can see, she has experience kneading bread…)

    Cleave in twain, about 1 lb per lump.
    Oil mixer bowl & one lump, let rise.
    Flatten other lump in plastic bag & freeze for next week.

    Put 1 unit homebrew pizza sauce on counter to thaw.

    T minus 45 minutes

    Roll crust to fit pan, generously flour bottom, let rise on countertop.

    Grate cheese:

    • 2 oz    Sharp Provolone
    • 2 oz    Mozzarella
    • 3 oz    Monterey Jack

    Cube meat:

    • 2 oz    Ham
    • 4 oz    Turkey / pork / what have you

    Chop veggies:

    • handful    Broccoli tips (save stalks for tomorrow’s stir fry)
    • 1/2             Sweet pepper (Green / red)
    • 3                 Bunching onions (or small scallions, whatever)
    • 1 big          Mushroom (or 4 tiddly buttons)

    T minus 15 minutes

    Fire the Oven! to 500 F

    Flour bottom of crust, flop on pan
    Spread pizza sauce generously over crust, counter, walls, self
    Distribute meat / veggies
    Top with cheese

    Slide onto middle shelf of oven
    Set timer to 10 minutes if preheated, 12 minutes if not quite hot yet

    Clean utensils / counter / walls / self

    T minus zero

    Remove from oven (top should be brown & bubbling)
    Pause for coagulation
    Cut
    Distribute
    Nom on!

    The original recipe was about the same, plus foo-foo steps like putting oil in the dough, spreading cornmeal on the pan, oiling the crust before applying the sauce, and suchlike. You’ll need the book for all the details:

    The Complete Book of Pizza
    Louise Love
    Sassafras Press
    1980 (grin)

    I’m sure something different has come along in the last third of a century, but you’ll never hear it from me. Mostly, build a few, tweak the ingredients to suit your style / what’s on hand, and it’ll be all good.

    Enjoy…

  • Automated Cookie Cutters: Putting It All Together

    With that musing, image processing, and data reformatting in hand, this now seems to work pretty well…

    This is MakeCutter.sh, the Bash file that controls the overall process:

    #!/bin/bash
    DotsPerMM=3
    MapHeight=5
    ImageName=${1%%.*}
    rm ${ImageName}_* ${ImageName}.stl
    echo Normalize and prepare grayscale image...
    convert $1 -trim -type Grayscale -depth 8 -auto-level -flip -negate -flop ${ImageName}_prep.png
    echo Create PGM files...
    convert ${ImageName}_prep.png -compress none ${ImageName}_map.pgm
    convert ${ImageName}_prep.png -white-threshold 1 -compress none ${ImageName}_plate.pgm
    echo Create height map data files...
    ImageX=`identify -format '%[fx:w]' ${ImageName}_map.pgm`
    ImageY=`identify -format '%[fx:h]' ${ImageName}_map.pgm`
    cat ${ImageName}_map.pgm | tr -s ' \012' '\012' | tail -n +5 | column -x -c $((8*$ImageX)) > {ImageName}_map.dat
    cat ${ImageName}_plate.pgm | tr -s ' \012' '\012' | tail -n +5 | column -x -c $((8*$ImageX)) > ${ImageName}_plate.dat
    echo Create height map STL files...
    time openscad -D DotsPerMM=$DotsPerMM -D Height=$MapHeight -D FileName=\"${ImageName}_map.dat\" -o ${ImageName}_map.stl MakeSurface.scad
    time openscad -D DotsPerMM=$DotsPerMM -D Height=255 -D FileName=\"${ImageName}_plate.dat\" -o ${ImageName}_plate.stl MakeSurface.scad
    echo Create cookie press and cutter...
    time openscad -D fnPress=\"${ImageName}_map.stl\" -D fnPlate=\"${ImageName}_plate.stl\" -D ImageX=$ImageX -D ImageY=$ImageY -o ${ImageName}.stl Cookie\ Cutter.scad
    

    Hand it an image file name and it just does the rest:

    ./MakeCutter.sh jellyfish-high.png
    

    I assume you’ll pick a workable dots/mm resolution and suchlike for your setup, so they’re hardcoded into the script. You could add them to the command line if you like.

    Starting from the same jellyfish.svg file as before, I came up with a slightly different jellyfish-high.png grayscale height map image with more dots (246×260 dots at 3 dot/mm = 82×87 mm). The original 160×169 file required about half an hour to render and, as you’d expect, increasing the number of dots by 1.5 (nearly √2) doubled the time to just over an hour:

    Manually tweaked jellyfish-high.png
    Manually tweaked jellyfish-high.png

    The first convert step turns that into the basic height map jellyfish_prep.png file:

    jellyfish-high_prep.png
    jellyfish-high_prep.png

    The next two convert steps produce two ASCII PGM files:

    • jellyfish-high_map.pgm
    • jellyfish-high_plate.pgm

    The _map file has the grayscale height map data, which is identical to the prepared PNG image:

    jellyfish-high_map
    jellyfish-high_map

    The _plate file defines the outline of the cookie cutter with a completely white interior, which is why the original cookie height map image can’t contain any pure white areas inside the outline (they’d become black here and produce islands). It seems the OpenSCAD minkowski() function runs significantly faster when it doesn’t process a whole bunch of surface detail; all we care about is the outline, so that’s all it gets:

    jellyfish-high_plate
    jellyfish-high_plate

    I originally composited the height maps on a known-size platen and worked with those dimensions, but it’s easier to just extract the actual image dimensions and feed them into the code as needed. As with all ImageMagick programs, identify has a myriad options.

    Those two lines of Bash gibberish reformat the ASCII PGM files into the ASCII DAT arrays required by OpenSCAD’s surface() function.

    The MakeSurface.scad script eats a DAT height map file and spits out a corresponding STL file. The Height parameter defines the overall Z-axis size of the slab; the maximum 255 corresponds to pure white in the image file:

    // Generate object from image height map
    // Ed Nisley - KE4ZNU
    // October 2012
    // This leaves the rectangular slab below Z=0 over the full image area
    //		... reduced in thickness by the Height/255 ratio
    
    FileName = "noname.dat";				// override with -D FileName="whatever.dat"
    Height = 255;						// overrride with -D Height=number
    DotsPerMM = 2;						// overrride with -D DotsPerMM=number
    
    ScaleXYZ = [1/DotsPerMM,1/DotsPerMM,Height/255];
    
    echo("File: ",FileName);
    echo("Height: ",Height);
    echo("Dots/mm: ",DotsPerMM);
    echo("Scale: ",ScaleXYZ);
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
      Range = floor(50 / Space);
    	for (x=[-Range:Range])
    	  for (y=[-Range:Range])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    }
    
    //- Build it
    
    ShowPegGrid();
    
    scale(ScaleXYZ)
    	surface(FileName,center=true,convexity=10);
    

    The grid defining the build platform doesn’t show up in the output file; it’s there just for manual fiddling inside the GUI. When run from the command line, OpenSCAD simply creates the output file.

    The _map.stl file has the height map data that will form the cookie press:

    jellyfish-high_map - Model
    jellyfish-high_map – Model

    The _plate.stl file is basically a digital bar cookie that will define the cutter:

    jellyfish-high_plate - Model
    jellyfish-high_plate – Model

    It’s possible to produce the cutter in one shot, starting from the DAT files, but having the two STL files makes it (barely) feasible to experiment interactively within the OpenSCAD GUI.

    This OpenSCAD program produces the cutter and press:

    // Cookie cutter from grayscale height map using Minkowski sum
    // Ed Nisley KE4ZNU - November 2012
    
    //-----------------
    // Cookie cutter files
    
    BuildPress = true;
    BuildCutter = true;
    
    fnPress = "nofile.stl";					// override with -D 'fnPress="whatever.stl"'
    fnPlate = "nofile.stl";					// override with -D 'fnPlate="whatever.stl"'
    
    ImageX = 10;						// overrride with -D ImageX=whatever
    ImageY = 10;
    
    MaxConvexity = 5;					// used for F5 previews in OpenSCAD GUI
    
    echo("Press File: ",fnPress);
    echo("Plate File: ",fnPlate);
    echo("Image X: ",ImageX," Y: ",ImageY);
    
    //- Extrusion parameters - must match reality!
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    //- Cookie cutter parameters
    
    TipHeight = IntegerMultiple(8,ThreadThick);		// cutting edge
    TipWidth = 4*ThreadWidth;
    
    WallHeight = IntegerMultiple(7,ThreadThick);		// center section
    WallWidth = 8*ThreadWidth;
    
    LipHeight = IntegerMultiple(2.0,ThreadThick);		// cutter handle
    LipWidth = IntegerMultiple(8.0,ThreadWidth);
    
    CutterGap = IntegerMultiple(2.0,ThreadWidth);		// gap between cutter and press
    
    PlateThick = IntegerMultiple(3.0,ThreadThick);		// solid plate under press relief
    
    //- Build platform
    
    PlatenX = 100;						// build platform size
    PlatenY = 120;
    PlatenZ = 120;						// max height for any object
    PlatenFuzz = 2;
    
    MaxSize = max(PlatenX,PlatenY);				// larger than any possible dimension ...
    
    ZFuzz = 0.20;						// height of numeric junk left by grayscale conversion
    ZCut = 1.20;						// thickness of block below Z=0
    
    //- Useful info
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;					// make holes and unions work correctly
    
    //-----------------
    // Import height map STL, convert to cookie press image
    
    module PressSurface() {
    
    	translate([0,0,-ZFuzz])
    		difference() {
    			import(fnPress,convexity=MaxConvexity);
    			translate([-(ImageX + PlatenFuzz)/2,-(ImageY + PlatenFuzz)/2,-ZCut])
    				cube([(ImageX + PlatenFuzz),(ImageY + PlatenFuzz),ZCut+ZFuzz],center=false);
    		}
    }
    
    //-----------------
    // Import plate STL, slice off a slab to define outline
    
    module Slab(Thick=1.0) {
    	intersection() {
    		translate([0,0,Thick/2])
    			cube([(PlatenX+PlatenFuzz),(PlatenY+PlatenFuzz),Thick],center=true);
    		translate([0,0,-1])
    			import(fnPlate,convexity=MaxConvexity);
    	}
    }
    
    //- Put peg grid on build surface
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      Range = floor(50 / Space);
    
    	for (x=[-Range:Range])
    	  for (y=[-Range:Range])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    //- Build it
    
    ShowPegGrid();
    
    if (BuildPress) {
    	echo("Building press");
    	union() {
    		minkowski() {					// fingernail ridge around press
    			Slab(LipHeight - 1);			//  ... same thickness as cutter lip
    			cylinder(r=CutterGap/2,h=1);
    		}
    		translate([0,0,(LipHeight - Protrusion)])	// solid plate under press
    			Slab(PlateThick - LipHeight + Protrusion);
    		translate([0,0,PlateThick])			// cookie press height map
    			intersection() {
    				import(fnPress,convexity=MaxConvexity);
    				translate([0,0,-Protrusion])
    					Slab(PlatenZ + Protrusion);
    			}
    
    	}
    }
    
    if (BuildCutter) {
    	echo("Building cutter");
    	difference() {
    		union() {					// stack cutter layers
    			translate([0,0,(WallHeight + LipHeight - 1)])
    				minkowski() {
    					Slab(TipHeight - 1);
    					cylinder(r=(TipWidth + CutterGap),h=1);
    				}
    			translate([0,0,LipHeight - 1])
    				minkowski() {
    					Slab(WallHeight - 1);
    					cylinder(r=(WallWidth + CutterGap),h=1);
    				}
    			minkowski() {
    				Slab(LipHeight - 1);
    				cylinder(r=(LipWidth + CutterGap),h=1);
    			}
    		}
    		minkowski() {					// punch out opening for cookie press
    			translate([0,0,-2])
    				Slab(PlatenZ);
    			cylinder(r=CutterGap,h=1);
    		}
    	}
    }
    

    The top view shows the height map press nested inside the cutter blade, but it’s not obvious they’re two separate pieces:

    jellyfish-high - Cutter and Press - top view
    jellyfish-high – Cutter and Press – top view

    The bottom view shows the 1 mm gap between the two objects:

    jellyfish-high - Cutter and Press - bottom view
    jellyfish-high – Cutter and Press – bottom view

    Now, to print the thing [Update: like that] so I can make some cookies…

    Further musings:

    • Printing separately would allow a tighter fit between the press and the cutter: an exact fit won’t work, but 2 mm may be too much.
    • A knob glued on the flat surface of the press would be nice; the fingernail ridge may get annoying.
    • PLA seems more socially acceptable than ABS for foodie projects. Frankly, I doubt that it matters, at least in this application.
    • A bigger build platform would be nice…