I’m teaching an introduction to OpenSCAD for Squidwrench this evening in Highland NY…
To quote from the course description:
This intensive course will bootstrap you into designing solid models of useful objects suitable for production on a 3D printer.
We won’t build anything like this, but it makes a nice showpiece:

The presentation in PDF form: Practical Solid Modeling for 3D Printing with OpenSCAD – 2013-09-25
I plan on a bunch of learning-by-doing, but, in the event the typing becomes burdensome, here are the OpenSCAD files:
A simplified version of the Dishwasher Rack Protector, minus the support structure:

// Dishwasher rack protector // Simplified version for OpenSCAD course // Ed Nisley KE4ZNU - July 2013 ThreadThick = 0.25; ThreadWidth = 0.40; Protrusion = 0.1; // make holes end cleanly //------- // Dimensions PinDia = 4.0 + 0.5; // upright pin diameter + clearance PinRadius = PinDia/2; PinOC = 3.4; // bar center to pin center PinTubeLength = 15.0; // length of upright tube along pin BarDia = 4.7 + 0.2; // horizontal bar diameter + clearance BarRadius = BarDia/2; BarTubeLength = 30.0; // length of horizontal half tube along bar TubeWall = 4*ThreadWidth; // wall thickness -- allow for fill motion TubeSides = 4 * 4; // default side count for tubes (in quadrants) $fn = TubeSides; SupportClear = 0.85; // support structure clearance fraction //------- 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); } //------- // Put it together module Protector() { difference() { union() { translate([0,PinOC,0]) rotate(180/TubeSides) cylinder(r=(PinDia + 2*TubeWall)/2,h=PinTubeLength); translate([-BarTubeLength/2,0,0]) rotate([0,90,0]) rotate(180/TubeSides) cylinder(r=(BarDia + 2*TubeWall)/2,h=BarTubeLength); } translate([0,PinOC,-Protrusion]) rotate(180/TubeSides) cylinder(r=PinRadius,h=(PinTubeLength + 2*Protrusion),$fn=TubeSides); translate([-BarTubeLength/2,0,0]) rotate([0,90,0]) rotate(180/TubeSides) translate([0,0,-Protrusion]) cylinder(r=BarRadius,h=(BarTubeLength + 2*Protrusion)); translate([0,0,-(BarRadius + TubeWall + Protrusion)/2]) cube([(BarTubeLength + 2*Protrusion), BarTubeLength, (BarRadius + TubeWall + Protrusion)],center=true); } } //------- // Build it! ShowPegGrid(); Protector();
And a bare-bones version:
// Dishwasher rack protector // Trivial version for OpenSCAD course // Ed Nisley KE4ZNU - July 2013 difference() { union() { translate([0,3.4,0]) color("lightgreen") cylinder(r=5,h=15); translate([-15.0,0,0]) rotate([0,90,0]) color("lightyellow") cylinder(r=6.0,h=30.0); } translate([0,3.4,-15.0]) cylinder(r=3.0,h=3*15.0); translate([-30.0,0,0]) rotate([0,90,0]) cylinder(r=3.0,h=2*30.0); translate([0,0,-5.0]) cube([50,50,10.0],center=true); }
A simplified version of the Sink Drain Strainer I wrote up for Digital Machinist:

// Strainer Plate // Simplified version for OpenSCAD course // Ed Nisley KE4ZNU - July 2013 Layout = "Build"; // Handle Plate Show Build Protrusion = 0.1; // make holes end cleanly PlateOD = 150.0; // strainer plate diameter PlateThick = 5.0; // .. thickness HoleOD = 6.0; // hole diameter NumRings = 4; // number of hole rings RingMinDia = 20.0; // innermost ring diameter RingStep = 30.0; // ring diameter increment HandleOD = 8.0; // handle diameter HandleLength = 15.0; // .. length HandlePegOD = HandleOD/2; // .. mounting peg HandlePegLength = 1.5; //-- Create single handle module Handle() { cylinder(r=HandleOD/2,h=HandleLength); cylinder(r=HandlePegOD/2,h=(HandleLength + HandlePegLength)); }//-- Create single ring of holes module RingHoles(RingDia,HoleDia,Thickness) { Num = floor(90/asin(HoleDia/RingDia)); // how many holes fit in ring? echo(str("Dia: ",RingDia," Holes: ",Num)); for(n=[0:(Num-1)]) { rotate([0,0,n*360/Num]) translate([RingDia/2,0,-Protrusion]) cylinder(r=HoleDia/2, h=(Thickness + 2*Protrusion)); } } //-- Create strainer plate with holes module StrainerPlate() { difference() { cylinder(r=PlateOD/2,h=PlateThick); for (RingID = [0:NumRings-1]) { RingHoles((RingMinDia + RingID*RingStep), HoleOD,PlateThick); } cylinder(r=HandlePegOD/2,h=3*PlateThick,center=true); } } //-- Build it! if (Layout == "Plate") StrainerPlate(); if (Layout == "Handle") Handle(); if (Layout == "Build") { StrainerPlate(); translate([PlateOD/2,PlateOD/2,0]) Handle(); translate([(PlateOD/2 - 2*HandleOD), PlateOD/2,0]) Handle(); } if (Layout == "Show") { color("LightYellow") StrainerPlate(); color("LightGreen") { translate([0,0,-HandleLength]) Handle(); translate([0,0,(PlateThick + HandleLength)]) rotate([180,0,0]) Handle(); } }
And a bare-bones version, minus the handles:
Protrusion = 0.1; PlateOD = 150.0; PlateThick = 5.0; HoleOD = 6.0; NumRings = 4; RingMinDia = 20.0; RingStep = 30.0; module RingHoles(RingDia,HoleDia,Thickness) { Num = floor(90/asin(HoleDia/RingDia)); echo("Dia: ",RingDia," holes: ",Num); for(n=[0:(Num-1)]) { rotate([0,0,n*360/Num]) translate([RingDia/2,0,-Protrusion]) cylinder(r=HoleDia/2, h=(Thickness + 2*Protrusion)); } } difference() { cylinder(r=PlateOD/2,h=PlateThick); for (RingID = [0:NumRings-1]) { RingHoles((RingMinDia + RingID*RingStep), HoleOD,PlateThick); } }
[Update: The talk went well and took a bit under three hours, although by mutual agreement we didn’t fire up the M2 at the end. I’ll work on a short talk about Design for Printability and we’ll run that with a separate printing session. A good time was had by all!]
holy smoke! best concise tutorial i have ever seen for openscad! i thought i was pretty good, but you managed to teach me even more! i feel like i just took your course. where do i send the check?
Imagine what it’ll be like with a few hours of standup comedy!
Dang, I knew I forgot a slide… Paypal should work fine, though. [grin]
What are the chances that the audio will be recorded? It would be hyper-groovy to be able to listen to the presentation while flipping through the pages.
Over the years various camera fanatics have tried that, but I’m apparently non-recordable; either I speak badly or Something Just Doesn’t Work.
On the other hand, if all those glitzy singers can lip-sync while gyrating vigorously, I ought to be able stand-and-deliver into a mic, right? Youtube, here I come … [wince]
I may be reading too quickly but on page 48 a definition of ‘manifold’ may be useful if the pdf is used as a stand-alone rather than accompanying a verbal discussion.
I’ll be telling a _lot_ of people about this because it’s extremely useful.
That’s where I say “Aaaaand what’s this ‘manifold’ thing? Hold that thought; you’ll see some examples in a bit.” Another couple dozen clicks, we get to “Geometric Requirements” on page 84, and then the examples appear.
If I can remember to say it, of course. I’m hoping for a straight man to ask questions to keep me on track…
This is a very useful PDF that covers a lot of the details not generally covered elsewhere. Thanks.
You draw your own supports? Have you found the slic3r automated supports not suitable for your needs?
Also, I had a question about drawing thin walled objects. I’m trying to get a thin wall that is, say, 5 extrusion widths across exactly to convince slic3r not to insert a zig-zag infill, which slows down the print considerably. I’ve tried playing with various dimensions, but it continues to insist on adding that infill. Do you have any idea if it is possible? The thin walls are only part of a larger object, so I can’t do something global like turning off infill.
Mostly, the things I build require so little support that it’s easier to just add a few lines that build exactly what’s needed. That wouldn’t work with the much larger support structures other folks need for their objects, though, so it’s more happenstance than anything significant.
I think you can get complete parallel “infill” only when the total number of perimeters on both sides adds up to the exact width of the wall, so there’s no actual infill required. Thinner walls produce gaps where the perimeters can’t fit and thicker walls require infill between the perimeters, so it’s a delicate balance.
In fact, if the walls aren’t exactly straight, then the parallel perimeter threads might not fit at the bends, so you get weird little holes and gaps.
I spend a lot of time having gcode.ws tell me that what I’m trying to do doesn’t work…
Thanks. You were right, I had to lower the perimeter settings to get it to work. gcode.ws is super handy.
Good!
The trouble with gcode.ws is that you (well, I) can spend way too much time futzing with the details. [sigh]