From 8e0e6adacb1dfc9291e13ee05c201ec52ca2abd3 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Thu, 10 Sep 2026 22:25:49 +0100 Subject: [PATCH] A lot more work on the Microcar design. I'm not yet at all satisfied with this. --- microcar/microcar.scad | 20 +++++ microcar/shockabsorber.scad | 40 ++++++++++ microcar/suspension.scad | 145 +++++++++++++++++++++++------------- microcar/tub.scad | 40 ++++++---- microcar/wheel.scad | 1 + model/hull.scad | 2 +- 6 files changed, 184 insertions(+), 64 deletions(-) create mode 100644 microcar/microcar.scad create mode 100644 microcar/shockabsorber.scad create mode 120000 microcar/wheel.scad diff --git a/microcar/microcar.scad b/microcar/microcar.scad new file mode 100644 index 0000000..d8dbc30 --- /dev/null +++ b/microcar/microcar.scad @@ -0,0 +1,20 @@ +/** + * microcar.scad + * + * First sketch of a microcar. + */ + +include + +include +include + + +tub(fl=1100); + +translate([-900,0,130]) + suspension(); + +translate([1100,0,130]) + suspension(); + diff --git a/microcar/shockabsorber.scad b/microcar/shockabsorber.scad new file mode 100644 index 0000000..79e5338 --- /dev/null +++ b/microcar/shockabsorber.scad @@ -0,0 +1,40 @@ +/** + * shockabsorber.scad + * + * First sketch of a microcar spring/shock absorber unit. Ideally I + * would want to use linked hydropneumatic units, but that would be + * *absurdly* over expensive for a one off prototype. Air or conventional + * spring units would be far more pragmatic. + */ + +include + +eye_inner_diameter = 25/3; // to make it the same as pivot_radius defined + // in suspension.scad + +module eye( eid=eye_inner_diameter) { + rotate([0, 90, 0]) { + difference() { + cylinder( h=eid, r=eid, center=true); + cylinder( h=2*eid, d=eid, center=true); + } + } +} + +module shockabsorber( length=150, eid=eye_inner_diameter, coil_over=true) { + short_length=length-(eid*4); + + translate([0,0,eid]) { + // cylinder + cylinder(h=short_length/2, r=short_length/16); + // rod + cylinder(h=short_length, r=short_length/32); + + translate([0,0,0-eid]) { + eye(eid); + } + translate([0,0, short_length+eid]) { + eye(eid); + } + } +} diff --git a/microcar/suspension.scad b/microcar/suspension.scad index 4d4f6b8..52998b8 100644 --- a/microcar/suspension.scad +++ b/microcar/suspension.scad @@ -5,49 +5,76 @@ * * 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; +// assumes we're building out of square section aluminium tobe; +// the section width of that tube. +stock_section = 25; - lug_thickness = stock_section/6; +lug_thickness = stock_section/6; - // radius of suspension pivots - pivot_radius = stock_section/3; //for now +// radius of suspension pivots +pivot_radius = stock_section/3; //for now - module lug() { +module lug() { difference() { - union() { - translate([0, stock_section/2, 0]){ - cube([ stock_section, stock_section, lug_thickness], center=true); - } + 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=stock_section/2, h=stock_section/4, + center=true); } cylinder( r=pivot_radius, h=stock_section, center=true); - } + } } - module wishbone(l, w) { - ssd2 = stock_section/2; - ssm2 = stock_section * 2; - ssm3 = stock_section * 3; +module wishbone(l, w, is_upper = true) { + ssd2 = stock_section/2; + ssm2 = stock_section * 2; + ssm3 = stock_section * 3; - translate([ (l - lug_thickness)/2, stock_section, ssd2]) - rotate([180,90,0]) + // 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]) + translate([ 0 - (l - lug_thickness)/2, stock_section, ssd2]) + rotate([180,90,0]) lug(); - color("silver") - union() { - intersection(){ - linear_extrude(stock_section) + // 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)], + [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], @@ -55,10 +82,10 @@ 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]) + } + translate([-3*ssd2, w-3*ssd2, 0]) cube( [stock_section, 3*ssd2, stock_section]); - translate([ssd2, w-3*ssd2, 0]) + translate([ssd2, w-3*ssd2, 0]) cube( [stock_section, 3*ssd2, stock_section]); }; color("darkgray") @@ -83,27 +110,45 @@ } } - module suspension( l = 300, w = 300, h = 300, +module suspension( l = 300, w = 300, h = 300, track = 1400, hub_width = 135, wheel_diameter=600) { - subframe(l,w,h); + subframe(l,w,h); + + wishbone_length = 500; // TODO: calculate - // Upper wishbones - translate([0, w/2, (h/2) - stock_section]) - wishbone( l, 500); - mirror([0,1, 0]) { - translate([0, w/2, (h/2) - stock_section]) - wishbone( l, 500); - } + // 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); + } - // lower wishbones - translate([0, w/2, 0 -(h/2)]) - wishbone( l, 500); - mirror([0,1, 0]) { - translate([0, w/2, 0 -(h/2)]) - wishbone( l, 500); - } - } + 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); + } + } +} - lug(); - -suspension(); \ No newline at end of file + +// suspension(); diff --git a/microcar/tub.scad b/microcar/tub.scad index 4c22689..77d1f18 100644 --- a/microcar/tub.scad +++ b/microcar/tub.scad @@ -1,3 +1,11 @@ +/** + * tub.scad + * + * The tub of a microcar. + */ + +include + $fn = $preview ? 32 : 256; a_pillar_y = -400; // y location of face of 'A' pillar @@ -28,7 +36,7 @@ floor_width = 1500; // angle of the front bulkhead to vertical layback_angle_f = 30; // angle of the rear bulkhead to vertical -layback_angle_r = 45; +layback_angle_r = 50; sheet_thickness = 8; sill_max_height = bb_height; @@ -84,7 +92,7 @@ module sill( floor_length = 1100) { } rotate([-3, 0, 0]) translate([0, cr - (sill_width/2), 0]) - cylinder( h = cowl_height, + cylinder( h = cowl_height, r = cr); } } @@ -100,17 +108,23 @@ module front_bulkhead() { module rear_bulkhead() { } +module tub(fl=floor_length, fw=floor_width, st=sheet_thickness, + sw=sill_width) { + cube([fl, fw, st], + center=true); + battery_box(); -cube([floor_length, floor_width, sheet_thickness], - center=true); -battery_box(); - -translate([0, ( floor_width/2) + (sill_width/2), 0]) - sill(); - -mirror([0, 1, 0]) - translate([0, - ( floor_width/2) + (sill_width/2), 0]) + translate([0, ( fw/2) + (sw/2), 0]) sill(); -front_bulkhead(); \ No newline at end of file + mirror([0, 1, 0]) + translate([0, + ( fw/2) + (sw/2), 0]) + sill(); + + front_bulkhead(); + + rear_bulkhead(); +} + +// tub(); \ No newline at end of file diff --git a/microcar/wheel.scad b/microcar/wheel.scad new file mode 120000 index 0000000..ec39b52 --- /dev/null +++ b/microcar/wheel.scad @@ -0,0 +1 @@ +../model/wheel.scad \ No newline at end of file diff --git a/model/hull.scad b/model/hull.scad index 7ab94cc..03ec8cb 100644 --- a/model/hull.scad +++ b/model/hull.scad @@ -63,4 +63,4 @@ module hull() { } } -// hull(); + hull();