summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--.gitignore2
-rw-r--r--Makefile12
-rw-r--r--fanduct-3jets.scad2
-rw-r--r--fanduct-circular.scad2
-rw-r--r--fanduct.scad241
-rw-r--r--snapper.scad27
6 files changed, 286 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..edc57ed
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/Makefile.local
+*.stl
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3afaa64
--- a/dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+-include Makefile.local
+
+OPENSCAD_APP?=/Applications/OpenSCAD.app
+OPENSCAD_BIN?=${OPENSCAD_APP}/Contents/MacOS/OpenSCAD
+
+default: fanduct-circular.stl fanduct-3jets.stl
+
+fanduct-%.stl: fanduct-%.scad fanduct.scad
+
+
+%.stl: %.scad
+ ${OPENSCAD_BIN} ${OPENSCAD_FLAGS} -o "$@" "$<"
diff --git a/fanduct-3jets.scad b/fanduct-3jets.scad
new file mode 100644
index 0000000..cd88ab0
--- a/dev/null
+++ b/fanduct-3jets.scad
@@ -0,0 +1,2 @@
+use <fanduct.scad>;
+fanduct(type="3jets");
diff --git a/fanduct-circular.scad b/fanduct-circular.scad
new file mode 100644
index 0000000..caaf6e4
--- a/dev/null
+++ b/fanduct-circular.scad
@@ -0,0 +1,2 @@
+use <fanduct.scad>;
+fanduct(type="circular");
diff --git a/fanduct.scad b/fanduct.scad
new file mode 100644
index 0000000..d711166
--- a/dev/null
+++ b/fanduct.scad
@@ -0,0 +1,241 @@
+use <snapper.scad>;
+extrusion_width=.5; layer_height=.2; // print parameters
+
+epsilon=.005; // for finer cuts
+
+heater_w = 16; // heatblock width
+heater_l = 20; // heatblock length
+nozzle_offset=4.5; // nozzle offset from the edge of heatblock
+
+fanduct_elevation = 3; // fanduct elevation above nozzle tip
+fanduct_h = 6; // inner height of the duct
+fanduct_w = 6; // inner width of the duct
+fanduct_shell=1.2; // shell thickness
+fanduct_ir = sqrt(pow(heater_w/2,2)+pow(heater_l-nozzle_offset,2))+5; // inner radius
+
+jet_angle = 60; // angular width of the jet
+
+inlet_w = 12.5; // inlet width
+inlet_h = 17; // inlet height
+inlet_l = 7; // inlet length of protrusion (or depth of intrusion:))
+inlet_away = 15; // how far away inlet is
+
+hotend_clearance = 12;
+
+snapper_d = 8; snapper_overlap=0.2; // snip snap
+
+smooth_f = 120;
+
+type="3jets"; // "3jets" ; // circular|3jets
+
+
+module fanduct(type=type) {
+
+ // *** duct is all around!
+ module duct(what) {
+ if(what=="in") {
+ rotate_extrude($fn=smooth_f)
+ translate([fanduct_ir,0])
+ square([fanduct_w+2*fanduct_shell,fanduct_h+2*fanduct_shell]);
+ }else if(what=="out") {
+ rotate_extrude($fn=smooth_f)
+ translate([fanduct_ir+fanduct_shell,fanduct_shell])
+ union() {
+ square([fanduct_w,fanduct_h/2]);
+ translate([fanduct_w/2,fanduct_h-fanduct_w/2])
+ rotate([0,0,90]) circle(d=fanduct_w,$fn=36);
+ }
+ }
+ }
+
+ // *** bumps for easier position adjustments in line with hotend
+ module marks(what) {
+ if(what=="in") {
+ for(y=[-1,1]) translate([0,y*(fanduct_ir+fanduct_shell+fanduct_w/2),fanduct_shell*2+fanduct_h])
+ rotate([90,0,0]) {
+ cylinder(r=fanduct_shell,h=fanduct_w,center=true,$fn=30);
+ for(z=[-1,1]) translate([0,0,z*fanduct_w/2])
+ sphere(r=fanduct_shell,$fn=30);
+ }
+ }
+ }
+
+ // *** output
+ module output(what,type=type) {
+ module guideline(xyxy) {
+ module pin(xy) {
+ translate([xy[0],xy[1],0])
+ cylinder(d=2*extrusion_width,h=2*fanduct_shell+inlet_h,$fn=6);
+ }
+ xyxyxy=concat(xyxy,[[0,0]]);
+ for(i=[0:1:len(xyxyxy)-2])
+ hull() for(j=[i,i+1]) pin(xyxyxy[j]);
+ }
+
+ module circus(what) {
+ if(what=="in") {
+ difference() {
+ rotate_extrude($fn=smooth_f)
+ polygon([
+ [0,-fanduct_elevation],
+ [fanduct_ir+fanduct_shell,fanduct_shell+fanduct_h/2],
+ [fanduct_ir+fanduct_shell,0],
+ [0,-fanduct_elevation-.1]]);
+ translate([0,0,-1])
+ cylinder(r=hotend_clearance,h=fanduct_h+2*fanduct_shell+2,$fn=smooth_f);
+ mirror([0,0,1])
+ translate([0,0,-epsilon])
+ cylinder(r=fanduct_ir+fanduct_shell+1,h=fanduct_elevation+.1+2);
+ }
+ }else if(what=="out") {
+ difference() {
+ rotate_extrude($fn=smooth_f)
+ polygon([
+ [0,-fanduct_elevation],
+ [fanduct_ir+fanduct_shell+1,fanduct_h/2],
+ [fanduct_ir+fanduct_shell+1,fanduct_shell],
+ [0,-fanduct_elevation-.1]]);
+ circus("airguides");
+ }
+ }else if(what=="airguides") {
+ inr = fanduct_ir+fanduct_shell; our = inr+fanduct_w;
+ union() {
+ for(my=[0,1]) mirror([0,my,0]) {
+ guideline([
+ [-our,inlet_w/6],
+ [-inr*sin(60),inr*cos(60)]
+ ]);
+ a0=30; as=15; a1=180;
+ for(a=[a0+as:as:a1]) {
+ f = as/(a1-a+as);
+ rotate([0,0,a]) guideline([[-inr-fanduct_w*f,0]]);
+ }
+ guideline([
+ [-our+fanduct_w*cos(30)*3/4,fanduct_w*sin(30)*3/4],
+ [-inr*cos(10),inr*sin(10)]
+ ]);
+ }
+ }/*union*/
+ }/*airguides*/
+ }
+
+ module jets(what) {
+ od = fanduct_h/2+fanduct_shell;
+ difference() {
+ for(a=[0:120:359]) rotate([0,0,a]) {
+ if(what=="in") {
+ hull() {
+ translate([fanduct_ir+od/2,0,od/2])
+ rotate([90,0,0])
+ cylinder(d=od,h=2*(fanduct_ir+fanduct_shell+fanduct_w/2)*sin(jet_angle/2)-3,center=true,$fn=36);
+ translate([0,0,-fanduct_elevation]) sphere(r=.5);
+ }
+ }else if(what=="out") {
+ hull() {
+ translate([fanduct_ir+od/2,0,od/2])
+ rotate([90,0,0])
+ cylinder(d=od-2*fanduct_shell,h=2*(fanduct_ir+fanduct_shell+fanduct_w/2)*sin(jet_angle/2)-3-2*fanduct_shell,center=true);
+ translate([0,0,-fanduct_elevation]) sphere(r=.2);
+ }
+
+ type="3jets";
+ }
+ }
+ if(what=="in") {
+ translate([0,0,-fanduct_elevation-2+epsilon])
+ cylinder(r=fanduct_ir+fanduct_shell*2+fanduct_w+1,h=fanduct_elevation+2);
+ translate([0,0,-hotend_clearance])
+ rotate([0,0,30])
+ cylinder(r1=hotend_clearance*2,r2=0,h=hotend_clearance*2,$fn=6);
+ }
+ }
+ }
+
+ if(type=="circular") circus(what);
+ else if(type=="3jets") jets(what);
+ }
+
+ // *** air intake
+ module intake(what) {
+ module placeit() {
+ translate([-fanduct_ir-2*fanduct_shell-fanduct_w-inlet_away,0,fanduct_shell])
+ rotate([0,-90,0])
+ children();
+ }
+ if(what=="in") {
+ placeit() translate([0,-inlet_w/2,0]) {
+ cube(size=[inlet_h,inlet_w,inlet_l+fanduct_shell]);
+ // supports
+ for(i=[-1,0,1])
+ translate([-fanduct_shell,
+ (i+1)*(inlet_w-extrusion_width)/2,
+ -inlet_away-fanduct_w/2])
+ cube(size=[fanduct_shell,
+ extrusion_width,
+ inlet_l+fanduct_shell+inlet_away+fanduct_w/2]);
+ }
+ hull() {
+ placeit() translate([-fanduct_shell,-inlet_w/2-fanduct_shell/2,0])
+ cube(size=[inlet_h+fanduct_shell,inlet_w+fanduct_shell,fanduct_shell]);
+ translate([-fanduct_ir-fanduct_shell-fanduct_w/2,0,0])
+ translate([0,-inlet_w/2-fanduct_shell/2,0])
+ cube(size=[1,inlet_w+fanduct_shell,fanduct_shell*2+fanduct_h]);
+ }
+ }else if(what=="out") {
+ placeit() translate([fanduct_shell,-inlet_w/2+fanduct_shell,0])
+ cube(size=[inlet_h-2*fanduct_shell,inlet_w-2*fanduct_shell,inlet_l+fanduct_shell+1]);
+ hull() {
+ placeit() translate([fanduct_shell,-inlet_w/2+fanduct_shell,0])
+ cube(size=[inlet_h-2*fanduct_shell,inlet_w-2*fanduct_shell,fanduct_shell]);
+ translate([-fanduct_ir-fanduct_shell-fanduct_w/2,0,fanduct_shell])
+ translate([0,-inlet_w/2,0])
+ cube(size=[1,inlet_w,fanduct_h]);
+ }
+ }
+ }
+
+ // *** DUCT TAILS!!! WOO-OO! (every day they're out there making duct tails…)
+ module tails(what) {
+ if(what=="in") {
+ for(mx=[0,1]) mirror([mx,0,0])
+ translate([fanduct_ir+fanduct_shell+fanduct_w/2,0,fanduct_shell+fanduct_h])
+ rotate([90,0,90])
+ translate([0,0,-snapper_d/2])
+ snapper(d=snapper_d,o=snapper_overlap,side=0,l=fanduct_h+fanduct_shell);
+ }
+ }
+
+ module parts(what) {
+ union() {
+ duct(what);
+ marks(what);
+ output(what);
+ intake(what);
+ tails(what);
+ }
+ }
+
+ difference() {
+ parts("in");
+ parts("out");
+ }
+
+}
+
+view=""; // hcut|vcut|*
+
+hinfinity=4*(fanduct_ir+fanduct_shell*2+fanduct_w+inlet_away);
+vinfinity=2*(fanduct_shell*2+fanduct_h+inlet_h);
+if(view=="hcut") {
+ difference() {
+ fanduct();
+ translate([-hinfinity/2,-hinfinity/2,fanduct_shell+fanduct_h/2])
+ cube(size=[hinfinity,hinfinity,vinfinity]);
+ }
+}else if(view=="vcut") {
+ difference() {
+ fanduct();
+ translate([-hinfinity/2,0,-vinfinity/2])
+ cube(size=[hinfinity,hinfinity,vinfinity]);
+ }
+}else fanduct();
diff --git a/snapper.scad b/snapper.scad
new file mode 100644
index 0000000..0c258ca
--- a/dev/null
+++ b/snapper.scad
@@ -0,0 +1,27 @@
+/* d - diameter, o - overlap (fraction) */
+function snapper_apart(d,o) = d*(1-o);
+module snapper(d,o,l=-1,side=0) {
+ snapper_apart = d*(1-o);
+ l_ = (l<0) ? d : l;
+ lw = d/2;
+ sfn = 8*d;
+ module lm() {
+ translate([-lw/2,0,0]) hull() {
+ cube(size=[lw,l_-d/2,d]);
+ translate([lw/2,l_,0]) cylinder(d=d/8,h=d,$fn=sfn);
+ }
+ }
+ if(side==0) {
+ translate([0,l_,d/2]) sphere(d=d,$fn=sfn);
+ lm();
+ }else if(side==1) {
+ difference() {
+ for(x=[-1,1]) translate([x*snapper_apart(d,o),0,0]) {
+ translate([0,l_,d/2]) sphere(d=d,$fn=sfn);
+ lm();
+ }
+ translate([0,l_,d/2]) sphere(d=d,$fn=sfn);
+ }
+ }else
+ echo("ERROR: what side?");
+}