use <WebWeaver/scad/Util.scad>; use <WebWeaver/scad/Piping.scad>; // Material definitions module GreenPLA() { color([28/255, 1.0, 47/255, 132/255]) children(); } module MockupColor() { color([0, 0.6, 0.8, 0.6]) children(); } module BlackAluminium() { color([16/255, 16/255, 16/255]) children(); } // hs = heat sink hs_l = 120; hs_w = 79; hs_baseplate = 4; hs_fin_w0 = 2; hs_fin_w1 = 1.3; hs_fin_d = 11; // depth hs_fin_cnt = 10; hs_fin_spacing = 3.5; /** * * TODO: Moar documentation! * */ module symmetricHeatsink( l = hs_l, w = hs_w, baseplate = hs_baseplate, fin_w0 = hs_fin_w0, fin_w1 = hs_fin_w1, fin_d = hs_fin_d, fin_cnt = hs_fin_cnt, fin_spacing = hs_fin_spacing ) { module fin() { dw2 = fin_d - fin_w1/2; translate([0, fin_w0, dw2]) rotate([-90, 0, -90]) linear_extrude(l) hull() { translate([0, dw2, 0]) square([fin_w0, 0.01]); translate([fin_w1/2, 0, 0]) circle(d=fin_w1); } } module half() { cube([l, w/2, baseplate]); for (y=[0:fin_cnt/2 - 1]) translate([0, y * ( fin_w0 + fin_spacing), baseplate]) fin(); } BlackAluminium() translate([-l/2, -w/2, 0]) { half(); translate([0, w, 0]) mirror([0, 1, 0]) half(); } } // f = fan f_r = 4; // corner radius of fan case f_d = 20; // depth. or thickness. f_wh = 40; // widht and height of the fan's chassis f_drill = 4; // mounting hole diameter f_drill_wh = 32; // size of a virtual rectangle with mounting holes drilled through the corners f_intake = 38; // air intake diameter f_motor = 23; // diameter of fan motor /** * * TODO: Moar documentation!!! * * `layer`: either "Body" or "MotorConnection". the latter produces the bridges to the motor * */ module fanProfile( r = f_r, wh = f_wh, drill = f_drill, drill_wh = f_drill_wh, intake = f_intake, motor = f_motor, layer = "Body", closed=false ) { difference() { roundRect(wh, wh, r, center=true); // mounting holes _dwh2 = drill_wh / 2; for (tx=[-_dwh2, _dwh2], ty=[-_dwh2, _dwh2]) translate([tx, ty, 0]) circle(d=drill); // the central air intake if (!closed) circle(d=intake); } // the fans motor if (!closed && motor > 0) circle(d=motor); } /** * * TODO: Moar documentation!!! * * `d` = thickness * */ module fan( d = f_d, r = f_r, wh = f_wh, drill = f_drill, drill_wh = f_drill_wh, intake = f_intake, motor = f_motor, layer_ratio = 0.1 ) { // shadow original module here so we don't have to repeat the param list ^^ module _fanProfile(layer) { fanProfile(r=r, wh=wh, drill=drill, drill_wh=drill_wh, intake=intake, motor=motor, layer=layer); } if (layer_ratio > 0) translate([0, 0, d - d * layer_ratio]) linear_extrude(d * layer_ratio) _fanProfile("MotorConnection"); if (layer_ratio < 1) linear_extrude(d * (1 - layer_ratio)) _fanProfile("Body"); } fu_strength = 2; // material strength fu_outlet_w = (hs_fin_cnt / 2) * hs_fin_w0 + (hs_fin_cnt / 2 - 1) * hs_fin_spacing; // Σ of fins spacing and width calculated over one side; module tri(w, h) { polygon([ [0, -h/2], [0, h/2], [w, 0] ]); } // length of the outlet x = 5; // TODO: rename!!!! // The profile of the funnel, ready for extrusion module funnel2D() { _y = hs_w/2 - fu_outlet_w; difference() { union() { translate([0, -hs_w/2, 0]) square([x, hs_w]); translate([0, 0, 0]) roundTri(x*9, hs_w, 5); } /* union() { translate([0, _y, 0]) square([x, fu_outlet_w]); translate([0, -_y - fu_outlet_w, 0]) square([x, fu_outlet_w]); // air funnel split translate([x, 0, 0]) tri(_y*4, hs_w); } */ // air funnel split translate([0, 0, 0]) roundTri(x*4, _y*2, 3); translate([0, -_y, 0]) square([x/2, _y*2]); } } // ff = funnel fin ff_str = hs_fin_w0; // strength module funnelFins( w = hs_w, fin_cnt = hs_fin_cnt, fin_spacing = hs_fin_spacing, fin_cnt = hs_fin_cnt, fin_w0 = hs_fin_w0, _str = ff_str ) { module fin(x, y) { module _fF(y) { translate([0, -y/2, 0]) square([x, y]); translate([0, 0, 0]) roundTri((x*9) * (y/w), y, 5); } difference() { _fF(y + _str/2); _fF(y - _str/2); } } _x = 5; for (y=[0:fin_cnt/2 - 1]) fin( -(y/fin_cnt/2 - 1) * _x, w - y * (fin_w0 + fin_spacing) * 2); } // ############################ // ####### New Approach ####### // ############################ fu_r = 2; fu_str = 1.6; module curvyFunnel() { hs_h = hs_baseplate + hs_fin_d; d = 2; y_off = hs_w/2 - fu_outlet_w/2; module half() { difference() { union() { translate([hs_l/2, -y_off, -hs_h]) rotate([90, 0, 90]) cornerPipeLayOnFace(hs_h, fu_outlet_w, d, 180, fu_r, fu_str, centerX=true); translate([hs_l/2, -y_off + fu_outlet_w/2 + d/2, d]) rotate([0, 0, 180]) cornerPipe(fu_outlet_w, hs_h, d, 90, fu_r, fu_str); translate([hs_l/2 - fu_outlet_w - d, -y_off + fu_outlet_w/2 + d/2, d]) rotate([0, 0, 0]) cornerPipe(fu_outlet_w, hs_h, d, 90, fu_r, fu_str); } translate([-hs_l/2, 0, 0]) cube([hs_l, hs_w/2, hs_w]); } } GreenPLA() { half(); mirror([0, 1, 0]) half(); } } module splitFunnel() { hs_h = hs_baseplate + hs_fin_d; d = 2; y_off = hs_w/2 - fu_outlet_w/2; alpha = 56; // curve angle module half() { translate([hs_l/2, -y_off, -hs_h]) rotate([90, 0, 90]) cornerPipeLayOnFace(hs_h, fu_outlet_w, d, 180, fu_r, fu_str, centerX=true); // intersection() { // debugging stuff translate([hs_l/2, -y_off + fu_outlet_w/2 + d/2, d]) rotate([0, 0, 270 - alpha]) cornerPipe(fu_outlet_w, hs_h, d, alpha, fu_r, fu_str); // the straight pipe after the curve sp_len = 20; // TODO: calculate! // translate([hs_l/2, y_off, hs_h/2 + d]) rotate([90, 0, -90]) straightPipe(fu_outlet_w, hs_h, sp_len, fu_r, fu_str); // difference() { // translate([-hs_l/2, 0, 0]) cube([hs_l, hs_w/2, hs_w]); // } } sp_len = 20; module _straight(x_off=0, _y_off=0, inner=false, outer=false) { // connecting a straight pipe to the end of a curve in a fully generic way // // step 1: move to a very specific point beneath origin // step 2: rotate by curve pipe angle // step 3: move to the beginning(!) of the curve pipe where we want them to meet // for (signum=[-1, 1]) translate([hs_l/2, (-y_off + fu_outlet_w/2) * signum, hs_h/2 + d]) // step 3 rotate([0, 0, -alpha * signum *$t]) // step 2 translate([+ x_off, -fu_outlet_w/2 * signum + d/2 + _y_off, 0]) rotate([90, 0, -90]) // step 1 straightPipe(fu_outlet_w, hs_h, sp_len + 2*x_off, fu_r, fu_str, inner=inner, outer=outer); // } // debugging stuff } color([1.0, 0, 0]) translate([0, 0, 0.1]) _straight(_y_off=-1, outer=true); GreenPLA() { half(); mirror([0, 1, 0]) half(); difference() { union() { translate([hs_l/2 - f_wh/2, 0, 0]) rotate([0, 0, 45]) linear_extrude(hs_h + d) roundRect(f_wh, f_wh, f_r, center=true); //_straight(outer=true); } translate([hs_l/2 - f_wh/2, 0, d + fu_str]) rotate([0, 0, 45]) cylinder(d=30, h=hs_h - fu_str); _straight(x_off=1, inner=true); } } } // Define the main module… module HeatSinkMainModule() { epsilon = 0.001; if ($preview) { $fs = 0.5; $fa = 10; // display heat sink only in render mode rotate([180, 0, 0]) symmetricHeatsink(); // translate([0, 0, 0]) curvyFunnel(); translate([0, 0, 0]) splitFunnel(); // color([0, 0, 1.0, 1.0]) translate([0, 0, 1]) linear_extrude(1) funnelFins(); translate([7+8 - 72/2, 0, epsilon]) rotate([0, 0, 30]) MockupColor() linear_extrude(1.6) roundNGon(72, 6, 10/2); // translate([12, 0, f_wh/2 + epsilon]) rotate([0, 90, 0]) MockupColor() fan(d=11); } else { $fs = 0.35; $fa = 2.0; // TODO: 3D-Print positioning! // translate([0, 0, 0]) curvyFunnel(); translate([0, 0, 0]) splitFunnel(); // color([0, 0, 1.0, 1.0]) translate([0, 0, 1]) linear_extrude(1) funnelFins(); } } // …and execute it ;) HeatSinkMainModule();