/** * 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 // aft tilt of kingpins in degrees from vertical caster_angle = 7; // inward tilt of the kingpins in degrees from vertical // TODO: should be calculated from hub width and wheel radius? camber_angle = 10; module kingpin( aa=0, h = 300, r = 12.5, cmb = camber_angle, cst = caster_angle, al = 100) { kl = h * (1/cos(90 - cmb)) * (1/cos(90 - cst)); // kingpin itself rotate([cmb, cst, 0]) cylinder( h=h, r=r, center=true); // stub axle // axle offset as a fraction of the lenth of the kingpin aof = 0.35 * h; camber_offset = aof/tan(90-cmb); caster_offset = 0 - aof/tan(90-cst); // axle itself translate([caster_offset, al + camber_offset, 0-aof]) rotate([ 90, 0, 0]) cylinder( h=al, r=r); // steering arm translate([caster_offset, camber_offset, 0-aof]) rotate([ aa, -90, 0]) cylinder( h=al, d=r); translate([caster_offset, al, 0-aof]) wheel(); } // kingpin(); // TODO: still need steering rack and track rods. 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, skew = 0, 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], [skew + (3*ssd2), w-(3*ssd2)], [skew -(3*ssd2), w-(3*ssd2)], // hole in the middle [(0 - (l/2 - 3*ssd2)), 3*ssd2], [(l/2 - 3*ssd2), 3*ssd2], [skew + ssd2, w-(5*ssd2)], [skew - 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([skew-3*ssd2, w-3*ssd2, 0]) cube( [stock_section, 3*ssd2, stock_section]); translate([skew+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([skew, 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( aa = 7, l = 300, w = 300, h = 300, track = 1400, hub_width = 135, wheel_diameter=600, cmb=camber_angle, cst=caster_angle) { subframe(l,w,h); wishbone_length = 500; // TODO: calculate camber_offset = h/tan(90-cmb); caster_offset = h/tan(90-cst); // Upper wishbones translate([0, w/2, (h/2) - stock_section]) wishbone( l, wishbone_length - camber_offset, caster_offset); mirror([0,1, 0]) { translate([0, w/2, (h/2) - stock_section]) wishbone( l, wishbone_length - camber_offset, caster_offset); } 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, 0, false); 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, 0, false); translate([0, (stock_section*2), h-(stock_section/2)]) rotate([shock_angle +180, 0, 0]) shockabsorber(length=shock_length, eid=stock_section/2); } } translate([caster_offset/2, wishbone_length + (stock_section * 4), 0]) kingpin(aa=aa, cst=cst); mirror([0,1, 0]) translate([caster_offset/2, wishbone_length + (stock_section * 4), 0]) kingpin(aa=aa, cst=cst); } // suspesion()