/** * suspension.scad * * First sketch of a microcar suspension subframe. * * The purpose of the subframe is sumply to carry the inner ends of the * wishbones, so it is simply the minimum size required to do that. * * TODO: this does not yet consider caster, camber, anti-dive geometry, * or other such niceties. */ include include include // assumes we're building out of square section aluminium tobe; // the section width of that tube. stock_section = 25; lug_thickness = stock_section/6; // radius of suspension pivots pivot_radius = stock_section/3; //for now module lug() { difference() { union() { translate([0, stock_section/2, 0]){ cube([ stock_section, stock_section, lug_thickness], center=true); } cylinder( r=stock_section/2, h=stock_section/4, center=true); } cylinder( r=pivot_radius, h=stock_section, center=true); } } module wishbone(l, w, is_upper = true) { ssd2 = stock_section/2; ssm2 = stock_section * 2; ssm3 = stock_section * 3; // wishbone inboard pivot lugs translate([ (l - lug_thickness)/2, stock_section, ssd2]) rotate([180,90,0]) lug(); translate([ 0 - (l - lug_thickness)/2, stock_section, ssd2]) rotate([180,90,0]) lug(); // shock absorber end lugs if (is_upper) { translate([ ssd2, ssm2, ssd2]) rotate([180,90,0]) lug(); translate([ -ssd2, ssm2, ssd2]) rotate([180,90,0]) lug(); } else { translate([ ssd2, w-ssm3, ssd2]) rotate([180,90,180]) lug(); translate([ -ssd2, w-ssm3, ssd2]) rotate([180,90,180]) lug(); } color("silver") union() { intersection(){ linear_extrude(stock_section) polygon( points=[[0-(l/2), ssd2], [l/2, ssd2], [3*ssd2, w-(3*ssd2)], [0-(3*ssd2), w-(3*ssd2)], // hole in the middle [0-(l/2 - 3*ssd2), 3*ssd2], [l/2 - 3*ssd2, 3*ssd2], [ssd2, w-(5*ssd2)], [0-ssd2, w-(5*ssd2)]], paths=[[0, 1, 2, 3], [4, 5, 6, 7]]); translate([0 - (l - ssd2)/2, 0, 0 - stock_section]) cube([l-ssd2, w, ssm3]); } translate([-3*ssd2, w-3*ssd2, 0]) cube( [stock_section, 3*ssd2, stock_section]); translate([ssd2, w-3*ssd2, 0]) cube( [stock_section, 3*ssd2, stock_section]); }; color("darkgray") translate([0, stock_section, ssd2]) rotate([0, 90, 0]) cylinder(h=l, r=pivot_radius, center=true); color("darkgray") translate([0, w - ssd2, ssd2]) rotate([0, 90, 0]) cylinder(h=ssm3, r=pivot_radius, center=true); } module subframe(l, w, h) { q = stock_section * 2; color( "silver") difference() { cube([l,w,h], center=true); cube([l+200, w-q, h-q], center=true); cube([l-q, w+200, h-q], center=true); cube([l-q, w-q, h+200], center=true); } } module suspension( l = 300, w = 300, h = 300, track = 1400, hub_width = 135, wheel_diameter=600) { subframe(l,w,h); wishbone_length = 500; // TODO: calculate // Upper wishbones translate([0, w/2, (h/2) - stock_section]) wishbone( l, wishbone_length); mirror([0,1, 0]) { translate([0, w/2, (h/2) - stock_section]) wishbone( l, wishbone_length); } shock_extent = wishbone_length - (5.5 * stock_section); shock_angle = atan(shock_extent/(h-stock_section)); shock_length = shock_extent * tan(shock_angle); // lower wishbones translate([0, w/2, 0 -(h/2)]) { wishbone( l, wishbone_length, false); translate([0, wishbone_length + 75, stock_section]) wheel(); translate([0, (stock_section*2), h-(stock_section/2)]) rotate([shock_angle +180, 0, 0]) shockabsorber(length=shock_length,eid=stock_section/2); } mirror([0,1, 0]) { translate([0, w/2, 0 -(h/2)]) { wishbone( l, wishbone_length, false); translate([0, wishbone_length + 75, stock_section]) wheel(); translate([0, (stock_section*2), h-(stock_section/2)]) rotate([shock_angle +180, 0, 0]) shockabsorber(length=shock_length, eid=stock_section/2); } } } // suspension();