// Test of various fastener hole dimensions. /* Note that values are *not* the nominal sizes, but instead what dimension must be specified to achieve the nominal size in 3D printing. There seems to be little sensitivity to layer height, at least for holes oriented on the Z axis as these are. If sizing is critical to your project, you should print these sample pieces using the material and parameters of the project to verify the dimensions needed. Version Notes 3.4 Added hole test for 3mm filament. Moved the material name to the top face because available space there doesn't vary. 3.3 Added tie-wrap slot. 3.2 Material label generated only if there's enough room. 3.1 Corrected some instances of "AF" to "AP". 3.0 Added material caption. 2.1 First release version. TO DO: Type NY, which is oriented toward the side, doesn't flip correctly. Type TW should perhaps be in its own separate script. Provision for various types to be optionally oriented on the X axis. Add Plastite fasteners. */ // GLOBALS gVersion="3.4"; // Version of this program. // Material and nozzle used. gMaterial="Armadillo 0.2mm"; // gMaterial = "PETG 0.3mm"; // gMaterial = "Raptor 0.2mm"; // If gbFlip is true, fastener labels are alternated, left and right. If false, all labels appear on the left. gbFlip = false; // This is set in each fastener section. // The following variables should not need to be changed, unless a very much bigger fastener is specified. gDefaultBodyX = 50; // Y dimension is determined by the sum of the bands generated. gDefaultBodyZ = 10; gDefaultCLOffset = 10; bodyX = gDefaultBodyX; bodyZ = gDefaultBodyZ; gFN = 32; // default roundness. materialCaptionBandHeight = 9; // X Centerline, the distance from each edge to the holes justified to that side. CL = bodyX - gDefaultCLOffset; labelX = 2; // x for all labels on the top surface. fontName = "Liberation Sans:style=Bold"; // fontSize = 5; fontSize = 4; bigFontSize = 7; // How far to extrude the text. //fontDepthVertical = 0.9; // on vertical surfaces fontDepthVertical = 0.6; // on vertical surfaces fontDepthHorizontal = 0.9; //on horizontal surfaces // AP: Across the Points dimension of a hex or square nut. // openScad creates a hex figure inscribed within a circle, so the value is AP, not Across the Flats. // Constants defining hole types. CB = 1; // CounterBored Type, BandHeight, [Label], [D1, H, clr] CS = 2; // CounterSunk Type, BandHeight, [Label], [D1, D2, H, clr] HO = 3; // HOle Type, BandHeight, [Label], [D1] HX = 4; // HeX nut Type, BandHeight, [Label], [AP, H, clr] IN = 5; // Insert Type, BandHeight, [Label], [D1, D2, H, clr] NY = 6; // NYlon lock nut Type, BandHeight, [Label], [AP, H, Slot Depth, clr] SQ = 7; // SQuare nut Type, BandHeight, [Label], [AP, H, clr] TP = 8; // TaPered hole Type, BandHeight, [Label], [D1, D2] TW = 9; // 100mm Tie-wrap Type, Bandheight, [Label], [X, Y] // 4-40, PLA Coarse /* clr = 4.4; // Clearance diameter. bh = 12; // bandHeight gbFlip = true; a = [ ["4-40", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [3.7]], [HO, bh, ["Tapped "], [3.7]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["Hex AP ", " H "], [9.5, 3.2, clr]], [CB, bh, ["Cbore D ", " H "], [9, 5, clr]], [CS, bh, ["Csink D ", " H "], [5.5, 1.8, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [4.1, 3.9, 000, clr]], // insert length 0.135" (4.7mm) McM 93365A120 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [9.1, 5, clr]] ]; */ // 6-32, PLA Coarse /* clr = 4.4; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["6-32", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [3.7]], [HO, bh, ["Tapped "], [3.7]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["Hex AP ", " H "], [9.5, 3.2, clr]], [CB, bh, ["Cbore D ", " H "], [5.8, 3.6, clr]], [CS, bh, ["Csink D ", " H "], [6.8, 2.2, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [5.3, 5, 3.8, clr]], // insert length 0.150" (3.8mm) McM 93365A130 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [9.1, 5.0, clr]] ]; */ // 8-32 /* // verified for PETG 0.3mm, PLA 0.3mm. clr = 5.1; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["8-32", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [4.5]], [HO, bh, ["Tapped "], [4.5]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["Hex AP ", " H "], [9.5, 3.4, clr]], [CB, bh, ["Cbore D ", " H "], [7.5, 5, clr]], [CS, bh, ["Csink D ", " H "], [8.5, 4, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [6, 5.8, clr]], // insert length 0.300" (7.7mm) McM ??? [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [8.68, 6, 20, clr]] ]; */ // 10-32, PLA 0.2mm verified /* clr = 5.9; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["10-32", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [5]], [HO, bh, ["Tapped "], [5]], [HO, bh, ["Clearance "], [clr]], [HX, bh, [" AF ", "Hex H "], [11.2, 3.7, clr]], [CB, bh, [" D ", "Cbore H "], [9, 5, clr]], [CS, bh, [" D ", "Csink H "], [10.5, 5.5, clr]], [IN, 20, [" D1 ", " D2 ", "Insert H "], [7.1, 6.8, 5.7, clr]], // insert length 0.300" (7.7mm) McM ??? [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [9.9, 7.5, 20, clr]] ]; */ // 1/4-20 /* clr = 7; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["1/4-20", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [5.8]], [HO, bh, ["Tapped "], [5.8]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["AP ", "Hex H "], [13, 5.6, clr]], [CB, bh, [" D ", "Cbore H "], [10, 7, clr]], [CS, bh, [" D ", "Csink H "], [13.2, 6.6, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [9.3, 8.9, 7.7, clr]], // insert length 0.300" (7.7mm) McM 93365A160 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [11.6, 9, 20, clr]] ]; */ // M3x0.5 /* // PETG 0.3mm clr = 3.7; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["M3x0.5", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [3.3]], [HO, bh, ["Tapped "], [3.3]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["Hex AP ", " H "], [6.1, 2.8, clr]], [CB, bh, ["Cbore D ", " H "], [5.6, 4.5, clr]], [CS, bh, ["Csink D ", " H "], [6, 3, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [5.31, 5.1, 4, clr]], // insert length 3.8mm McM 94180A331 [IN, 20, ["D1 ", "D2 ", "Insert H "], [5.7, 5.3, 6.4, clr]], // insert length 6.4mm McM 94180A333 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [5.5, 4, clr]], [TW, bh, ["X ", "Y "], [1, 4]] ]; */ // M4 /* clr = 4.1; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["M4-0.7", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [3.3]], [HO, bh, ["Tapped "], [3.3]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["Hex AP ", " H "], [7, 3.5, clr]], [CB, bh, ["Cbore D ", " H "], [7.5, 4, clr]], [CS, bh, ["Csink D ", " H "], [13.2, 6.6, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [6, 5.7, 4.7, clr]], // insert length 4.7mm McM 94180A351 [IN, 20, ["D1 ", "D2 ", "Insert H "], [5.3, 6, 7.9, clr]], // insert length 7.9mm McM 94180A353 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [7, 8, clr]] ]; */ // M6x1 clr = 6.6; // Clearance diameter. bh = 12.5; // bandHeight gbFlip = true; a = [ ["M6x1", gVersion, gMaterial, gbFlip], [HO, bh, ["Selftap "], [5.8]], [HO, bh, ["Tapped "], [5.8]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["AP ", "Hex H "], [11.2, 5.2, clr]], [CB, bh, [" D ", "Cbore H "], [10, 7, clr]], [CS, bh, [" D ", "Csink H "], [13.2, 6.6, clr]], [IN, 20, ["D1 ", "D2 ", "Insert H "], [9.3, 8.9, 7.7, clr]], // insert length 0.300" (7.7mm) McM 93365A160 [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [11.6, 9, 20, clr]] ]; /* // M10x1 (fine thread) clr = 11.5; // Clearance diameter. bh = 10; // bandHeight gbFlip = true; a = [ ["M10x1", gVersion, gMaterial, gbFlip], // [HO, bh, ["Selftap "], [5.8]], // [HO, bh, ["Tapped "], [9]], [HO, bh, ["Clearance "], [clr]], [HX, bh, ["AP ", "Hex H "], [19.5, 8.5, clr]] // [CB, bh, [" D ", "Cbore H "], [10, 7, clr]], // [CS, bh, [" D ", "Csink H "], [13.2, 6.6, clr]], // [IN, 20, ["D1 ", "D2 ", "Insert H "], [9.3, 8.9, 7.7, clr]], // insert length 0.300" (7.7mm) McM 93365A160 // [NY, 20, ["Nut AF ", "Nut H ", "Slot "], [17, 9, 20, clr]] ]; */ // Test of hole fit for 3mm filament used as mechanical element. /* clr = 0; // Clearance diameter. bh = 8; // bandHeight gbFlip = false; a = [ ["3mm Hole", gVersion, gMaterial, gbFlip], [HO, bh, [" "], [3.4]], [HO, bh, [" "], [3.1]], [HO, bh, [" "], [3.3]], [HO, bh, [" "], [3.5]] ]; */ /* The bandYPosition function determines the Y value for positioning the current band by adding together the bandHeights of bands already processed. */ function bandYPosition (n, sum=0) = n==0 ? sum : bandYPosition (n-1, sum + a[n][1]); union () { // "main" { // Put material name in a band of its own. do_band ([bodyX, materialCaptionBandHeight, bodyZ]); do_captions ([gMaterial], [""], materialCaptionBandHeight, 1); } // Begin forming the main body of the object. for (i = [1:len(a)-1]) // Generate a band for each fastener specified in a. translate ([0, bandYPosition(i-1)+materialCaptionBandHeight, 0]) { gFlip = (gbFlip) ? i%2 : 1; do_fastener (a[i], gFlip); } topEdgeY = bandYPosition(len(a)-1) + materialCaptionBandHeight; echo (topEdgeY=topEdgeY); translate ([0, -bodyZ*tan(30), 0]) // Install tilted panel on front edge. difference () { intersection () { rotate (a=[-30, 0, 0]) cube ([bodyX, 12, bodyZ+20]); cube ([bodyX, bodyZ*tan(30), bodyZ+20]); } translate ([0, 6, 0]) cube ([bodyX, 10, 30]); } translate ([4, -4, 2]) // Put the thread description on the front panel. rotate ([60, 0, 0]) linear_extrude (height=fontDepthHorizontal) text (font=fontName, size=bigFontSize, a[0][0]); translate ([0, topEdgeY, 0]) // Add a cap to the top of the body. do_band ([bodyX, 3, bodyZ]); translate ([45, topEdgeY+3, 2]) // Label the back face with the dimension and version number. rotate(a=[90, 0, 180]) linear_extrude (height=fontDepthVertical) text (font=fontName, size=fontSize, str("<-- ", bodyX, " --> v", a[0][1])); } // end of "main" // MODULES module apply_mouse_ears () { // WARNING: This probably doesn't work. earD = 19; earH = 0.3; for (i = [ [[0,0,0], [0, 0, 0]], // translate, rotate [[bodyX, 0, 0], [0, 0, 90]], [[bodyX, bodyY, 0],[0, 0, 180]], [[0, bodyY, 0], [0, 0, 270]] ]) linear_extrude (height=earH) translate (i[0]) rotate (i[1]) difference () {circle(earD);square(earD);} } // end of apply_mouse_ears module do_band (d) { // d = [x, y, z] cube (d); // Make a slight ridge on the top face of the band. translate ([0, 0, d[2]]) cube ([d[0], 0.6, 0.6]); } // end of do_band module do_captions (captions, values, bandHeight, bFlip) { echo ("bFlip ", bFlip); labelXOffset = (bFlip) ? labelX : bodyX-labelX; alignText = (bFlip) ? "left" : "right"; /* The lineYPosition function determines the Y value for positioning the current caption line within the band by adding together the lineYHeights of bands already processed. */ function lineYPosition (n, sum=lineSpacing) = n==0 ? sum : lineYPosition (n-1, sum + lineSpacing + fontSize); howManyLines = len(captions); lineSpacing = max( ((bandHeight - (howManyLines*fontSize))/(howManyLines+1)), 1); for (j = [0:len(captions)-1]) translate([labelXOffset, lineYPosition(j), bodyZ]) linear_extrude (height=fontDepthHorizontal) text (font = fontName, size = fontSize, halign=alignText, str(captions[j], values[j])); } // end of do_captions module do_fastener (b, bFlip) { type = b[0]; bandHeight = b[1]; thisCL = (bFlip) ? CL : bodyX - CL; caps=b[2]; dims=b[3]; minBandHeight = 12; // Calculate Y dimension (bandHeight) // bandHeight = max (max( (len(caps)*(fontSize+1)), max(dims)), minBandHeight); if (type==HO) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=dims[0], $fn=gFN); translate([thisCL+4, bandHeight/2, bodyZ/2]) // X value only works for hole D < 8. rotate ([0, 90, 0]) cylinder (bodyZ, d=dims[0], $fn=gFN); } } // end of difference } else if (type==TP) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d1=dims[0], d2=dims[1], $fn=gFN); } } else if (type==HX) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=dims[2], $fn=gFN); translate([thisCL, bandHeight/2, bodyZ-dims[1]]) cylinder ($fn=6, h=dims[1], d=dims[0]); } } } else if (type==SQ) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=dims[2], $fn=gFN); translate([thisCL, bandHeight/2, bodyZ-dims[1]]) cylinder ($fn=4, h=dims[1], d=dims[0]); } } } else if (type==IN) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { inD1 = dims[1]; inD2 = dims[0]; inH = dims[2]; inCl = dims[3]; translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=inCl, $fn=gFN); translate([thisCL, bandHeight/2, bodyZ-dims[2]]) cylinder (h=inH, d1=inD1, d2=inD2, $fn=gFN); } } } else if (type==NY) { // This only works off the left edge, could be modified to do either. difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { af = dims[0]; h = dims[1]; // Height of nut. sl = dims[2]; sw = dims[3]; // Slot width (clearance for threaded part of screw). translate ([0, ((bandHeight-sw)/2)]) cube ([sl, sw, bodyZ]); // slot translate ([10, (bandHeight-af)/2, 0]) cube ([h, af, bodyZ]); // cross slot } } // end of difference } else if (type==CS) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { csD = dims[0]; csH = dims[1]; csclD = dims[2]; translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=csclD, $fn=gFN); translate([thisCL, bandHeight/2, bodyZ-csH]) cylinder (h=csH, d2=csD, d1=csclD, $fn=gFN); } } } else if (type==CB) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { cbD = dims[0]; cbH = dims[1]; clD= dims[2]; translate([thisCL, bandHeight/2, 0]) cylinder (bodyZ, d=clD, $fn=gFN); translate([thisCL, bandHeight/2, bodyZ-cbH]) cylinder (h=cbH, d=cbD, $fn=gFN); } } } else if (type==TW) { difference () { union () { do_band ([bodyX, bandHeight, bodyZ]); do_captions (caps, dims, bandHeight, bFlip); } union () { translate([thisCL-15, bandHeight/2, 0]) rotate ([0, 45, 0]) cube ([dims[0], dims[1], bodyZ*2]); translate([thisCL, bandHeight/2, 0]) cube ([dims[0], dims[1], bodyZ]); translate([thisCL+4, bandHeight/2, 0]) cube ([dims[1], dims[0], bodyZ]); } } } else { echo ("ERROR: unrecognized type '", type, "'"); } } // end of do_fastener