M4 nuts are nominally 3.2mm thick. I made the base and lid 2.4mm and sliced it with 0.4mm layers. That meant the top of the nut would be flush with a layer boundary at 5.6mm and I confirmed that the first covering layer was at 6.0mm in Skeinlayer. So I needed to pause the build before the start of the layer at Z=6.0 and insert the nuts.
I run my USB machines using Raspberry PIs and OctoPrint (so that all my machines are connected via Ethernet) and noticed a post by the author, Gina Häußge, that said OctoPrint interprets an M0 in the gcode as a pause command. The host stops sending gcode until you press the pause button to un-pause it again. I believe other hosts use
F12000.0 G1 X-9.082 Y3.907 Z6.0 F12000.0 G1 X-5.457 Y-3.937 Z6.0 F12000.0 G1 X-7.05 Y-3.803 Z6.0 F12000.0 G1 X-11.486 Y-4.991 Z6.0 F12000.0 G1 X-13.721 Y-10.229 Z6.0 F12000.0 G1 F1800.0 G1 E1.0 G1 F12000.0 M101 G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036
What we have is a sequence of non-extruding moves followed by an un-retract and the first extrusion. The moves are the result of the comb module and not really relevant if we are restarting after a pause, so I removed all but the last move and inserted my pause code:
M104 S100 G1 Z6.0 G1 X-100 Y-100 F9000 M0 G1 X10.0 Y98.0 F9000 G1 Z0.05 M109 S250 G92 E0 G1 E3 F50 G1 E-1 F1200 G1 X40.0 F4000 G1 Z6.0 F9000 G1 X-13.721 Y-10.229 Z6.0 F12000.0 G1 F1800.0 G1 E1.0 G1 F12000.0 M101 G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036
The cavity for the nut is made by subtracting a shape like this:
Here is the OpenScad code. It needs various functions from the Mendel90 source tree.
// // Smaller alternative to a wingnut // include <conf config.scad> module hanging_hole(or, ir, ofn = 0) { union() { intersection() { if(ofn) cylinder(r = or, h = 3 * layer_height, center = true, $fn = ofn); else poly_cylinder(r = or, h = 3 * layer_height, center = true); rotate([0, 0, 90]) cube([2 * or + 1, 2 * ir, 2 * layer_height], center = true); } rotate([0, 0, 90]) cube([ir * 2, ir * 2, 4 * layer_height + 4 * eta], center = true); rotate([0, 0, 22.5]) translate([0, 0, 2 * layer_height]) cylinder(r = corrected_radius(ir, 8), h = 100, $fn = 8); } } base_thickness = 2.4; lid_thickness = 2.4; function nut_knob_height(nut) = base_thickness + nut_thickness(nut) + lid_thickness; module nut_knob_stl(screw = M4_hex_screw, d = 14) { nut = screw_nut(screw); h = nut_knob_height(nut); flutes = 3; stl("nut_knob"); rotate([0, 0, -45]) difference() { cylinder(r = d / 2, h = h); // basic shape for(i = [0 : flutes - 1]) // flutes for finger grip rotate([0, 0, i * 360 / flutes + 30]) translate([d * cos(90 / flutes), 0, base_thickness]) cylinder(r = d / 2, h = 100); union() { // nut cavity difference() { translate([0, 0, base_thickness + nut_thickness(nut)]) nut_trap(screw_clearance_radius(screw), nut_radius(nut), nut_thickness(nut)); translate([0, 0, base_thickness + nut_thickness(nut)]) // remove top of nut trap cylinder(r = 20, h = 110); } translate([0, 0, base_thickness + nut_thickness(nut)]) hanging_hole(nut_radius(nut), screw_clearance_radius(screw), 6); // replace with hanging hole } } }
So this seems to be a general solution to printing holes in mid air without any support material. The only downside is that it is a bit weaker than using a membrane and drilling it out. In this case no strength above the nut was required. In general you can just make it two layers thicker.