// Toolcart design for milling machine - week 7 Fabacademy 2024 - e13 $fn = 40; // drawing segments mat = 15; // material thickness mill = 5; // used mill diameter tab = 80; // tab width width = 800; // main unit width (bottom plate) height = 1000; // total height (side plate) depth = 560; // depth (bottom plate) corner = 60; // corner ratio (global) cross1 = [mat,175]; // sizes and heights for cross section panels cross2 = [250,125]; // bottom side cross3 = [425,125]; // .. cross4 = [600,100]; // .. cross5 = [750,100]; // .. cross6 = [900,100]; // top panel tabspacing = [60,180]; // two tabs on the groundplane at these distances peg = 5; // dowel size for tab-fixing // below the different build stages: build(); // build the cart - the full assembled design // color("yellow")cube([1700,1220,1]); // base material (for reference) // flat(); // all components on one pane // projection()flat(); // make a flat SVG projection // testcut(); // make a small test piece to test the tab fitting // experimental: the following generates an offset cut-path (not needed for Vcarve) // color("red")translate([0,0,8])cutpath_buildplate(); module cutpath_buildplate(){ translate([40,670,0])difference(){ offset(r=mill/2,chamfer = true)projection()sidepanel(depth,height,180,180,corner); offset(r=-mill/2,chamfer = true)projection()sidepanel_cutshapes(depth); } translate([1320,1020,0])rotate([0,0,180])difference(){ offset(r=mill/2,chamfer = true)projection()sidepanel(depth,height,180,180,corner); offset(r=-mill/2,chamfer = true)projection()sidepanel_cutshapes(depth); } translate([20,20,0])difference(){ offset(r=mill/2,chamfer = true)projection()bottomplate(width,depth,400,150,corner); offset(r=-mill/2,chamfer = true)projection()bottom_cutshapes(width,depth); } translate([1540,440,0])rotate([0,0,90])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross1[1]); translate([900,20,0])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross2[1]); translate([1680,440,0])rotate([0,0,90])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross3[1]); translate([900,160,0])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross4[1]); translate([400,1080,0])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross5[1]); translate([900,280,0])offset(r=mill/2,chamfer = true)projection()crosspanel(width-4*mat,cross6[1]); } module testcut(){ projection(){ millslot(80); translate([40,0,0])tab(80); translate([40+mat,-10,0])cube([10,100,mat]); } } module build(){ bottomplate(width,depth,400,150,corner); // todo: replace fixed sizes by ratios translate([2*mat,0,mat])rotate([0,-90,0])sidepanel(depth,height,180,180,corner); translate([width-mat,0,mat])rotate([0,-90,0])sidepanel(depth,height,180,180,corner); // cross section plates translate([2*mat,depth/2+mat/2,cross1[0]])rotate([90,0,0])crosspanel(width-4*mat,cross1[1]); translate([2*mat,depth/2+mat/2,cross2[0]])rotate([90,0,0])crosspanel(width-4*mat,cross2[1]); translate([2*mat,depth/2+mat/2,cross3[0]])rotate([90,0,0])crosspanel(width-4*mat,cross3[1]); translate([2*mat,depth/2+mat/2,cross4[0]])rotate([90,0,0])crosspanel(width-4*mat,cross4[1]); translate([2*mat,depth/2+mat/2,cross5[0]])rotate([90,0,0])crosspanel(width-4*mat,cross5[1]); translate([2*mat,depth/2+mat/2,cross6[0]])rotate([90,0,0])crosspanel(width-4*mat,cross6[1]); } module flat(){ translate([20,20,0])bottomplate(width,depth,400,150,corner); translate([40,670,0])sidepanel(depth,height,180,180,corner); translate([1320,1020,0])rotate([0,0,180])sidepanel(depth,height,180,180,corner); translate([1540,440,0])rotate([0,0,90])crosspanel(width-4*mat,cross1[1]); translate([900,20,0])crosspanel(width-4*mat,cross2[1]); translate([1680,440,0])rotate([0,0,90])crosspanel(width-4*mat,cross3[1]); translate([900,160,0])crosspanel(width-4*mat,cross4[1]); translate([400,1080,0])crosspanel(width-4*mat,cross5[1]); translate([900,280,0])crosspanel(width-4*mat,cross6[1]); } module bottomplate(bottom_width,bottom_depth,bottom_middlewidth,bottom_sidewidth,bottom_r) { difference(){ union(){ hull(){ translate([bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_sidewidth-bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_sidewidth-bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_sidewidth-bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_sidewidth-bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width/3-bottom_r,bottom_r+bottom_depth/2-bottom_middlewidth/2,0])cylinder(r=bottom_r,h=mat); translate([bottom_width/3-bottom_r,bottom_depth/2+bottom_middlewidth/2-bottom_r,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_width/3-bottom_r,bottom_r+bottom_depth/2-bottom_middlewidth/2,0])cylinder(r=bottom_r,h=mat); translate([bottom_width/3-bottom_r,bottom_depth/2+bottom_middlewidth/2-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_width/3+bottom_r,bottom_r+bottom_depth/2-bottom_middlewidth/2,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_width/3+bottom_r,bottom_depth/2+bottom_middlewidth/2-bottom_r,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_width-bottom_width/3+bottom_r,bottom_r+bottom_depth/2-bottom_middlewidth/2,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_width/3+bottom_r,bottom_depth/2+bottom_middlewidth/2-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_sidewidth+bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_sidewidth+bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_width-bottom_sidewidth+bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_sidewidth+bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_r,bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_width-bottom_r,bottom_depth-bottom_r,0])cylinder(r=bottom_r,h=mat); } } bottom_cutshapes(bottom_width,bottom_depth); } } module bottom_cutshapes(bottom_width,bottom_depth){ translate([mat,tabspacing[0],0])millslot(tab); translate([mat,tabspacing[1],0])millslot(tab); translate([mat,bottom_depth-tabspacing[1]-tab,0])millslot(tab); translate([mat,bottom_depth-tabspacing[0]-tab,0])millslot(tab); translate([bottom_width-2*mat,tabspacing[0],0])millslot(tab); translate([bottom_width-2*mat,tabspacing[1],0])millslot(tab); translate([bottom_width-2*mat,bottom_depth-tabspacing[1]-tab,0])millslot(tab); t ranslate([bottom_width-2*mat,bottom_depth-tabspacing[0]-tab,0])millslot(tab); } module millslot(width){ union(){ translate([0,mill/2,0])cylinder(d=mill,h=mat+0.01); translate([0,width-mill/2,0])cylinder(d=mill,h=mat+0.01); translate([mat,width-mill/2,0])cylinder(d=mill,h=mat+0.01); translate([mat,mill/2,0])cylinder(d=mill,h=mat+0.01); translate([0,0,0])cube([mat,width,mat+0.01]); } } module tab(width){ difference(){ union(){ translate([0,0,0])cube([mat,width,mat]); hull(){ translate([0,mat/2,0])cylinder(d=mat,h=mat); translate([0,width-mat/2,0])cylinder(d=mat,h=mat); } } translate([-(peg)/2,mat,0])cylinder(d=peg,h=mat+0.01); translate([-(peg)/2,width-mat,0])cylinder(d=peg,h=mat+0.01); } } module sidepanel(bottom_width,panel_height,bottom_height,central_width,bottom_r){ difference(){ union(){ hull(){ translate([0,bottom_r/2,0])cube([bottom_height-bottom_r,bottom_width-bottom_r,mat]); translate([bottom_height-bottom_r,bottom_r/2+bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_height-bottom_r,bottom_width-bottom_r-bottom_r/2,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_height-bottom_r,bottom_r/2+bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_height-bottom_r,bottom_width-bottom_r-bottom_r/2,0])cylinder(r=bottom_r,h=mat); translate([2*bottom_height-bottom_r,bottom_width/2-central_width/2+bottom_r,0])cylinder(r=bottom_r,h=mat); translate([2*bottom_height-bottom_r,bottom_width/2+central_width/2-bottom_r,0])cylinder(r=bottom_r,h=mat); } hull(){ translate([bottom_height-bottom_r,bottom_width/2-central_width/2+bottom_r,0])cylinder(r=bottom_r,h=mat); translate([bottom_height-bottom_r,bottom_width/2+central_width/2-bottom_r,0])cylinder(r=bottom_r,h=mat); translate([panel_height-bottom_r,bottom_width/2-central_width/2+bottom_r,0])cylinder(r=bottom_r,h=mat); translate([panel_height-bottom_r,bottom_width/2+central_width/2-bottom_r,0])cylinder(r=bottom_r,h=mat); } translate([-mat,tabspacing[0],0])tab(tab); translate([-mat,tabspacing[1],0])tab(tab); translate([-mat,bottom_width-tabspacing[1]-tab,0])tab(tab); translate([-mat,bottom_width-tabspacing[0]-tab,0])tab(tab); } translate([0,tabspacing[0]-mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,tab+tabspacing[0]+mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,tabspacing[1]-mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,tab+tabspacing[1]+mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,bottom_width-tabspacing[1]+mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,bottom_width-tabspacing[1]-tab-mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,bottom_width-tabspacing[0]+mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,bottom_width-tabspacing[0]-tab-mill/2,0])cylinder(d=mill,h=10+mat+0.01); sidepanel_cutshapes(bottom_width); } } module sidepanel_cutshapes(bottom_width){ translate([cross1[0]+cross1[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); translate([cross2[0]+cross2[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); translate([cross3[0]+cross3[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); translate([cross4[0]+cross4[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); translate([cross5[0]+cross5[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); translate([cross6[0]+cross6[1]/2-tab/2-mat,bottom_width/2+mat/2,0])rotate([0,0,-90])millslot(tab); } module crosspanel(width,height){ difference(){ union(){ cube([width,height,mat]); translate([-mat,height/2-tab/2,0])tab(tab); translate([width+mat,height/2+tab/2,0])rotate([0,0,180])tab(tab); } translate([0,height/2-tab/2-mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([0,tab+height/2-tab/2+mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([width,height/2-tab/2-mill/2,0])cylinder(d=mill,h=10+mat+0.01); translate([width,tab+height/2-tab/2+mill/2,0])cylinder(d=mill,h=10+mat+0.01); } }