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: Machine Shop

Mechanical widgetry

  • Automated Cookie Cutters: OpenSCAD surface() Function

    While pondering the notion of making cookie cutters, it occurred to me that the process could be automated: a grayscale height map image of the cookie should be enough to define the geometry. The existing height map solutions (like William Adams’s fine work) seem entirely too heavyweight, what with custom Windows or Java programs and suchlike. Some doodling indicates that a simpler solution may suffice for my simple needs, although the devil always hides in the details.

    The overall problem with a cookie press involves producing a non-rectangular solid with a bumpy upper surface corresponding to the grayscale values of an image: dark pixels = low points of the surface, light pixels = peaks. The image size controls the XY extent of the solid and the pixel values control the Z, with some known value (likely either black or white) acting as a mask around the perimeter. Given such a solid, you can then wrap a cutter blade and handle around the outline, much as I did for the Tux cutter.

    OpenSCAD has a lightly documented surface() function that reads an ASCII text file consisting of an array of numeric values. Each array element defines a 1 × 1 unit square of the resulting 3D object; the example in the doc shows a 10 x 10 array producing a 10 x 10 unit object. Each numeric value sets the height of the surface at the center of the square.

    This array, slightly modified from the one in the doc, shows how that works:

    9 9 8 7 6 5 5 5 5 1
    9 9 7 6 6 4 3 2 1 0
    8 7 6 6 4 3 2 1 0 0
    7 6 6 4 3 2 1 0 0 0
    6 6 4 3 2 1 1 0 0 0
    6 6 3 2 1 1 1 0 0 0
    6 6 2 1 1 1 9 9 9 0
    6 6 1 0 0 0 9 8 9 0
    3 1 0 0 0 0 9 9 9 0
    9 8 7 6 5 4 3 2 1 0
    

    Feeding that into this OpenSCAD program:

    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);
    
    }
    
    ShowPegGrid();
    surface("/tmp/test.dat",center=true,convexity=10);
    

    Produces this object, surrounded by a few non-printing 1 unit alignment cubes on the Z=0 plane for scale:

    Example Object
    Example Object

    Some things to note:

    • The text array looks like it builds downward from the upper left, but the solid model builds from the origin toward the +X and +Y directions, with the first line of the array appearing along Y=0. This reverses the object along the Y axis: the first line of the array is the front side of the object.
    • The “center=true” option centers the object in XY around the Z axis, with a 1 unit thick slab below the entire array; the top surface of that slab (at Z=0) represents the level corresponding to 0 elements in the array.
    • Each array element becomes a square one unit on a side; the RepRap software chain regards units as millimeters
    • The center point of each element’s square is at the nominal height
    • The Z coordinate of the edges of those squares linearly interpolate between adjacent centers
    • Vertical edges become slanted triangular facets

    Remember that STL files contain a triangular tessellation (or whatever you call it in 3D) of the object surface, which means rectangles aren’t natural. The edge interpolation make the whole thing work, because an array of pure square pillars probably won’t be a 2-manifold object: some pillars would share only a common vertical edge. The interpolation does, however, produce a bazillion facets atop the object.

    So the problem reduces to generating such an array from a grayscale image, for which some ImageMagick and Bash-fu should suffice, and then manipulating it into a model that will produce a cookie press and cutter. More on that tomorrow…

    [Update: image file, height map file, solid modeling, printing]

  • Whirlpool Refrigerator: Replacement Freezer Shelf Bracket

    Somehow, one of the brackets that supports the small shelf inside the freezer of our Whirlpool refrigerator went missing over the many intervening years and repairs; we never used that shelf and stashed it in a closet almost immediately after getting the refrigerator, so not having the bracket didn’t matter. We recently set up a chest freezer in the basement for all the garden veggies that used to fill all the space available and decided to (re-)install the shelf, which meant we needed a bracket.

    It’s impossible to figure out exactly which “shelf stud” in that list would solve the problem, but one of the upper-left pair in that set seems to be about right. On the other paw, I don’t need all the other brackets and doodads and screws, sooo… I can probably make one.

    Start with a few measurements, then doodle up the general idea:

    Refrigerator Bracket - dimension doodle
    Refrigerator Bracket – dimension doodlet’s time to conjure up a solid model:

    A bit of OpenSCAD solid modeling:

    Refrigerator Bracket Pin - solid model
    Refrigerator Bracket Pin – solid model

    The yellow bars support the ceiling of that big dovetail, which would otherwise sag badly. The OEM bracket has nicely rounded corners on the base and a bit of an overall radius at the end of the post; this was pretty close and easier to do.

    Now it’s time to Fire the Thing-O-Matic…

    I switched from blue to white filament during the print, because I figured I’d print another one after I got the sizes right, so it emerged with an attractive blue base:

    Bracket on build platform
    Bracket on build platform

    A better view of the support structure:

    Bracket - dovetail support structure
    Bracket – dovetail support structure

    Two of the bars snapped off cleanly, but the third required a bit of scraping:

    Bracket - support scars
    Bracket – support scars

    Somewhat to my surprise, Prototype 001 slipped snugly over the matching dovetail on the freezer wall, with about the same firm fit as the OEM brackets:

    Refrigerator bracket - installed
    Refrigerator bracket – installed

    And it works perfectly, apart from that attractive blue base that I suppose we’ll get used to after a while:

    Refrigerator bracket - in use
    Refrigerator bracket – in use

    I have no idea whether ABS is freezer-rated. It seems strong enough and hasn’t broken yet, so we’ll declare victory and keep the source code on tap.

    The whole project represents about an hour of hammering out OpenSCAD code for the solid model and another hour of printing, which means I’d be better off to just buy the parts kit and throw away the unused bits. Right?

    I loves me my Thing-O-Matic…

    The OpenSCAD source code:

    // Shelf support bracket
    // for Whirlpool freezer
    // Ed Nisley KE4ZNU Octoboer 2012
    
    //include </mnt/bulkdata/Project Files/Thing-O-Matic/MCAD/units.scad>
    //include </mnt/bulkdata/Project Files/Thing-O-Matic/Useful Sizes.scad>
    
    // Layout options
    
    Layout = "Build";
     // Overall layout: Show Build
     // Printing plates: Build
     // Parts: Post Base Keystone Support
    
    ShowGap = 10; // spacing between parts in Show layout
    
    //- Extrusion parameters must match reality!
    // Print with +1 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.2;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1; // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    PostLength = 17.5;
    PostWidth = 8.2;
    PostHeight = 14.4;
    PostOffset = 4.4;
    
    PostTopWidth = 4.0;
    PostTopHeight = 4.2;
    
    BaseLength = 22.6;
    BaseWidth = 20.8;
    BaseThick = 5.0;
    
    KeystoneOffset = 3.4;
    KeyThick = IntegerMultiple(3.0,ThreadThick);
    KeyBase = 2.5;
    SlotOpening = 11.63;
    //----------------------
    // 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);
    }
    
    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);
    
    }
    
    //-------------------
    // Component parts
    
    //--- Post
    
    module Post(h=PostLength) {
    
    PostTopAngle = atan((PostWidth - PostTopWidth)/(2*PostTopHeight));
    PostBottomRadius = PostWidth/2;
    
    PostPolyTop = [PostTopWidth/2,0];
    PostPolyBottom = [PostWidth/2,-PostTopHeight];
    
    hull() {
     linear_extrude(height=h) {
     polygon(points=[
     [-PostPolyTop[0],PostPolyTop[1]],
     PostPolyTop,
     PostPolyBottom,
     [-PostPolyBottom[0],PostPolyBottom[1]]
     ]);
     translate([0,-PostHeight + PostBottomRadius])
     circle(r=PostBottomRadius,$fn=4*8);
     }
     }
    }
    
    //--- Base block
    
    module Base() {
    
     linear_extrude(height=BaseThick)
     square([BaseWidth,BaseLength],center=true);
    
    }
    
    //-- Keystone slot
    
    module Keystone() {
    
    Tx = SlotOpening/2 + KeyBase;
    
     rotate([90,0,0])
     linear_extrude(height=BaseLength)
     polygon(points=[
     [-Tx,KeyThick],
     [ Tx,KeyThick],
     [ SlotOpening/2,0],
     [ SlotOpening/2,-Protrusion],
     [-SlotOpening/2,-Protrusion],
     [-SlotOpening/2,0]
     ]);
    }
    
    //--- Support structure
    
    module Support() {
    
    SupportLength = BaseLength - 2*ThreadWidth;
    SupportWidth = 2*ThreadWidth;
    SupportHeight = KeyThick - Protrusion;
    
    SupportPeriod = 7.0*ThreadWidth;
    
    SupportBeams = 3; // must be odd -- choose to fit
    SIndex = floor((SupportBeams - 1)/2);
    
    for (i=[-SIndex:SIndex])
     translate([(i*SupportPeriod - SupportWidth/2),-(SupportLength + ThreadWidth),0])
     color("Yellow") cube([SupportWidth,SupportLength,SupportHeight]);
    }
    
    //--- The whole thing!
    
    module Bracket(ShowSupp) {
    
     union() {
     difference() {
     Base();
     translate([0,(BaseLength/2 - KeystoneOffset),0])
     Keystone();
     }
     translate([0,(BaseLength/2 - PostOffset),BaseThick - Protrusion])
     Post(h=(PostLength + Protrusion));
     }
    
     if (ShowSupp)
     translate([0,(BaseLength/2 - KeystoneOffset),0])
     Support();
    
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Show")
     Bracket(false);
    
    if (Layout == "Build")
     Bracket(true);
    
    if (Layout == "Post")
     Post();
    
    if (Layout == "Base")
     Base();
    
    if (Layout == "Keystone")
     Keystone();
    
    if (Layout == "Support") {
     Support();
    % Keystone();
    }
    
  • Recommended Tool: Bosch GLR225 Laser Rangefinder

    I’ve been doing some amateur surveying in preparation for the long-awaited driveway paving project, just to see where the property boundaries might be, and this Bosch GLR225 laser rangefinder makes it wonderfully easy to measure distances:

    Bosch GLR225 Laser Rangefinder
    Bosch GLR225 Laser Rangefinder

    It’s good up to 230 feet = 70 meters, which means you can measure a sizable chunk of property in one shot. It reads down to 2 inches with 1/16 inch accuracy / resolution (call it 50 mm and 1.5 mm), so one could use it for setups in the shop. It can solve right triangles, which means you can measure distances with an obstruction in the middle, and has a few other tricks. Other rangefinders evidently have more tricks, but I favor writing direct measurements on paper and making computations based those values, rather than using mysterious results direct from the field that can’t be easily verified at the desk.

    I tried measuring the nominal 212 foot distance to the Hudson River from the center of the Walkway, but it reported an error. Most likely, specular reflections from water don’t work well, at least not at that distance.

    You can buy retroreflective targets, but the Basement Laboratory Warehouse Wing disgorged what looks like roadside border markers, pre-bent into a useful shape:

    Laser targets - normal
    Laser targets – normal

    Seen by reflected light, they’re much more impressive:

    Laser targets - flash
    Laser targets – flash

    They came with the house, so I don’t know their provenance. What I do know is that I can’t hold the rangefinder steady enough to keep the spot on the target at much more than 100 feet. If I get around to doing much more surveying, I must conjure up a tripod mount; the base has a 1/4-20 socket in an awkward location and can measure relative to the screw centerline. Perhaps a rifle stock with a spotting scope would be handy, too, although I’d certainly acquire another black spot on my record.

    If you were going to use it in the shop, you’d want a rotating pivot aligned at the intersection of the tripod socket and sensor port to get a known center point.

    You can get one on eBay at a substantial discount, of course…

  • Inkjet Colors vs. Time

    Back in December 2007 I printed four copies of a picture on various papers with the Canon S630 and hung them on a floor joist over my workbench, directly below a fluorescent shop light. Having just hung those screwdrivers where the pictures used to be, it’s time to see what’s happened.

    The pictures, scanned on an HP C7670A (aka Scanjet 6300C) against the neutral gray of the ADF platen:

    Inkjet Colors vs. Paper vs. Time
    Inkjet Colors vs. Paper vs. Time

    The papers, clockwise from lower left:

    • Glossy
    • Matte
    • Plain
    • Inkjet

    While the scanner isn’t renown for its color fidelity, the overall results look about right; the platen really is that shade of gray and the upper-right picture has a sickly green hue.

    The faded edges along the right side of the left-hand image show where the adjacent sheet overlapped: the colors didn’t fade nearly as much. The small rectangles on the lower left corners of the right-hand images show where I put clothes pins to keep the sheets from curling.

    All of the images have a blue overtone; the magenta dye fades out with exposure to UV from the fluorescent fixture.

    As you’d expect, the glossy paper looks best, with very crisp detail. The inkjet paper is next, followed by the matte, and the plain paper in the upper right obviously doesn’t support the ink well at all.

    Of course, after five years I no longer have any of those papers and am using entirely different ink

    To show that the scanner really does matter, here’s the same set of images from a Canon LiDE 30:

    Inkjet Colors - Canon LiDE30
    Inkjet Colors – Canon LiDE30

    In both cases. that’s without any color correction / gamma compensation / whatever. I should fish out my scanner calibration targets and go through the whole color calibration dance again; with any luck, the Linux color management infrastructure will be less inadequate by now.

    IIRC, we were doing public safety radio at an event at the Dutchess County Fairgrounds with the Mt Beacon Amateur Radio Club. This was before the Diamond antenna mounts disintegrated, too.

    Memo to Self: If you love it, don’t expose it to UV.

  • Longboard Electronics Case: Now With Mouse Ears

    Our Larval Engineer may have a commission to fit her Speed-Sensing Ground Effect Lighting controller to another longboard. To that end, the case now sports mouse ears to spread the force from the cooling ABS over more of the Kapton tape, in the hope the plastic won’t pull the tape off the aluminum build platform:

    Longboard Case Solid Model - mouse ears
    Longboard Case Solid Model – mouse ears

    That view shows the bottom slice that will hold the battery, but the ears appear on all three layers.

    The OpenSCAD source code is now up on Github, which should make it easier to update & share.

  • Sony DSC-H5: Shutter Button Rebuild

    Having extracted the shutter button from the camera body, it’s easy to see why the plunger causes problems:

    DSC-H5 Shutter Button - bottom view
    DSC-H5 Shutter Button – bottom view

    The plunger is basically a pin that eventually deforms the top of the switch membrane. Tee’s DSC-H1 had an exposed switch, although this picture shows that membrane was still in reasonably good condition:

    Shutter Switch Closeup
    Shutter Switch Closeup

    My DSC-H5 has a thin black protective disk atop the switch, but the disk wasn’t particularly protective and developed a dimple that held the contacts closed even with the shutter button released (which is why I’m tearing the camera apart in the first place):

    DSC-H5 Shutter Switch - dimpled protector
    DSC-H5 Shutter Switch – dimpled protector

    The C-clip around the plunger is now plastic, rather than metal, making it less likely to erode the thin plastic shaft. Pulling the clip off while holding the button down releases all the parts:

    DSC-H5 Shutter Button - components
    DSC-H5 Shutter Button – components

    A few measurements from an intact shutter button, which may come in handy if you don’t have one:

    DSC-H5 Shutter Button - plunger measurements
    DSC-H5 Shutter Button – plunger measurements

    Mount three-jaw chuck on the Sherline table, laser-align chuck to spindle, grab shutter button by its shaft in a Jacobs chuck, grab shutter button in three-jaw chuck, release from Jacobs chuck:

    DSC-H5 Shutter Button - in Sherline chuck
    DSC-H5 Shutter Button – in Sherline chuck

    That’s not particularly precise, but it’s close enough for this purpose. I used manual jogging while testing the fit with a paper shim until all three jaws had the same clearance, then tightened the jaws.

    I nicked the plunger at its base with a flush-cutting diagonal cutter, snapped off the plunger, and drilled a #56 hole through the button:

    DSC-H5 Shutter Button - cap drilling
    DSC-H5 Shutter Button – cap drilling

    For reasons that made sense at the time, I repaired Tee’s DSC-H1 with a 1-72 brass screw. This time, I used an 0-80 (which I learned as ought-eighty, if you’re wondering about the indefinite article) screw and nut, because the screw head fit neatly into the bezel recess and I had a better idea of how to smooth out the threads.

    This being plastic, I used the chuck to hold the tap in the proper alignment, then turned the tap through by finger pressure. This trial fit showed it worked:

    DSC-H5 Shutter Button - 0-80 screw
    DSC-H5 Shutter Button – 0-80 screw

    Milling the nut down to a 2.8 mm cylinder required the usual manual CNC, with repeated iterations of this chunk of code in the MDI panel:

    #<r>=[[2.8+3.11]/2]
    g1 x[-#<r>] f50
    g0 z0
    g2 i#<r> f100
    g0 z4
    

    The 2.8 in the first line is the current OD and the 3.11 is the measured diameter of the 1/8 inch end mill. I started from a 5.0 mm OD that just kissed the nut, then worked inward by 0.2 mm at a time for very shallow 0.1 mm cuts:

    DSC-H5 Shutter Button - 0-80 nut milling
    DSC-H5 Shutter Button – 0-80 nut milling

    The alert reader will notice, as did I, that the head isn’t quite centered: the cut trimmed the left side and left the right untouched, with an offset far larger than the centering error. As nearly as I can tell, the heads of those screws aren’t exactly centered on their threaded shafts, but the final result fixed that… and the overall error is a few tenths of a millimeter = maybe 10 mils, tops, so it’s no big deal.

    With all that in hand, I applied a very very thin layer of epoxy to fill the threads below the now-cylindrical nut and convert the screw into a rod:

    DSC-H5 Shutter Button - 0-80 plunger
    DSC-H5 Shutter Button – 0-80 plunger

    My original intent was to use the screw head as-is atop the PET shield (per those instructions) on the switch membrane, but after reassembling enough of the camera to try that out, it didn’t work correctly: the half-pressed switch didn’t activate reliably before the full-pressed switch tripped.

    The PET shield I used came from the side of a 1 liter soda bottle and turned out to be 0.27 mm thick:

    DSC-H5 Shutter Switch - cover removed
    DSC-H5 Shutter Switch – cover removed

    I think the PET shield would work with the original plunger shape concentrating the force in the middle of the shield, but the nice flat screw head spreads the force out over a wider area. As a result, the force required to close the half-pressed switch contacts was roughly the same as that required to close the full-pressed contacts; remember the nub on the bottom of the black plastic tray concentrates the force in the middle of the full-pressed switch membrane.

    So I removed the PET shield, added a dot of epoxy to fill the screw slot and compensate for the missing shield thickness, then filed a flat to make a nice pad:

    DSC-H5 Shutter Button - epoxy on plunger
    DSC-H5 Shutter Button – epoxy on plunger

    Reassembling the camera once more showed it worked exactly the way it should. In fact, the button seems more stable than the OEM version, probably because the slightly enlarged plunger shaft fits better in the bezel. Too bad about those scuffs on that nice shiny button dome, though:

    DSC-H5 - repaired shutter button
    DSC-H5 – repaired shutter button

    Tossing the leftover parts seems entirely appropriate…

    Sony DSC-H5 Shutter Button - leftovers
    Sony DSC-H5 Shutter Button – leftovers
  • Sony DSC-H5: Disassembly

    The half-pressed shutter switch position on my Sony DSC-H5 recently stopped working, which seems to be one of two common failures. The other, a broken switch shaft, happened to Tee’s camera, as described there, and I figured I should preemptively fix that while I was inside my camera.

    This being a common failure, several folks have described how to dismantle the camera; I followed that guide’s English version.

    The DSC-H5 differs slightly from that description. After I got the thing apart, it became obvious that there’s no need to remove the LCD panel, the main control board, and most of the ribbon cables if you have a Philips #0 or #00 screwdriver with a very thin shaft. There’s no way to describe this operation, so take it apart his way, then you’ll see what I mean: the guts can come out as one big lump.

    In any event, all the camera controls eventually emerge from the body:

    DSC-H5 Control Assembly
    DSC-H5 Control Assembly

    Looking back into the camera body reveals the bottom of the shutter button, captured by a static discharge contact and the gray plastic frame of the Focus / Break button caps:

    DSC-H5 Shutter Button - interior view
    DSC-H5 Shutter Button – interior view

    Removing the pushbutton frame and pushing the left button bezel latch with a small flat-blade screwdriver extracts the shutter button; it falls out of the inverted body. This is one of the few intact DSC-H[1-9] shutter buttons you’ll ever see:

    DSC-H5 Shutter Button - bottom view
    DSC-H5 Shutter Button – bottom view

    Those rectangular protrusions lock into the slots in the black plastic cap that appears almost silver in this front view that shows the dimple in the switch membrane:

    DSC-H5 Shutter Button Switch - depressed surface
    DSC-H5 Shutter Button Switch – depressed surface

    You must remove the cap to release the flex PCB with the shutter switches. Two heat-staked pins retain the cap; a scalpel neatly slices off the melted plastic:

    DSC-H5 Shutter Switch - cover removed
    DSC-H5 Shutter Switch – cover removed

    Nota bene: the DSC-H1 button bezel I repaired earlier does not have features that lock into the cap over the switch assembly, which means you can remove and replace it without disassembling the camera. You cannot remove or install the DSC-H5 button without taking the camera apart. I suppose this counts as a continuous product improvement, but …

    The shutter switch has two parts:

    • The full-press switch that takes the picture (the white dot on the blue flex, shown above)
    • The half-press switch that triggers the focus & exposure is in a black plastic tray (seen edge-on above the white dot)

    The bottom of the half-press tray has a small nub that activates the full-press switch, so the force required to activate the half-press switch must be considerably less than the force that activates the full-press switch. This turns out to be a critical part of the repair…

    A closeup of the half-press switch with the protective cover sheet (the “damn confetti” of the disassembly instruction) and the dimple that held the contacts together with the button released:

    DSC-H5 Shutter Switch - dimpled protector
    DSC-H5 Shutter Switch – dimpled protector

    A closeup of the switch through a snippet of PET plastic shows the switch membrane itself is in fine shape:

    DSC-H5 Shutter Switch - cover removed
    DSC-H5 Shutter Switch – cover removed

    However, the new plastic shield did not work out well, for reasons having to do with the new button plunger. That’s the next step: rebuild the plunger…