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!]
















