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.

The New Hotness

  • 3D Printed Chain Mail Again

    Everybody likes chain mail, so I made a few big sheets:

    Chain Mail Sheet
    Chain Mail Sheet

    That’s a nominal 150 mm on the X axis and 200 mm on the Y, which pretty well fills the M2’s 8×10 inch platform after Slic3r lays a few skirt threads around the outside. All 192 links require a bit under four hours to print: all those short movements never let the platform get up to full speed.

    Look no further for a brutal test of platform alignment and adhesion. The platform is slightly too high in the left front corner and, no surprise, slightly too low in the right rear. The skirt thread varies from 0.15 to 0.27 around the loop.

    Hairspray works wonder to glue down all those little tiny links. They pop off the platform quite easily after it cools under 50 °C, with no need for any post-processing.

    This version of the OpenSCAD code correctly figures the number of links to fill a given width & length; the old code didn’t get it quite right.

    Coloring the links makes the whole thing easier to look at:

    Chain Mail Sheet - detail
    Chain Mail Sheet – detail

    The real world version comes out in red PLA that saturates Sony imagers:

    Chain Mail - flexed
    Chain Mail – flexed

    It really is that flexible!

    The OpenSCAD source code:

    // Chain Mail Sheet
    // For Slic3r and M2 printer
    // Ed Nisley KE4ZNU - Apr 2013
    //   Oct 2013 - larger links, better parameterization
    //   Nov 2014 - fix size calculation, add coloration
    
    Layout = "Show";			// Link Build Show
    
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 6 solid layers
    
    ThreadThick = 0.20;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.2;
    
    Protrusion = 0.1;			// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Dimensions
    
    BarThreads = 6;
    BarWidth = BarThreads * ThreadWidth;
    
    BarThick = 4 * ThreadThick;
    
    LinkSquare = IntegerMultiple(2.5*BarThreads,ThreadWidth);
    LinkHeight = 2*BarThick + 4*ThreadThick;           // bars + clearance
    
    echo(str("Link height: ",LinkHeight));
    
    LinkOutDiagonal = LinkSquare*sqrt(2) - BarWidth;
    LinkInDiagonal = LinkSquare*sqrt(2) - 2*(BarWidth/2 + BarWidth*sqrt(2));
    
    echo(str("Outside diagonal: ",LinkOutDiagonal));
    
    LinkSpacing = 0.60 * LinkOutDiagonal;		// totally empirical
    echo(str("Link spacing: ",LinkSpacing));
    
    SheetSizeX = 150;
    SheetSizeY = 200;
    
    NumLinksX = floor((SheetSizeX - LinkOutDiagonal) / LinkSpacing) + 1;
    NumLinksY = floor((SheetSizeY - LinkOutDiagonal) / LinkSpacing) + 1;
    
    echo(str("Links X: ",NumLinksX," Y: ",NumLinksY," Total: ",NumLinksX*NumLinksY));
    
    //-------
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      RangeX = floor(95 / Space);
      RangeY = floor(125 / Space);
    
    	for (x=[-RangeX:RangeX])
    	  for (y=[-RangeY:RangeY])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    //-------
    // Create basic link
    
    module Link() {
        render()
    	rotate(45)
    		difference(convexity=2) {
    			translate([0,0,LinkHeight/2]) {
    				difference(convexity=2) {
    					intersection() {		// outside shape
    						cube([LinkSquare,LinkSquare,LinkHeight],center=true);
    						rotate(45)
    							cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight],center=true);
    					}
    					intersection() {		// inside shape
    						cube([(LinkSquare - 2*BarWidth),(LinkSquare - 2*BarWidth),(LinkHeight + 2*Protrusion)],center=true);
    						rotate(45)
    							cube([LinkInDiagonal,LinkInDiagonal,(LinkHeight +2*Protrusion)],center=true);
    					}
    				}
    			}
    			for (i=[-1,1]) {				// create bars
    				translate([0,-i*(sqrt(2)*BarWidth/2),BarThick])
    					rotate(45 + 180*(i+1)/2)
    						cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight]);
    				translate([i*(sqrt(2)*BarWidth/2),0,-BarThick])
    					rotate(135 + 180*(i+1)/2)
    						cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight]);
    			}
    		}
    }
    
    //-------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Link") {
      Link();
    
    }
    
    if (Layout == "Build" || Layout == "Show") {
    	for (ix=[-(NumLinksX/2 - 0):(NumLinksX/2 - 1)])
    		for (iy=[-(NumLinksY/2 - 0):(NumLinksY/2 - 1)])
    			translate([ix*LinkSpacing + LinkSpacing/2,iy*LinkSpacing + LinkSpacing/2,0])
    				if (Layout == "Show")
    					color([0.5+(ix/NumLinksX),0.5+(iy/NumLinksY),1.0]) Link();
    				else Link();
    }