From 659001351eaf2210703b29490bbd998567d3c448 Mon Sep 17 00:00:00 2001 From: Teddy Middleton-Smith Date: Tue, 25 Feb 2025 12:13:03 +0000 Subject: [PATCH] Initial commit --- config.scad | 157 ++++++++++++++++++ docs/.~lock.UBOM.ods# | 1 + docs/UBOM.ods | Bin 0 -> 98306 bytes main.json | 7 + main.scad | 22 +++ models/bed/bed.scad | 41 +++++ models/brake/beam_leg_ballscrew_to_bed.scad | 10 ++ models/brake/brake_arm.scad | 16 ++ models/brake/brake_assembly.scad | 76 +++++++++ models/brake/brake_assembly_functions.scad | 3 + models/brake/brake_pad.scad | 13 ++ models/brake/brake_spring_load_assembly.scad | 43 +++++ models/brake/fixing_ballscrew_to_bed.scad | 42 +++++ .../brake/fixing_brake_arm_to_brake_pad.scad | 50 ++++++ .../fixing_brake_arm_to_rear_axle_leg.scad | 35 ++++ .../fixing_brake_ballscrew_to_brake_arms.scad | 29 ++++ models/brake/power_wheel_assembly.scad | 39 +++++ models/common/angle_beam.scad | 13 ++ models/common/ball_socket_joint.scad | 51 ++++++ models/common/beam_hexagonal.scad | 13 ++ models/common/beam_hollow_rectangular.scad | 13 ++ models/common/beam_hollow_square.scad | 10 ++ models/common/compression_spring.json | 7 + models/common/compression_spring.scad | 23 +++ models/common/hollow_cuboid.scad | 12 ++ models/common/metric_bolt.scad | 28 ++++ models/common/metric_bolt_functions.scad | 9 + models/common/metric_nut.json | 7 + models/common/metric_nut.scad | 20 +++ models/common/universal_joint.scad | 49 ++++++ models/common/washer.json | 7 + models/common/washer.scad | 15 ++ models/common/wheel.scad | 12 ++ models/dog_cart/dog_cart.scad | 31 ++++ ...tube_clamp_round_3_way_outlet_tee_176.scad | 39 +++++ .../tube_clamp_round_3_way_through_116.scad | 27 +++ ...amp_round_3_way_through_116_functions.scad | 10 ++ .../tube_clamp_round_base_plate_132.scad | 29 ++++ ..._clamp_round_base_plate_132_functions.scad | 23 +++ .../tube_clamp_round_tee_long_104.scad | 24 +++ ...be_clamp_round_tee_long_104_functions.scad | 16 ++ .../tube_clamp_square_base_plate_132.scad | 28 ++++ ...clamp_square_base_plate_132_functions.scad | 21 +++ models/front_drive/front_drive_assembly.scad | 80 +++++++++ models/front_drive/front_leg_fixing.scad | 50 ++++++ models/front_drive/tiller_assembly.scad | 64 +++++++ models/front_drive/tiller_joint.scad | 50 ++++++ models/rear_drive/rear_drive_assembly.scad | 45 +++++ models/rear_drive/rear_leg_fixing.scad | 45 +++++ models/rear_drive/rear_wheel_fastener.scad | 28 ++++ models/top_crate/fixing_top_crate_shaft.scad | 30 ++++ .../top_crate/top_crate_shaft_assembly.scad | 29 ++++ 52 files changed, 1542 insertions(+) create mode 100644 config.scad create mode 100644 docs/.~lock.UBOM.ods# create mode 100644 docs/UBOM.ods create mode 100644 main.json create mode 100644 main.scad create mode 100644 models/bed/bed.scad create mode 100644 models/brake/beam_leg_ballscrew_to_bed.scad create mode 100644 models/brake/brake_arm.scad create mode 100644 models/brake/brake_assembly.scad create mode 100644 models/brake/brake_assembly_functions.scad create mode 100644 models/brake/brake_pad.scad create mode 100644 models/brake/brake_spring_load_assembly.scad create mode 100644 models/brake/fixing_ballscrew_to_bed.scad create mode 100644 models/brake/fixing_brake_arm_to_brake_pad.scad create mode 100644 models/brake/fixing_brake_arm_to_rear_axle_leg.scad create mode 100644 models/brake/fixing_brake_ballscrew_to_brake_arms.scad create mode 100644 models/brake/power_wheel_assembly.scad create mode 100644 models/common/angle_beam.scad create mode 100644 models/common/ball_socket_joint.scad create mode 100644 models/common/beam_hexagonal.scad create mode 100644 models/common/beam_hollow_rectangular.scad create mode 100644 models/common/beam_hollow_square.scad create mode 100644 models/common/compression_spring.json create mode 100644 models/common/compression_spring.scad create mode 100644 models/common/hollow_cuboid.scad create mode 100644 models/common/metric_bolt.scad create mode 100644 models/common/metric_bolt_functions.scad create mode 100644 models/common/metric_nut.json create mode 100644 models/common/metric_nut.scad create mode 100644 models/common/universal_joint.scad create mode 100644 models/common/washer.json create mode 100644 models/common/washer.scad create mode 100644 models/common/wheel.scad create mode 100644 models/dog_cart/dog_cart.scad create mode 100644 models/fixings/tube_clamp_round_3_way_outlet_tee_176.scad create mode 100644 models/fixings/tube_clamp_round_3_way_through_116.scad create mode 100644 models/fixings/tube_clamp_round_3_way_through_116_functions.scad create mode 100644 models/fixings/tube_clamp_round_base_plate_132.scad create mode 100644 models/fixings/tube_clamp_round_base_plate_132_functions.scad create mode 100644 models/fixings/tube_clamp_round_tee_long_104.scad create mode 100644 models/fixings/tube_clamp_round_tee_long_104_functions.scad create mode 100644 models/fixings/tube_clamp_square_base_plate_132.scad create mode 100644 models/fixings/tube_clamp_square_base_plate_132_functions.scad create mode 100644 models/front_drive/front_drive_assembly.scad create mode 100644 models/front_drive/front_leg_fixing.scad create mode 100644 models/front_drive/tiller_assembly.scad create mode 100644 models/front_drive/tiller_joint.scad create mode 100644 models/rear_drive/rear_drive_assembly.scad create mode 100644 models/rear_drive/rear_leg_fixing.scad create mode 100644 models/rear_drive/rear_wheel_fastener.scad create mode 100644 models/top_crate/fixing_top_crate_shaft.scad create mode 100644 models/top_crate/top_crate_shaft_assembly.scad diff --git a/config.scad b/config.scad new file mode 100644 index 0000000..151e4d5 --- /dev/null +++ b/config.scad @@ -0,0 +1,157 @@ + +use <./models/common/metric_bolt_functions.scad>; +use <./models/brake/brake_assembly_functions.scad>; +use <./models/fixings/tube_clamp_round_tee_long_104_functions.scad>; +use <./models/fixings/tube_clamp_round_3_way_through_116_functions.scad>; +use <./models/fixings/tube_clamp_round_base_plate_132_functions.scad>; +use <./models/fixings/tube_clamp_square_base_plate_132_functions.scad>; + +// Configuration +R_BED = [400, 1200, 18]; +T_WHEEL = 100; +D_WHEEL = 400; +D_WHEEL_BORE = 25; + +T_PLATE = 8; +T_CLAMP = 20; + +// D_AXIS = 25; +D_AXLE_FRONT = 42; +D_AXLE_REAR = 27; +Y_POS_AXLE_FRONT = R_BED[1] / 2 - D_WHEEL / 2; +Y_POS_AXLE_REAR = -R_BED[1] / 2 + D_WHEEL / 2; +X_POS_WHEEL_CENTRE = R_BED[0] / 2 + T_WHEEL / 2; + +SPACING_XY_BED_BORDER = 10; +Z_OVERLAP_TEE_CLAMP_ROUND = 80; +Z_OFFSET_WHEEL_TO_BED_BASE = 5; +Z_OFFSET_BED_TO_AXLE = D_WHEEL / 2 + Z_OFFSET_WHEEL_TO_BED_BASE; +M_TOTAL = 160; + +L_BOLT_EXTENSION = 10; +SIZE_BOLT = 25; // M25 +SIZE_BOLT_REAR_WHEEL_POSITIONING = 10; +T_WASHER_BOLT_REAR_WHEEL_POSITIONING = 1.5; +D_WASHER_BOLT_REAR_WHEEL_POSITIONING = 30; // get_metric_bolt_washer_diameter_safe_working_clearance(SIZE_BOLT_REAR_WHEEL_POSITIONING); +T_WASHER_AXLE_REAR_WHEEL_POSITIONING = 4; +D_WASHER_AXLE_REAR_WHEEL_POSITIONING = 50; +SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING = 1; + +R_FIXING_AXLE_LEG_REAR_TO_BED = get_R_plate_round_base_plate_132(D_AXLE_REAR); +L_SHAFT_AXLE_FIXING_AXLE_REAR_TO_LEG = get_L_shaft_long_round_tee_long_104(D_AXLE_REAR); +X_POS_AXLE_LEG_REAR = min(X_POS_WHEEL_CENTRE - T_WHEEL / 2 - SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING - T_WASHER_AXLE_REAR_WHEEL_POSITIONING - D_WASHER_BOLT_REAR_WHEEL_POSITIONING - L_SHAFT_AXLE_FIXING_AXLE_REAR_TO_LEG / 2, R_BED[0] / 2 - SPACING_XY_BED_BORDER - R_FIXING_AXLE_LEG_REAR_TO_BED[0] / 2); + +// BRAKE +// THICKNESS_SHELL_BRAKE_BEAM = 5; +// L_BEAM_BRAKE_BELT_TENSION_FIXING = 150; +D_BEAM_BRAKE = 40; +T_BEAM_BRAKE = 5; +D_BRAKE_BALLSCREW_AXLE = 16; // M16 pitch 1.5 +L_BRAKE_BALLSCREW_AXLE = 700; +D_BRAKE_BALLSCREW_POWER_WHEEL = 120; +T_BRAKE_BALLSCREW_POWER_WHEEL = get_metric_bolt_head_height(D_BRAKE_BALLSCREW_AXLE); +D_WASHER_BRAKE_BALLSCREW_POWER_WHEEL = 50; // get_metric_bolt_washer_diameter_safe_working_clearance(D_BRAKE_BALLSCREW_AXLE); +T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL = 3; +Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE = 125; // D_BRAKE_BALLSCREW_POWER_WHEEL / 2 + 25; +Y_OFFSET_BALLSCREW_LEG_REAR_FIXING_FROM_END = 100; +Y_OFFSET_BALLSCREW_LEG_FRONT_FIXING_FROM_END = Y_OFFSET_BALLSCREW_LEG_REAR_FIXING_FROM_END + 100; +// L_BEAM_FIXING_BALLSCREW_TO_BED = D_BRAKE_BALLSCREW_AXLE + D_WASHER_FIXING_BALLSCREW_TO_BED * 2; // beam lying along bed, not perpendicular to bed +R_BASE_PLATE_FIXING_LEG_BRAKE_BALLSCREW_TO_BED = get_R_plate_square_base_plate_132(D_BEAM_BRAKE); +L_LEG_FIXING_BRAKE_BALLSCREW_TO_BED = Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE - R_BASE_PLATE_FIXING_LEG_BRAKE_BALLSCREW_TO_BED[2] + D_BEAM_BRAKE / 2; +R_LEAD_FIXING_BRAKE_BALLSCREW_TO_BRAKE_ARMS = [100, 10, D_BEAM_BRAKE]; +X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE = D_BEAM_BRAKE; +ANGLE_BRAKE_ROD_MIN = 50; // angle between ballscrew axle and brake rod radius about pivot +ANGLE_BRAKE_ROD_MAX = 60; // atan((X_POS_AXLE_LEG_REAR - X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE) / Y_OFFSET_LEAD_FIXING_TO_AXLE_REAR_MIN); +SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 6; // M6 +L_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 20; // 20-25mm +D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 25; // get_metric_bolt_washer_diameter_safe_working_clearance(SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD); +T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 1.5; +R_BRAKE_PAD = [10, 75, 10]; +T_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 4.8; +W_FIXING_BRAKE_ARM_TO_BRAKE_PAD = 25.4; +R_BRAKE_ARM = [240, 75, 5]; // (X_POS_WHEEL_CENTRE - T_WHEEL / 2 - R_BRAKE_PAD[0] - T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD - X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE + tan(90 - ANGLE_BRAKE_ROD_MAX) * 75 / 2) / sin(ANGLE_BRAKE_ROD_MAX) // TOO SHORT? +L_FIXING_BRAKE_ARM_TO_BRAKE_PAD = D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD * 3; // R_BRAKE_PAD[1]; +L_BRAKE_ARM_TOTAL = R_BRAKE_ARM[0] + R_BRAKE_PAD[0] + L_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD; +// Y_OFFSET_LEAD_FIXING_TO_AXLE_REAR_MIN = 50; +X_OFFSET_FIXING_BRAKE_ARM_TO_BRAKE_PAD_FROM_END = R_BRAKE_ARM[1] / 2 * tan(ANGLE_BRAKE_ROD_MAX); +// X_OFFSET_HOLE_AXLE_FROM_BRAKE_ARM_END_INNER = (X_POS_AXLE_LEG_REAR - X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE) / tan(ANGLE_BRAKE_ROD_MAX); +DELTA_L_SPRING_BALLSCREW_MAX = get_y_pos_lead_fixing_ballscrew_to_brake_arms(ANGLE_BRAKE_ROD_MIN, Y_POS_AXLE_REAR, X_POS_AXLE_LEG_REAR, X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE) - get_y_pos_lead_fixing_ballscrew_to_brake_arms(ANGLE_BRAKE_ROD_MAX, Y_POS_AXLE_REAR, X_POS_AXLE_LEG_REAR, X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE); +SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG = 10; +D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG = 30; // get_metric_bolt_washer_diameter_safe_working_clearance(SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG); +T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG = 1.5; +D_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG = 50; +T_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG = 4; + +// ANGLE_INCLINE_TILLER = 20; // [-20:5:135] +ANGLE_INCLINE_TILLER_MAX = 101; +L_TILLER = R_BED[1] / 2 - Y_POS_AXLE_FRONT + D_AXLE_FRONT / 2 + Z_OFFSET_BED_TO_AXLE * tan(ANGLE_INCLINE_TILLER_MAX - 90); +// T_WASHER_UNIVERSAL_JOINT = 2; // Deprecated +L_TILLER_EXTENSION = 1000; +L_JOINT_TILLER_EXTENSION = 85; +SIZE_BOLT_JOINT_TILLER_EXTENSION = SIZE_BOLT_REAR_WHEEL_POSITIONING; // 6; +D_WASHER_TILLER_JOINT = D_WASHER_BOLT_REAR_WHEEL_POSITIONING; // 25; +T_WASHER_TILLER_JOINT = T_WASHER_BOLT_REAR_WHEEL_POSITIONING; // 3; +OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL = SIZE_BOLT_JOINT_TILLER_EXTENSION * 3 / 2; + +D_HANDLE_BAR = 27; +W_HANDLE_BAR = 300; + +SIZE_BOLT_FRONT_AXLE_BEARING = 20; +DEPTH_BOLT_FRONT_AXLE_BEARING = get_metric_bolt_head_height(SIZE_BOLT_FRONT_AXLE_BEARING); +T_JOINT_FRONT_AXLE_TO_TILLER = get_thickness_round_3_way_through_116(D_AXLE_FRONT); +T_WASHER_JOINT_FRONT_AXLE_TO_TILLER = 3; +D_WASHER_JOINT_FRONT_AXLE_TO_TILLER = 39; // get_metric_bolt_washer_diameter_safe_working_clearance(SIZE_BOLT_FRONT_AXLE_BEARING); +COUNT_WASHERS_JOINT_FRONT_AXLE_TO_TILLER = 3; +L_BOLT_FRONT_AXLE_BEARING = T_JOINT_FRONT_AXLE_TO_TILLER + 2 * DEPTH_BOLT_FRONT_AXLE_BEARING + D_AXLE_FRONT + COUNT_WASHERS_JOINT_FRONT_AXLE_TO_TILLER * T_WASHER_JOINT_FRONT_AXLE_TO_TILLER; + +T_WASHER_BASE_PLATE = T_WASHER_BOLT_REAR_WHEEL_POSITIONING; +D_WASHER_BASE_PLATE = D_WASHER_BOLT_REAR_WHEEL_POSITIONING; + +L_SHAFT_TOP_CRATE = 333; +D_SHAFT_TOP_CRATE = 16; +D_WASHER_SHAFT_TOP_CRATE = 50; // get_metric_bolt_washer_diameter_safe_working_clearance(D_SHAFT_TOP_CRATE); +T_WASHER_SHAFT_TOP_CRATE = 3; +COUNT_SHAFTS_TOP_CRATE_X = 2; +COUNT_SHAFTS_TOP_CRATE_Y = 3; +COUNT_WASHERS_SHAFT_TOP_CRATE_EACH_END = 3; + + +// Constants +SAFETY_FACTOR = 2; +PI = 3.1415926536; +G = 9.81; + +COLOUR_ROD_THREADED = "Gray"; +COLOUR_BEAM_ALUMINIUM = "DarkGray"; +COLOUR_FILAMENT_3D_PRINTER = "HotPink"; + + +// Engineering analysis +W_TOTAL_SAFE = M_TOTAL * G * SAFETY_FACTOR; + +SHEAR_STRESS_YIELD_STAINLESS_STEEL = 200 * 10 ^ 6; +SHEAR_STRESS_YIELD_ALUMINIUM = 200 * 10 ^ 6; + +/* +T_BOLT_MAX = PI * (D_AXLE_FRONT / 1000) ^ 3 / 16 * SHEAR_STRESS_YIELD_ALUMINIUM; + +T_BOLT_ACTUAL = W_TOTAL_SAFE * (3 * T_BEAM / 1000); +*/ + +T_FRONT_WHEEL_AXIS_CENTRE_Y = W_TOTAL_SAFE * (R_BED[1] / 2 + T_WHEEL / 2) / 1000; +T_FRONT_WHEEL_AXIS_X = W_TOTAL_SAFE * (D_WHEEL / 2) / 1000; + +F_FRONT_WHEEL_AXIS_INTERSECTION_Z_MAX = SHEAR_STRESS_YIELD_ALUMINIUM * PI * (SIZE_BOLT / 1000) ^ 3 / 32 / ((R_BED[0] + T_WHEEL) / 1000); + +T_REAR_WHEEL_AXIS_Y_MAX = PI * (D_AXLE_REAR / 1000) ^ 3 / 16 * SHEAR_STRESS_YIELD_ALUMINIUM; +// T_REAR_WHEEL_AXIS_Y_ACTUAL = W_TOTAL_SAFE * (T_WHEEL / 2 + SPACING_XY_BED_BORDER + R_FIXING_ROUND[0] / 2) / 1000; + +/* output +// echo("L_TILLER: ", L_TILLER, "mm"); +echo("load safe max: ", W_TOTAL_SAFE, "N"); +echo("T_front_wheel_axis_centre_y: ", T_FRONT_WHEEL_AXIS_CENTRE_Y, "Nm"); +echo("T_front_wheel_axis_x: ", T_FRONT_WHEEL_AXIS_X, "Nm - fully dispersed by wheel"); +echo("F_front_wheel_axis_intersection_z_max: ", F_FRONT_WHEEL_AXIS_INTERSECTION_Z_MAX, "N"); +echo("T_rear_wheel_axis_y_max: ", T_REAR_WHEEL_AXIS_Y_MAX, "Nm"); +echo("T_rear_wheel_axis_y_actual: ", T_REAR_WHEEL_AXIS_Y_ACTUAL, "Nm"); +*/ \ No newline at end of file diff --git a/docs/.~lock.UBOM.ods# b/docs/.~lock.UBOM.ods# new file mode 100644 index 0000000..6c2e65a --- /dev/null +++ b/docs/.~lock.UBOM.ods# @@ -0,0 +1 @@ +,teddy,lord-T-1024,20.02.2025 13:01,file:///home/teddy/.config/libreoffice/4; \ No newline at end of file diff --git a/docs/UBOM.ods b/docs/UBOM.ods new file mode 100644 index 0000000000000000000000000000000000000000..6c52c2752c80bcbe653dff1ee22c16e12f0916f9 GIT binary patch literal 98306 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

1c;U?p= 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 +use <./models/dog_cart/dog_cart.scad>; + +// Customisable parameters +angle_incline_tiller = 20; // [-20:5:135] +angle_brake_rod = 60; // [45:5:60] + +$fn = 100; + +// output +dog_cart(angle_incline_tiller, angle_brake_rod); + +/* +Shopping +Components + +Tools +M10 tap (HSS) - size change, check spreadsheet +*/ \ No newline at end of file diff --git a/models/bed/bed.scad b/models/bed/bed.scad new file mode 100644 index 0000000..67a8f34 --- /dev/null +++ b/models/bed/bed.scad @@ -0,0 +1,41 @@ +include <../../config.scad>; +use <../fixings/tube_clamp_round_base_plate_132.scad>; + +module bed() { + offset_hole_y_front = get_offset_hole_y_round_base_plate_132(D_AXLE_FRONT); + d_hole_front = get_diameter_hole_round_base_plate_132(D_AXLE_FRONT); + offset_hole_y_rear = get_offset_hole_y_round_base_plate_132(D_AXLE_REAR); + d_hole_rear = get_diameter_hole_round_base_plate_132(D_AXLE_REAR); + count_shafts_y = 3; + color("burlywood") difference() { + cube(R_BED, center = true); + // front axle leg holes + translate([0, Y_POS_AXLE_FRONT, 0]) for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + translate([0, offset_hole_y_front, 0]) cylinder(R_BED[2], d_hole_front / 2, d_hole_front / 2, center = true); + } + } + // rear axle leg holes + translate([0, Y_POS_AXLE_REAR, 0]) for (index_side_x = [0 : 1 : 1]) { + mirror([index_side_x, 0, 0]) { + translate([X_POS_AXLE_LEG_REAR, 0, 0]) for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + translate([0, offset_hole_y_rear, 0]) cylinder(R_BED[2], d_hole_rear / 2, d_hole_rear / 2, center = true); + } + } + } + } + // top crate perimeter shaft holes + for (index_side_x = [0 : 1 : 1]) { + mirror([index_side_x, 0, 0]) { + translate([R_BED[0] / 2 - D_WASHER_SHAFT_TOP_CRATE / 2, 0, 0]) for (index_shaft_y = [0 : 1 : count_shafts_y]) { + translate([0, -R_BED[1] / 2 + D_WASHER_SHAFT_TOP_CRATE / 2 + index_shaft_y * (R_BED[1] - D_WASHER_SHAFT_TOP_CRATE) / (count_shafts_y - 1), 0]) cylinder(R_BED[2], D_SHAFT_TOP_CRATE / 2, D_SHAFT_TOP_CRATE / 2, center = true); + } + } + } + } + // Shopping + echo(str("Bed: MDF board ", R_BED[1], "mm x ", R_BED[0], "mm x ", R_BED[2], "mm - x1")); +} + +bed(); \ No newline at end of file diff --git a/models/brake/beam_leg_ballscrew_to_bed.scad b/models/brake/beam_leg_ballscrew_to_bed.scad new file mode 100644 index 0000000..329a5df --- /dev/null +++ b/models/brake/beam_leg_ballscrew_to_bed.scad @@ -0,0 +1,10 @@ +include <../../config.scad>; +use <../common/beam_hollow_square.scad>; + +module beam_leg_ballscrew_to_bed() { + color(COLOUR_BEAM_ALUMINIUM) beam_hollow_square(L_LEG_FIXING_BRAKE_BALLSCREW_TO_BED, D_BEAM_BRAKE, T_BEAM_BRAKE); + // Shopping + // Beam leg ballscrew to bed +} + +beam_leg_ballscrew_to_bed(); \ No newline at end of file diff --git a/models/brake/brake_arm.scad b/models/brake/brake_arm.scad new file mode 100644 index 0000000..1868d25 --- /dev/null +++ b/models/brake/brake_arm.scad @@ -0,0 +1,16 @@ +include <../../config.scad>; + + +module brake_arm() { + L_big = 2 * max(R_BRAKE_ARM); + color(COLOUR_BEAM_ALUMINIUM) difference() { + // body + cube(R_BRAKE_ARM, center = true); + // chamfer across end face for wheel overlap + translate([R_BRAKE_ARM[0] / 2 - R_BRAKE_ARM[1] / 2 * tan(ANGLE_BRAKE_ROD_MAX), 0, 0]) rotate([0, 0, 90 - ANGLE_BRAKE_ROD_MAX]) translate([0, -L_big / 2, -L_big / 2]) cube(L_big, center = false); + } + // Shopping + echo(str("Brake arm: Aluminium sheet ", R_BRAKE_ARM[1], "mm x ", R_BRAKE_ARM[0], "mm x ", R_BRAKE_ARM[2], "mm - x1")); +} + +brake_arm(); diff --git a/models/brake/brake_assembly.scad b/models/brake/brake_assembly.scad new file mode 100644 index 0000000..7d1d16a --- /dev/null +++ b/models/brake/brake_assembly.scad @@ -0,0 +1,76 @@ +include <../../config.scad>; +use <../common/metric_bolt.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/washer.scad>; +use <../fixings/tube_clamp_square_base_plate_132.scad>; +use <../fixings/tube_clamp_square_base_plate_132_functions.scad>; +use <./brake_assembly_functions.scad>; +use <./fixing_ballscrew_to_bed.scad>; +use <./power_wheel_assembly.scad>; +use <./fixing_brake_ballscrew_to_brake_arms.scad>; +use <./brake_arm.scad>; +use <./fixing_brake_arm_to_brake_pad.scad>; +use <./brake_pad.scad>; +use <./fixing_brake_arm_to_rear_axle_leg.scad>; +use <./brake_spring_load_assembly.scad>; + + + +module brake_assembly(angle_brake_rod) { + echo("Brake assembly:"); + // Y_POS_LEAD_FIXING_BALLSCREW_TO_BRAKE_ARMS + y_pos_lead_fixing_ballscrew_to_brake_arms = get_y_pos_lead_fixing_ballscrew_to_brake_arms(angle_brake_rod, Y_POS_AXLE_REAR, X_POS_AXLE_LEG_REAR, X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE); + y_pos_ballscrew_end_front = -R_BED[1] / 2 + L_BRAKE_BALLSCREW_AXLE; + union() { + // ballscrew axle + color(COLOUR_ROD_THREADED) translate([0, y_pos_ballscrew_end_front, -Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE]) rotate([90, 0, 0]) cylinder(L_BRAKE_BALLSCREW_AXLE, D_BRAKE_BALLSCREW_AXLE / 2, D_BRAKE_BALLSCREW_AXLE / 2, center = false); + // fixing ballscrew to bed front + translate([0, y_pos_ballscrew_end_front - Y_OFFSET_BALLSCREW_LEG_FRONT_FIXING_FROM_END, 0]) fixing_ballscrew_to_bed(); + // fixing ballscrew to bed rear + translate([0, -R_BED[1] / 2 + Y_OFFSET_BALLSCREW_LEG_REAR_FIXING_FROM_END, 0]) fixing_ballscrew_to_bed(); + // ballscrew power wheel + translate([0, -R_BED[1] / 2 + Y_OFFSET_BALLSCREW_LEG_REAR_FIXING_FROM_END - D_BEAM_BRAKE / 2 - T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL - T_BRAKE_BALLSCREW_POWER_WHEEL / 2, -Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE]) power_wheel_assembly(); + // ballscrew power wheel washer + translate([0, -R_BED[1] / 2 + Y_OFFSET_BALLSCREW_LEG_REAR_FIXING_FROM_END - D_BEAM_BRAKE / 2 - T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL / 2, -Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE]) rotate([90, 0, 0]) washer(T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_AXLE); + // fixing ballscrew to brake rod + translate([0, y_pos_lead_fixing_ballscrew_to_brake_arms, -Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE]) { + fixing_brake_ballscrew_to_brake_arms(); + + for (index_side_x = [0:1:1]) { + mirror([index_side_x, 0, 0]) { + translate([X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE, 0, 0]) rotate([0, 0, -(90 - angle_brake_rod)]) { + // brake arm + translate([R_BRAKE_ARM[0] / 2, 0, 0]) brake_arm(); + // fixing brake arm to brake pad + translate([R_BRAKE_ARM[0] - X_OFFSET_FIXING_BRAKE_ARM_TO_BRAKE_PAD_FROM_END, 0, R_BRAKE_ARM[2] / 2]) rotate([0, 0, 90 - ANGLE_BRAKE_ROD_MAX]) fixing_brake_arm_to_brake_pad(); + // brake pad + translate([R_BRAKE_ARM[0] - X_OFFSET_FIXING_BRAKE_ARM_TO_BRAKE_PAD_FROM_END, 0, R_BRAKE_ARM[2] / 2 + T_FIXING_BRAKE_ARM_TO_BRAKE_PAD + (W_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_FIXING_BRAKE_ARM_TO_BRAKE_PAD) / 2]) rotate([0, 0, 90 - ANGLE_BRAKE_ROD_MAX]) translate([T_FIXING_BRAKE_ARM_TO_BRAKE_PAD, 0, 0]) brake_pad(); + } + // fixing brake arm to rear axle leg + translate([X_POS_AXLE_LEG_REAR, -y_pos_lead_fixing_ballscrew_to_brake_arms + Y_POS_AXLE_REAR, 0]) fixing_brake_arm_to_rear_axle_leg(); + } + } + } + // Spring-loading assembly + translate([0, y_pos_ballscrew_end_front - Y_OFFSET_BALLSCREW_LEG_FRONT_FIXING_FROM_END + D_BEAM_BRAKE / 2, -Z_OFFSET_BALLSCREW_AXLE_TO_BED_BASE]) brake_spring_load_assembly(); + } + + // Shopping + echo(str("Ballscrew axle: Threaded Steel rod M", D_BRAKE_BALLSCREW_AXLE, " x ", L_BRAKE_BALLSCREW_AXLE, " - x1")); + // Fixing ballscrew to bed front + // Fixing ballscrew to bed rear + // Ballscrew power wheel + // Ballscrew power wheel washer + // Fixing ballscrew to brake arms + // Brake arms + // Fixings brake arm to brake pad + // Brake pads + // fixing brake arm to rear axle leg + // Spring-load assembly +} + + +angle_brake_rod = ANGLE_BRAKE_ROD_MAX; + +brake_assembly(angle_brake_rod); + diff --git a/models/brake/brake_assembly_functions.scad b/models/brake/brake_assembly_functions.scad new file mode 100644 index 0000000..d319680 --- /dev/null +++ b/models/brake/brake_assembly_functions.scad @@ -0,0 +1,3 @@ +// include <../../config.scad>; // circular reference! + +function get_y_pos_lead_fixing_ballscrew_to_brake_arms(angle_brake_rod, y_pos_axle_rear, x_pos_axle_leg_rear, x_offset_fixing_brake_arm_to_lead_plate) = y_pos_axle_rear + (x_pos_axle_leg_rear - x_offset_fixing_brake_arm_to_lead_plate) / tan(angle_brake_rod); // (X_POS_AXLE_LEG_REAR - X_OFFSET_FIXING_BRAKE_ARM_TO_LEAD_PLATE) \ No newline at end of file diff --git a/models/brake/brake_pad.scad b/models/brake/brake_pad.scad new file mode 100644 index 0000000..a8b9608 --- /dev/null +++ b/models/brake/brake_pad.scad @@ -0,0 +1,13 @@ +include <../../config.scad>; + + +module brake_pad() { + union() { + color("black") cube(R_BRAKE_PAD, center = true); + color("gray") translate([-R_BRAKE_PAD[0] / 2 - L_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, center = true); + } + // Shopping + echo(str("Brake pad: Bike V-brake pad - x1")); +} + +brake_pad(); \ No newline at end of file diff --git a/models/brake/brake_spring_load_assembly.scad b/models/brake/brake_spring_load_assembly.scad new file mode 100644 index 0000000..e76a831 --- /dev/null +++ b/models/brake/brake_spring_load_assembly.scad @@ -0,0 +1,43 @@ +include <../../config.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/metric_nut.scad>; +use <../common/compression_spring.scad>; +use <../common/washer.scad>; + + +module brake_spring_load_assembly() { + echo("Brake spring-load assembly:"); + /* design variables + echo(str("DELTA_L_SPRING_BALLSCREW_MAX: ", DELTA_L_SPRING_BALLSCREW_MAX, "mm")); = 19 + */ + L_spring_free = 110; + d_spring_outer = 21.6; + d_spring_wire = 1.6; + pitch = L_spring_free / 8; + + h_nut = get_metric_bolt_head_height(D_BRAKE_BALLSCREW_AXLE); + d_nut = get_metric_bolt_head_diameter(D_BRAKE_BALLSCREW_AXLE); + + union() { + // washer rear + rotate([-90, 0, 0]) washer(T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_AXLE, false); + // spring + translate([0, T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL + L_spring_free / 2, 0]) rotate([-90, 0, 0]) compression_spring(L_spring_free, d_spring_outer, d_spring_outer - d_spring_wire * 2, pitch); + // washer front + translate([0, T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL + L_spring_free, 0]) rotate([-90, 0, 0]) washer(T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_AXLE, false); + // nut(s) + color("gray") for (index_nut = [0 : 1 : 1]) { + translate([0, T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL * 2 + L_spring_free + index_nut * h_nut, 0]) rotate([-90, 0, 0]) rotate([0, 0, index_nut * 30]) metric_nut(D_BRAKE_BALLSCREW_AXLE, centre = false); // cylinder(h_nut, d_nut / 2, d_nut / 2, center = false); + } + } + // Shopping + // spring + // https://uk.rs-online.com/web/p/compression-springs/0121242 + // washers + // nuts +} + +// $fn = 20; +brake_spring_load_assembly(); + + diff --git a/models/brake/fixing_ballscrew_to_bed.scad b/models/brake/fixing_ballscrew_to_bed.scad new file mode 100644 index 0000000..04d8317 --- /dev/null +++ b/models/brake/fixing_ballscrew_to_bed.scad @@ -0,0 +1,42 @@ +include <../../config.scad>; +use <../common/metric_bolt.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/washer.scad>; +use <../fixings/tube_clamp_square_base_plate_132.scad>; +use <../fixings/tube_clamp_square_base_plate_132_functions.scad>; +use <./beam_leg_ballscrew_to_bed.scad>; + + +module fixing_ballscrew_to_bed() { + echo("Fixing ballscrew to bed: "); + y_offset_hole_bed_fastener = get_offset_hole_x_square_base_plate_132(D_BEAM_BRAKE); + d_hole_fastener = get_diameter_hole_square_base_plate_132(); + h_head_fastener = get_metric_bolt_head_height(d_hole_fastener); + L_fastener = R_BED[2] + 2 * (T_WASHER_BASE_PLATE + h_head_fastener) + R_BASE_PLATE_FIXING_LEG_BRAKE_BALLSCREW_TO_BED[2] + L_BOLT_EXTENSION; + // d_washer_outer = get_metric_bolt_washer_diameter_safe_working_clearance(d_hole_fastener); + union() { + // fixing tube clamp + rotate([0, 180, 90]) tube_clamp_square_base_plate_132(D_BEAM_BRAKE); + + for (index_side_y = [0:1:1]) { + mirror([0, index_side_y, 0]) translate([0, y_offset_hole_bed_fastener, 0]) { + // fastener bolt + translate([0, 0, -L_fastener / 2 + R_BED[2] + T_WASHER_BASE_PLATE + h_head_fastener]) metric_bolt(d_hole_fastener, L_fastener, true, L_BOLT_EXTENSION); + // fastener washers + // bed side + translate([0, 0, R_BED[2] + T_WASHER_BASE_PLATE / 2]) washer(T_WASHER_BASE_PLATE, D_WASHER_BASE_PLATE, d_hole_fastener); + // axle side + translate([0, 0, -R_BASE_PLATE_FIXING_LEG_BRAKE_BALLSCREW_TO_BED[2] - T_WASHER_BASE_PLATE / 2]) washer(T_WASHER_BASE_PLATE, D_WASHER_BASE_PLATE, d_hole_fastener); + } + } + // leg + translate([0, 0, -R_BASE_PLATE_FIXING_LEG_BRAKE_BALLSCREW_TO_BED[2] - L_LEG_FIXING_BRAKE_BALLSCREW_TO_BED / 2]) beam_leg_ballscrew_to_bed(); + } + // Shopping + // Fixing leg to bed + // Fixing fasteners + // Fixing fastener washers + // Leg +} + +fixing_ballscrew_to_bed(); diff --git a/models/brake/fixing_brake_arm_to_brake_pad.scad b/models/brake/fixing_brake_arm_to_brake_pad.scad new file mode 100644 index 0000000..3421cba --- /dev/null +++ b/models/brake/fixing_brake_arm_to_brake_pad.scad @@ -0,0 +1,50 @@ +include <../../config.scad>; +use <../common/angle_beam.scad>; +use <../common/metric_bolt.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/washer.scad>; + + +module fixing_brake_arm_to_brake_pad() { + echo("Fixing brake arm to brake pad:"); + h_head_fastener = get_metric_bolt_head_height(SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD); + L_fastener = 2 * (h_head_fastener + T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD) + R_BRAKE_ARM[2] + T_FIXING_BRAKE_ARM_TO_BRAKE_PAD + L_BOLT_EXTENSION; + union() { + // fixing + color(COLOUR_BEAM_ALUMINIUM) difference() { + // body + rotate([90, 0, 180]) translate([0, 0, -L_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2]) angle_beam(L_FIXING_BRAKE_ARM_TO_BRAKE_PAD, W_FIXING_BRAKE_ARM_TO_BRAKE_PAD, T_FIXING_BRAKE_ARM_TO_BRAKE_PAD, false); + // brake pad fastener hole + translate([0, 0, T_FIXING_BRAKE_ARM_TO_BRAKE_PAD + (W_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_FIXING_BRAKE_ARM_TO_BRAKE_PAD) / 2]) rotate([0, 90, 0]) cylinder(W_FIXING_BRAKE_ARM_TO_BRAKE_PAD * 2, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, center = true); + // brake arm fastener holes + for (index_side_y = [0:1:1]) { + mirror([0, index_side_y, 0]) { + translate([-T_FIXING_BRAKE_ARM_TO_BRAKE_PAD - (W_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_FIXING_BRAKE_ARM_TO_BRAKE_PAD) / 2, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, 0]) cylinder(W_FIXING_BRAKE_ARM_TO_BRAKE_PAD * 2, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, center = true); + } + } + } + // fasteners to brake arm + for (index_side_y = [0:1:1]) { + mirror([0, index_side_y, 0]) { + translate([-T_FIXING_BRAKE_ARM_TO_BRAKE_PAD - (W_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_FIXING_BRAKE_ARM_TO_BRAKE_PAD) / 2, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, 0]) { + // bolt + translate([0, 0, -L_fastener / 2 + T_FIXING_BRAKE_ARM_TO_BRAKE_PAD + T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD + h_head_fastener]) metric_bolt(SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, L_fastener, true, L_BOLT_EXTENSION); + // washers + // upper + translate([0, 0, T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2 + T_FIXING_BRAKE_ARM_TO_BRAKE_PAD]) washer(T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD); + // lower + translate([0, 0, -T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2 - R_BRAKE_ARM[2]]) washer(T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD); + } + } + } + // fastener to brake pad + // washer + translate([-T_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD / 2, 0, T_FIXING_BRAKE_ARM_TO_BRAKE_PAD + (W_FIXING_BRAKE_ARM_TO_BRAKE_PAD - T_FIXING_BRAKE_ARM_TO_BRAKE_PAD) / 2]) rotate([0, 90, 0]) washer(T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD, SIZE_BOLT_FIXING_BRAKE_ARM_TO_BRAKE_PAD); + } + // Shopping + // Angle beam + // Fasteners + // Washers +} + +fixing_brake_arm_to_brake_pad(); \ No newline at end of file diff --git a/models/brake/fixing_brake_arm_to_rear_axle_leg.scad b/models/brake/fixing_brake_arm_to_rear_axle_leg.scad new file mode 100644 index 0000000..365541a --- /dev/null +++ b/models/brake/fixing_brake_arm_to_rear_axle_leg.scad @@ -0,0 +1,35 @@ +include <../../config.scad>; +use <../common/metric_bolt.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/washer.scad>; + + +module fixing_brake_arm_to_rear_axle_leg() { + echo("Fixing brake arm to rear axle leg:"); + count_washers_each_end = 3; + h_nut = get_metric_bolt_head_height(SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG); + L_bolt = D_AXLE_REAR + 2 * (T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG * count_washers_each_end + h_nut) + L_BOLT_EXTENSION; + rotate([0, 0, ANGLE_BRAKE_ROD_MAX]) for (index_side_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_z]) translate([0, 0, R_BRAKE_ARM[2] / 2]) { + // axle washer + translate([0, 0, 0]) washer(T_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, D_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, D_AXLE_REAR, centre = false); + // bolt + translate([0, -L_bolt / 2 + D_AXLE_REAR / 2 + T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG + h_nut, T_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG + D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG / 2]) rotate([-90, 0, 0]) metric_bolt(SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, L_bolt, true, L_BOLT_EXTENSION); + // bolt washer + for (index_washer = [0 : 1 : count_washers_each_end]) { + // front + translate([0, D_AXLE_REAR / 2 + index_washer * T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, T_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG + D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG / 2]) rotate([-90, 0, 0]) washer(T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, centre = false); + // rear + translate([0, -D_AXLE_REAR / 2 - index_washer * T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, T_WASHER_AXLE_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG + D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG / 2]) rotate([90, 0, 0]) washer(T_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, D_WASHER_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, SIZE_BOLT_FIXING_BRAKE_ARM_TO_REAR_AXLE_LEG, centre = false); + } + } + } + // Shopping + // Axle washers + // Bolts + // Bolt washers front + // Bolt washers rear +} + +fixing_brake_arm_to_rear_axle_leg(); + diff --git a/models/brake/fixing_brake_ballscrew_to_brake_arms.scad b/models/brake/fixing_brake_ballscrew_to_brake_arms.scad new file mode 100644 index 0000000..66434ce --- /dev/null +++ b/models/brake/fixing_brake_ballscrew_to_brake_arms.scad @@ -0,0 +1,29 @@ +include <../../config.scad>; +use <../common/metric_nut.scad>; +use <../common/washer.scad>; + +module fixing_brake_ballscrew_to_brake_arms() { + h_nut = get_metric_bolt_head_height(D_BRAKE_BALLSCREW_AXLE); + count_nuts_each_side = 2; + union() { + // ballscrew positioning plate + color(COLOUR_FILAMENT_3D_PRINTER) cube(R_LEAD_FIXING_BRAKE_BALLSCREW_TO_BRAKE_ARMS, center = true); + + for (index_side_y = [0:1:1]) { + mirror([0, index_side_y, 0]) { + // washers + translate([0, R_LEAD_FIXING_BRAKE_BALLSCREW_TO_BRAKE_ARMS[1] / 2 + T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL / 2, 0]) rotate([-90, 0, 0]) washer(T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_WASHER_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_AXLE); + // nuts + for (index_nut = [0 : 1 : count_nuts_each_side - 1]) { + translate([0, R_LEAD_FIXING_BRAKE_BALLSCREW_TO_BRAKE_ARMS[1] / 2 + T_WASHER_BRAKE_BALLSCREW_POWER_WHEEL + h_nut * index_nut, 0]) rotate([-90, 0, 0]) rotate([0, 0, 30 * index_nut]) metric_nut(D_BRAKE_BALLSCREW_AXLE, centre = false); + } + } + } + } + // Shopping + echo("Fixing brake ballscrew to brake arms: 3D printed component - x1"); + // Axle fastener washers + // Axle fastener nuts +} + +fixing_brake_ballscrew_to_brake_arms(); \ No newline at end of file diff --git a/models/brake/power_wheel_assembly.scad b/models/brake/power_wheel_assembly.scad new file mode 100644 index 0000000..99cecb4 --- /dev/null +++ b/models/brake/power_wheel_assembly.scad @@ -0,0 +1,39 @@ +include <../../config.scad>; +use <../common/beam_hexagonal.scad> +use <../common/metric_nut.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/washer.scad> + + +module power_wheel_assembly() { + echo("Power wheel assembly:"); + d_nut = get_metric_bolt_head_diameter(D_BRAKE_BALLSCREW_AXLE); + h_nut = get_metric_bolt_head_height(D_BRAKE_BALLSCREW_AXLE); + union() { + // power wheel + rotate([90, 0, 0]) { + color(COLOUR_FILAMENT_3D_PRINTER) difference() { + // body + cylinder(T_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_POWER_WHEEL / 2, D_BRAKE_BALLSCREW_POWER_WHEEL / 2, center = true); + // nut slot + beam_hexagonal(h_nut, d_nut, centre = true, suppress_shopping_outputs = true); // cylinder(T_BRAKE_BALLSCREW_POWER_WHEEL, d_nut / 2, d_nut / 2, center = true); + } + // ballscrew bearing (nut) + /* + color("gray") difference() { + // body + cylinder(T_BRAKE_BALLSCREW_POWER_WHEEL, d_nut / 2, d_nut / 2, center = true); + // hole + cylinder(T_BRAKE_BALLSCREW_POWER_WHEEL, D_BRAKE_BALLSCREW_AXLE / 2, D_BRAKE_BALLSCREW_AXLE / 2, center = true); + } + */ + metric_nut(D_BRAKE_BALLSCREW_AXLE); + } + } + // Shopping + echo("Power wheel: 3D printed component - x1"); + // Power wheel bearing (nut) +} + +power_wheel_assembly(); + diff --git a/models/common/angle_beam.scad b/models/common/angle_beam.scad new file mode 100644 index 0000000..82bd2dc --- /dev/null +++ b/models/common/angle_beam.scad @@ -0,0 +1,13 @@ + +module angle_beam(L, w, t, centre = true) { + R_offset_centre = [-w / 2, -w / 2, -L / 2]; + translate(centre ? R_offset_centre : [0, 0, 0]) union() { + cube([w, t, L], center = false); + cube([t, w, L], center = false); + } + // Shopping + echo(str("Rectangular Aluminium angle beam: Rectangular Aluminium angle beam ", L, "mm x ", w, "mm x ", t, "mm - x1")); + // https://www.metals4u.co.uk/materials/aluminium/aluminium-angle/aa25-4x25-4x4-8-p +} + +angle_beam(500, 50, 5); \ No newline at end of file diff --git a/models/common/ball_socket_joint.scad b/models/common/ball_socket_joint.scad new file mode 100644 index 0000000..5c4d02c --- /dev/null +++ b/models/common/ball_socket_joint.scad @@ -0,0 +1,51 @@ +include <../../config.scad>; + +/* +function get_universal_joint_length() = 40; +function get_universal_joint_d_bore_hole() = 6; +function get_universal_joint_d_hole() = 4; +function get_universal_joint_d() = 11; +function get_universal_joint_thickness() = (get_universal_joint_d() - get_universal_joint_d_bore_hole()) / 2; +function get_universal_joint_joint_axial_offset() = get_universal_joint_thickness() * 2; +function get_universal_joint_pin_axial_offset() = get_universal_joint_thickness() + get_universal_joint_d_hole() / 2; + +module ball_socket_joint() { + L = get_universal_joint_length(); + t = get_universal_joint_thickness(); + joint_axial_offset = get_universal_joint_joint_axial_offset(); + translate([L / 2, 0, 0]) mirror([1, 0, 0]) universal_joint_half(); + translate([L / 2 - joint_axial_offset, 0, 0]) rotate([90, -ANGLE_INCLINE_TILLER, 0]) translate([-joint_axial_offset, 0, 0]) universal_joint_half(); +} + +module universal_joint_half() { + d_hole_bore = get_universal_joint_d_bore_hole(); + d_hole = get_universal_joint_d_hole(); + d = get_universal_joint_d(); + L = get_universal_joint_length(); + t = get_universal_joint_thickness(); + joint_axial_offset = get_universal_joint_joint_axial_offset(); + pin_axial_offset = get_universal_joint_pin_axial_offset(); + color("orange") union() { + difference() { + // body + rotate([0, 90, 0]) cylinder(L / 2, d / 2, d / 2, center = false); + // threaded hole + translate([L - pin_axial_offset, 0, 0]) cylinder(d, d_hole / 2, d_hole / 2, center = true); + // bore hole + rotate([0, 90, 0]) cylinder(L / 2, d_hole / 2, d_hole / 2, center = false); + // joint slot + translate([L / 8, 0, 0]) cube([L / 4, d - t * 2, d], center = true); + } + // joint + translate([joint_axial_offset, 0, 0]) rotate([90, 0, 0]) cylinder(d, t, t, center = true); + } +} + +// output +translate([100, 0, 0]) universal_joint_half(); +universal_joint(); + +*/ + +// shopping +// https://www.amazon.co.uk/HiPicco-Universal-M5-Automotive-Cupboard/dp/B0BK28WXY8/ref=sr_1_21?crid=6A6OMRNKNXFR&dib=eyJ2IjoiMSJ9.e8gSWrg3UPxR5gMbATNC91I6qERE0rN5FCcOtnZJmGbFIHW9Rz6Rtq02WZj_C2CYgbwA8KHdd1W1xyOxZrH60UtwiGKd9MkmAbd09h9ACi4yGnbOLjhWb-Iboe0IZ_tvxh3XFdo4ygZ-iV98DODCXzl1WdVpTyUg3N4bok5qGtTP2CWfzPOmUFwyTe7_snV4fb7jlTGHK_ks3tR4FSDiUtCwEnuzxJUqdZSRNp4EhGo.2_e9Kal7A7FfEcIzWVEzQXH2zOWiECkGj9UqjIb_8XQ&dib_tag=se&keywords=metric%2Bball%2BJOINT&qid=1739814661&sprefix=metric%2Bball%2Bjoint%2Caps%2C99&sr=8-21&th=1 \ No newline at end of file diff --git a/models/common/beam_hexagonal.scad b/models/common/beam_hexagonal.scad new file mode 100644 index 0000000..aaecfab --- /dev/null +++ b/models/common/beam_hexagonal.scad @@ -0,0 +1,13 @@ +// include <../../config.scad>; + +module beam_hexagonal(L, d, centre = true, suppress_shopping_outputs = false) { + radius = d / 2; + linear_extrude(L, center = centre) polygon([[radius, 0], [radius * cos(60), radius * sin(60)], [radius * cos(120), radius * sin(120)], [radius * cos(180), radius * sin(180)], [radius * cos(240), radius * sin(240)], [radius * cos(300), radius * sin(300)]]); + // Shopping + if (!suppress_shopping_outputs) { + echo(str("Hexagonal beam: Hexagonal beam Φ", d, "mm x ", L, "mm - x1")); + } +} + +// $fn = 200; +beam_hexagonal(500, 50); \ No newline at end of file diff --git a/models/common/beam_hollow_rectangular.scad b/models/common/beam_hollow_rectangular.scad new file mode 100644 index 0000000..cce4264 --- /dev/null +++ b/models/common/beam_hollow_rectangular.scad @@ -0,0 +1,13 @@ + +module beam_hollow_rectangular(L, w, d, t, suppress_shopping_outputs = false) { + difference() { + cube([w, d, L], center = true); + cube([w - t * 2, d - t * 2, L], center = true); + } + // Shopping + if (!suppress_shopping_outputs) { + echo(str("Rectangular Aluminium hollow beam: Rectangular Aluminium hollow beam ", L, "mm x ", w, "mm x ", d, "mm x ", t, "mm - x1")); + } +} + +beam_hollow_rectangular(500, 50, 30, 5); \ No newline at end of file diff --git a/models/common/beam_hollow_square.scad b/models/common/beam_hollow_square.scad new file mode 100644 index 0000000..dcd84e8 --- /dev/null +++ b/models/common/beam_hollow_square.scad @@ -0,0 +1,10 @@ +include <../../config.scad>; +use <./beam_hollow_rectangular.scad>; + +module beam_hollow_square(L, D, T) { + color(COLOUR_BEAM_ALUMINIUM) beam_hollow_rectangular(L, D, D, T, suppress_shopping_outputs = true); + // Shopping + echo(str("Square Aluminium hollow beam: Square Aluminium hollow beam ", L, "mm x ", D, "mm x ", D, "mm x ", T, "mm - x1")); +} + +beam_hollow_square(L, D, T); \ No newline at end of file diff --git a/models/common/compression_spring.json b/models/common/compression_spring.json new file mode 100644 index 0000000..b2b4dd1 --- /dev/null +++ b/models/common/compression_spring.json @@ -0,0 +1,7 @@ +{ + "parameterSets": { + "ANGLE": "" + }, + "parameterSets": "", + "fileFormatVersion": "1" +} diff --git a/models/common/compression_spring.scad b/models/common/compression_spring.scad new file mode 100644 index 0000000..a45999b --- /dev/null +++ b/models/common/compression_spring.scad @@ -0,0 +1,23 @@ +// include <../../config.scad>; + +module compression_spring(L_free, d_outer, d_inner, pitch) { + r_wire = (d_outer - d_inner) / 2; + r_mean = (d_outer + d_inner) / 4; + angle_rotation = 360 * L_free / pitch; + color("DimGray") union() { + difference() { + // spiral + linear_extrude(height = L_free - r_wire * 2, center = true, convexity = 10, twist = angle_rotation) translate([r_mean, 0, 0]) scale([1, 3, 1]) circle(r_wire); + // end blocks + } + // ring top + translate([0, 0, L_free / 2 - r_wire]) rotate_extrude(angle = 360) translate([r_mean, 0, 0]) circle(r_wire); + // ring bottom + translate([0, 0, -L_free / 2 + r_wire]) rotate_extrude(angle = 360) translate([r_mean, 0, 0]) circle(r_wire); + } + // Shopping + echo(str("Compression spring: Compression spring Φ", d_outer, "mm x ", d_inner, "mm x ", L_free, "mm - x1")); +} + +// $fn = 20; +compression_spring(100, 25, 20, 10); diff --git a/models/common/hollow_cuboid.scad b/models/common/hollow_cuboid.scad new file mode 100644 index 0000000..6b274e9 --- /dev/null +++ b/models/common/hollow_cuboid.scad @@ -0,0 +1,12 @@ +// include <../../config.scad>; + +module hollow_cuboid(R, t) { + difference() { + cube(R, center = true); + cube([R[0] - t * 2, R[1] - t * 2, R[2] - t * 2], center = true); + } + // Shopping + echo(str("Hollow cuboid: Hollow cuboid ", R[0], "mm x ", R[1], "mm x ", R[2], "mm x ", R[3], "mm - x1")); +} + +hollow_cuboid([100, 200, 300], 5); \ No newline at end of file diff --git a/models/common/metric_bolt.scad b/models/common/metric_bolt.scad new file mode 100644 index 0000000..ef39763 --- /dev/null +++ b/models/common/metric_bolt.scad @@ -0,0 +1,28 @@ +// include <../../config.scad>; +use <./beam_hexagonal.scad>; +use <./metric_bolt_functions.scad>; +use <./metric_nut.scad>; + +module metric_bolt(size, length, has_nut = true, offset_nut_from_end = 0) { + echo("Metric bolt assembly:"); + head_height = get_metric_bolt_head_height(size); + head_diameter = get_metric_bolt_head_diameter(size); + head_radius = head_diameter / 2; + color("gray") union() { + // Stem + cylinder(length, size / 2, size / 2, center = true); + // Head + translate([0, 0, length / 2 - size / 2]) beam_hexagonal(head_height, head_diameter, centre = true, suppress_shopping_outputs = true); + if (has_nut) { + // Nut + translate([0, 0, -(length / 2 - size / 2) + offset_nut_from_end]) metric_nut(size); + } + } + // Shopping + echo(str("Bolt: Bolt M", size, " x ", length, "mm - x1")); +} + +// $fn = 200; +metric_bolt(12, 100); +translate([30, 0, 0]) metric_bolt(12, 100, false); +translate([60, 0, 0]) metric_bolt(12, 100, true, 5); \ No newline at end of file diff --git a/models/common/metric_bolt_functions.scad b/models/common/metric_bolt_functions.scad new file mode 100644 index 0000000..67374a3 --- /dev/null +++ b/models/common/metric_bolt_functions.scad @@ -0,0 +1,9 @@ + +function get_metric_bolt_head_height(size) = size; +function get_metric_bolt_head_diameter(size) = size * 2; +function get_metric_bolt_washer_diameter_safe_working_clearance(size) = + (size < 20) ? + 4 * size + : + 3 * size +; \ No newline at end of file diff --git a/models/common/metric_nut.json b/models/common/metric_nut.json new file mode 100644 index 0000000..b2b4dd1 --- /dev/null +++ b/models/common/metric_nut.json @@ -0,0 +1,7 @@ +{ + "parameterSets": { + "ANGLE": "" + }, + "parameterSets": "", + "fileFormatVersion": "1" +} diff --git a/models/common/metric_nut.scad b/models/common/metric_nut.scad new file mode 100644 index 0000000..a91ec8b --- /dev/null +++ b/models/common/metric_nut.scad @@ -0,0 +1,20 @@ +// include <../../config.scad>; +use <./beam_hexagonal.scad>; +use <./metric_bolt_functions.scad>; + +module metric_nut(size, centre = true) { + height = get_metric_bolt_head_height(size); + diameter = get_metric_bolt_head_diameter(size); + radius = diameter / 2; + color("gray") difference() { + // body + beam_hexagonal(height, diameter, centre = centre, suppress_shopping_outputs = true); + // hole + cylinder(height, size / 2, size / 2, center = centre); + } + // Shopping + echo(str("Nut: Nut M", size, " - x1")); +} + +// $fn = 200; +metric_nut(12); \ No newline at end of file diff --git a/models/common/universal_joint.scad b/models/common/universal_joint.scad new file mode 100644 index 0000000..a8c6efd --- /dev/null +++ b/models/common/universal_joint.scad @@ -0,0 +1,49 @@ +include <../../config.scad>; + +function get_universal_joint_length() = 40; +function get_universal_joint_d_bore_hole() = 6; +function get_universal_joint_d_hole() = 4; +function get_universal_joint_d() = 11; +function get_universal_joint_thickness() = (get_universal_joint_d() - get_universal_joint_d_bore_hole()) / 2; +function get_universal_joint_joint_axial_offset() = get_universal_joint_thickness() * 2; +function get_universal_joint_pin_axial_offset() = get_universal_joint_thickness() + get_universal_joint_d_hole() / 2; + +module universal_joint() { + echo("Universal joint assembly: ERROR MISSING"); + L = get_universal_joint_length(); + t = get_universal_joint_thickness(); + joint_axial_offset = get_universal_joint_joint_axial_offset(); + translate([L / 2, 0, 0]) mirror([1, 0, 0]) universal_joint_half(); + translate([L / 2 - joint_axial_offset, 0, 0]) rotate([90, -ANGLE_INCLINE_TILLER, 0]) translate([-joint_axial_offset, 0, 0]) universal_joint_half(); +} + +module universal_joint_half() { + d_hole_bore = get_universal_joint_d_bore_hole(); + d_hole = get_universal_joint_d_hole(); + d = get_universal_joint_d(); + L = get_universal_joint_length(); + t = get_universal_joint_thickness(); + joint_axial_offset = get_universal_joint_joint_axial_offset(); + pin_axial_offset = get_universal_joint_pin_axial_offset(); + color("orange") union() { + difference() { + // body + rotate([0, 90, 0]) cylinder(L / 2, d / 2, d / 2, center = false); + // threaded hole + translate([L - pin_axial_offset, 0, 0]) cylinder(d, d_hole / 2, d_hole / 2, center = true); + // bore hole + rotate([0, 90, 0]) cylinder(L / 2, d_hole / 2, d_hole / 2, center = false); + // joint slot + translate([L / 8, 0, 0]) cube([L / 4, d - t * 2, d], center = true); + } + // joint + translate([joint_axial_offset, 0, 0]) rotate([90, 0, 0]) cylinder(d, t, t, center = true); + } +} + +// output +translate([100, 0, 0]) universal_joint_half(); +universal_joint(); + +// shopping +//https://www.amazon.co.uk/Ohamtes-diameter-universal-coupling-Rotatable/dp/B09NXCKJY7/ref=sr_1_1_sspa?crid=3DS7BH7WHYTF4&dib=eyJ2IjoiMSJ9.qTSAOeHpLAIx1plz8THvnJuCvLh8y4zf-H37BRTvT5TTF4M6kqHBg50e-40C5hjdmTAPJLEgHg0Jx5cbB8m_wQM7WCaEibSQJBNZnTwHBZ3w0jHw-znfaRDSaMRP0xlHOblYtwBc9XbF5-KNpHR9dtRmXPDooHcnFM8vchBOqGp-5rR5c6o9Nh0TCq9APO-csslNPAa4bTVjWtniflkcqc39VaQL55CghNaz2NQGdQRrifAgcEqwIM5BpJODfEizqzlotNlbrk6F1gdAZw2clQOw5dIVvjbKLGTCgXnK2xI.vL2JYm04p6ohOn9Jf1OMaPuo9PoqjzItE0AQg2irL0E&dib_tag=se&keywords=UNIVERSAL%2BJOINT&qid=1739725484&sprefix=universal%2Bjoint%2Caps%2C66&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&th=1 \ No newline at end of file diff --git a/models/common/washer.json b/models/common/washer.json new file mode 100644 index 0000000..b2b4dd1 --- /dev/null +++ b/models/common/washer.json @@ -0,0 +1,7 @@ +{ + "parameterSets": { + "ANGLE": "" + }, + "parameterSets": "", + "fileFormatVersion": "1" +} diff --git a/models/common/washer.scad b/models/common/washer.scad new file mode 100644 index 0000000..6dabd5d --- /dev/null +++ b/models/common/washer.scad @@ -0,0 +1,15 @@ +include <../../config.scad>; + +module washer(t, d_outer, d_inner, centre = true) { + r_outer = d_outer / 2; + r_inner = d_inner / 2; + color("silver") difference() { + cylinder(t, r_outer, r_outer, center = centre); + cylinder(t, r_inner, r_inner, center = centre); + } + // Shopping + echo(str("Washer: Washer Φ", d_outer, "mm x ", d_inner, "mm x ", t, "mm - x1")); +} + +// $fn = 200; +washer(3, 10, 40); \ No newline at end of file diff --git a/models/common/wheel.scad b/models/common/wheel.scad new file mode 100644 index 0000000..575d876 --- /dev/null +++ b/models/common/wheel.scad @@ -0,0 +1,12 @@ +include <../../config.scad>; + +module wheel() { + r_wheel = D_WHEEL / 2; + r_wheel_bore = D_WHEEL_BORE / 2; + color("red") rotate([0, 90, 0]) difference() { + cylinder(T_WHEEL, r_wheel, r_wheel, center = true); + cylinder(T_WHEEL, r_wheel_bore, r_wheel_bore, center = true); + } + // Shopping + echo("Wheel: Wheel - x1"); +} \ No newline at end of file diff --git a/models/dog_cart/dog_cart.scad b/models/dog_cart/dog_cart.scad new file mode 100644 index 0000000..ee77089 --- /dev/null +++ b/models/dog_cart/dog_cart.scad @@ -0,0 +1,31 @@ +// Molly Dog Towing Cart + +include <../../config.scad>; +use <../bed/bed.scad>; +use <../top_crate/top_crate_shaft_assembly.scad>; +use <../rear_drive/rear_drive_assembly.scad>; +use <../brake/brake_assembly.scad>; +use <../front_drive/front_drive_assembly.scad>; + +module dog_cart(angle_incline_tiller, angle_brake_rod) { + echo("Dog cart assembly:"); + // bed + bed(); + // top crate shaft assembly + top_crate_shaft_assembly(); + // rear drive assembly + rear_drive_assembly(); + // brake assembly + translate([0, 0, -R_BED[2] / 2]) brake_assembly(angle_brake_rod); + // front drive assembly + front_drive_assembly(angle_incline_tiller); + + // Shopping + // bed + // top crate shaft assembly + // rear drive assembly + // front drive assembly +} + +// output +dog_cart(20); diff --git a/models/fixings/tube_clamp_round_3_way_outlet_tee_176.scad b/models/fixings/tube_clamp_round_3_way_outlet_tee_176.scad new file mode 100644 index 0000000..e6b674c --- /dev/null +++ b/models/fixings/tube_clamp_round_3_way_outlet_tee_176.scad @@ -0,0 +1,39 @@ +include <../../config.scad>; + +function get_L_shaft_long_round_3_way_outlet_tee_176(tube_diameter) = + (tube_diameter == 27) ? + 85 + : (tube_diameter == 42) ? + 122 + : 25 +; +function get_L_shaft_short_round_3_way_outlet_tee_176(tube_diameter) = + (tube_diameter == 27) ? + 42 + : (tube_diameter == 42) ? + 61 + : 10 +; + +module tube_clamp_round_3_way_outlet_tee_176(tube_diameter) { + t = 7; + L_shaft_long = get_L_shaft_long_round_3_way_outlet_tee_176(tube_diameter); + L_shaft_short = get_L_shaft_short_round_3_way_outlet_tee_176(tube_diameter); + color("LightGrey") difference() { + union() { + // long edge + cylinder(L_shaft_long, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + // short perpendicular section + translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + } + cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true); + translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2, tube_diameter / 2, center = true); + rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true); + } + // Shopping + echo("Round 3-way outlet tee 176: Tube clamp - x1"); +} + +// test output +tube_clamp_round_3_way_outlet_tee_176(27); +translate([200, 0, 0]) tube_clamp_round_3_way_outlet_tee_176(42); \ No newline at end of file diff --git a/models/fixings/tube_clamp_round_3_way_through_116.scad b/models/fixings/tube_clamp_round_3_way_through_116.scad new file mode 100644 index 0000000..9bbddb2 --- /dev/null +++ b/models/fixings/tube_clamp_round_3_way_through_116.scad @@ -0,0 +1,27 @@ +include <../../config.scad>; +use <./tube_clamp_round_3_way_through_116_functions.scad>; + +module tube_clamp_round_3_way_through_116(tube_diameter) { + t = get_thickness_round_3_way_through_116(tube_diameter); + L_shaft_long = get_L_shaft_long_round_3_way_through_116(tube_diameter); + L_shaft_short = get_L_shaft_short_round_3_way_through_116(tube_diameter); + color("LightGrey") difference() { + union() { + // short horizontal section + rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + // long vertical section + translate([0, 0, L_shaft_long / 2]) rotate([0, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + // long horizontal section + translate([0, L_shaft_long / 2, 0]) rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + } + rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2, tube_diameter / 2, center = true); + translate([0, 0, L_shaft_long / 2]) rotate([0, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true); + translate([0, L_shaft_long / 2, 0]) rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true); + } + // Shopping + echo("Round 3-way through 116: Tube clamp - x1"); +} + +// test output +tube_clamp_round_3_way_through_116(27); +translate([200, 0, 0]) tube_clamp_round_3_way_through_116(42); \ No newline at end of file diff --git a/models/fixings/tube_clamp_round_3_way_through_116_functions.scad b/models/fixings/tube_clamp_round_3_way_through_116_functions.scad new file mode 100644 index 0000000..1aee241 --- /dev/null +++ b/models/fixings/tube_clamp_round_3_way_through_116_functions.scad @@ -0,0 +1,10 @@ + +function get_L_shaft_long_round_3_way_through_116(tube_diameter) = + (tube_diameter == 27) ? + 42 + : (tube_diameter == 42) ? + 60 + : 25 +; +function get_thickness_round_3_way_through_116(tube_diameter) = 7; +function get_L_shaft_short_round_3_way_through_116(tube_diameter) = tube_diameter + 2 * get_thickness_round_3_way_through_116(); \ No newline at end of file diff --git a/models/fixings/tube_clamp_round_base_plate_132.scad b/models/fixings/tube_clamp_round_base_plate_132.scad new file mode 100644 index 0000000..edad366 --- /dev/null +++ b/models/fixings/tube_clamp_round_base_plate_132.scad @@ -0,0 +1,29 @@ +include <../../config.scad>; +use <./tube_clamp_round_base_plate_132_functions.scad>; + +module tube_clamp_round_base_plate_132(tube_diameter) { + L_shaft_with_base_plate = get_L_shaft_with_base_plate_round_base_plate_132(tube_diameter); + R_plate = get_R_plate_round_base_plate_132(tube_diameter); + t = R_plate[2]; + offset_hole_y = get_offset_hole_y_round_base_plate_132(tube_diameter); + d_hole_bolt_round_base_plate_132 = get_diameter_hole_round_base_plate_132(tube_diameter); + color("LightGrey") union() { + // cylinder section + translate([0, 0, L_shaft_with_base_plate / 2]) difference() { + cylinder(L_shaft_with_base_plate, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + cylinder(L_shaft_with_base_plate, tube_diameter / 2, tube_diameter / 2, center = true); + } + // base plate + translate([0, 0, R_plate[2] / 2]) difference() { + cube(R_plate, center = true); + translate([0, offset_hole_y, 0]) cylinder(R_plate[2], d_hole_bolt_round_base_plate_132 / 2, d_hole_bolt_round_base_plate_132 / 2, center = true); + translate([0, -offset_hole_y, 0]) cylinder(R_plate[2], d_hole_bolt_round_base_plate_132 / 2, d_hole_bolt_round_base_plate_132 / 2, center = true); + } + } + // Shopping + echo("Round base plate 132: Tube clamp - x1"); +} + +// test output +tube_clamp_round_base_plate_132(27); +translate([200, 0, 0]) tube_clamp_round_base_plate_132(42); \ No newline at end of file diff --git a/models/fixings/tube_clamp_round_base_plate_132_functions.scad b/models/fixings/tube_clamp_round_base_plate_132_functions.scad new file mode 100644 index 0000000..de7a8e0 --- /dev/null +++ b/models/fixings/tube_clamp_round_base_plate_132_functions.scad @@ -0,0 +1,23 @@ + +function get_L_shaft_with_base_plate_round_base_plate_132(tube_diameter) = + (tube_diameter == 27) ? + 85 + : (tube_diameter == 42) ? + 122 + : 25 +; +function get_R_plate_round_base_plate_132(tube_diameter) = + (tube_diameter == 27) ? + [64, 114, 7] + : (tube_diameter == 42) ? + [80, 140, 10] + : [10, 20, 1] +; +function get_offset_hole_y_round_base_plate_132(tube_diameter) = + (tube_diameter == 27) ? + 38 + : (tube_diameter == 42) ? + 50 + : 10 +; +function get_diameter_hole_round_base_plate_132(tube_diameter) = 10; diff --git a/models/fixings/tube_clamp_round_tee_long_104.scad b/models/fixings/tube_clamp_round_tee_long_104.scad new file mode 100644 index 0000000..eef8a43 --- /dev/null +++ b/models/fixings/tube_clamp_round_tee_long_104.scad @@ -0,0 +1,24 @@ +include <../../config.scad>; +use <./tube_clamp_round_tee_long_104_functions.scad>; + +module tube_clamp_round_tee_long_104(tube_diameter) { + t = 7; + L_shaft_long = get_L_shaft_long_round_tee_long_104(tube_diameter); + L_shaft_short = get_L_shaft_short_round_tee_long_104(tube_diameter); + color("LightGrey") difference() { + union() { + // long edge + cylinder(L_shaft_long, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + // short perpendicular section + translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2 + t, tube_diameter / 2 + t, center = true); + } + cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true); + translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2, tube_diameter / 2, center = true); + } + // Shopping + echo("Round tee long 104: Tube clamp - x1"); +} + +// test output +tube_clamp_round_tee_long_104(27); +translate([200, 0, 0]) tube_clamp_round_tee_long_104(42); \ No newline at end of file diff --git a/models/fixings/tube_clamp_round_tee_long_104_functions.scad b/models/fixings/tube_clamp_round_tee_long_104_functions.scad new file mode 100644 index 0000000..9ed2cf8 --- /dev/null +++ b/models/fixings/tube_clamp_round_tee_long_104_functions.scad @@ -0,0 +1,16 @@ +// include <../../config.scad>; + +function get_L_shaft_long_round_tee_long_104(tube_diameter) = + (tube_diameter == 27) ? + 85 + : (tube_diameter == 42) ? + 122 + : 25 +; +function get_L_shaft_short_round_tee_long_104(tube_diameter) = + (tube_diameter == 27) ? + 42 + : (tube_diameter == 42) ? + 61 + : 10 +; diff --git a/models/fixings/tube_clamp_square_base_plate_132.scad b/models/fixings/tube_clamp_square_base_plate_132.scad new file mode 100644 index 0000000..4b6bda0 --- /dev/null +++ b/models/fixings/tube_clamp_square_base_plate_132.scad @@ -0,0 +1,28 @@ +include <../../config.scad>; +use <./tube_clamp_square_base_plate_132_functions.scad>; + +module tube_clamp_square_base_plate_132(beam_width) { + L_shaft_with_base_plate = get_L_shaft_with_base_plate_square_base_plate_132(beam_width); + R_plate = get_R_plate_square_base_plate_132(beam_width); + t = get_thickness_square_base_plate_132(beam_width); + offset_hole_x = get_offset_hole_x_square_base_plate_132(beam_width); + d_hole_bolt_square_base_plate_132 = get_diameter_hole_square_base_plate_132(beam_width); + color("LightGrey") union() { + // shaft section + translate([0, 0, L_shaft_with_base_plate / 2]) difference() { + cube([beam_width + t * 2, beam_width + t * 2, L_shaft_with_base_plate], center = true); + cube([beam_width, beam_width, L_shaft_with_base_plate], center = true); + } + // base plate + translate([0, 0, R_plate[2] / 2]) difference() { + cube(R_plate, center = true); + translate([offset_hole_x, 0, 0]) cylinder(R_plate[2], d_hole_bolt_square_base_plate_132 / 2, d_hole_bolt_square_base_plate_132 / 2, center = true); + translate([-offset_hole_x, 0, 0]) cylinder(R_plate[2], d_hole_bolt_square_base_plate_132 / 2, d_hole_bolt_square_base_plate_132 / 2, center = true); + } + } + // Shopping + echo("Square base plate 132: Tube clamp - x1"); +} + +// test output +tube_clamp_square_base_plate_132(42); \ No newline at end of file diff --git a/models/fixings/tube_clamp_square_base_plate_132_functions.scad b/models/fixings/tube_clamp_square_base_plate_132_functions.scad new file mode 100644 index 0000000..6f75496 --- /dev/null +++ b/models/fixings/tube_clamp_square_base_plate_132_functions.scad @@ -0,0 +1,21 @@ + +function get_L_shaft_with_base_plate_square_base_plate_132(beam_width) = + // (beam_width == 40) ? + 75 +; +function get_R_plate_square_base_plate_132(beam_width) = + // (beam_width == 40) ? + [143, 75, 18.5] +; +function get_thickness_square_base_plate_132(beam_width) = + // (beam_width == 40) ? + 8 +; +function get_offset_hole_x_square_base_plate_132(beam_width) = + // (beam_width == 40) ? + 100 / 2 +; +function get_diameter_hole_square_base_plate_132(beam_width) = + // (beam_width == 40) ? + 10 +; diff --git a/models/front_drive/front_drive_assembly.scad b/models/front_drive/front_drive_assembly.scad new file mode 100644 index 0000000..f7ba6ca --- /dev/null +++ b/models/front_drive/front_drive_assembly.scad @@ -0,0 +1,80 @@ +include <../../config.scad>; +use <../front_drive/front_leg_fixing.scad>; +use <../front_drive/tiller_assembly.scad>; +use <../rear_drive/rear_wheel_fastener.scad>; +use <../common/metric_bolt.scad>; +use <../common/washer.scad>; +use <../common/wheel.scad>; + +module front_drive_assembly(angle_incline_tiller) { + echo("Front drive assembly:"); + y_pos_axis = R_BED[1] / 2 - D_WHEEL / 2; + L_axle_long = R_BED[0] - T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 2; + L_axle_short = T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 2 + T_WHEEL + D_WASHER_BOLT_REAR_WHEEL_POSITIONING; + height_bolt_head = get_metric_bolt_head_height(SIZE_BOLT_REAR_WHEEL_POSITIONING); + L_bolt_axle_extension = D_AXLE_FRONT + 2 * (T_WASHER_BOLT_REAR_WHEEL_POSITIONING + height_bolt_head) + L_BOLT_EXTENSION; + offset_axle_extension_fastener_axial = 2 * SIZE_BOLT_REAR_WHEEL_POSITIONING; + L_bolt_wheel_positioning = D_AXLE_REAR + 2 * (T_WASHER_BOLT_REAR_WHEEL_POSITIONING + height_bolt_head) + L_BOLT_EXTENSION; + translate([0, y_pos_axis, -R_BED[2] / 2]) union() { + // leg fixing + front_leg_fixing(); + // left-right symmetry + translate([0, 0, -Z_OFFSET_BED_TO_AXLE]) for (index_side = [0:1:1]) { + mirror([index_side, 0, 0]) { + // axle extensions + color(COLOUR_BEAM_ALUMINIUM) translate([L_axle_long / 2 + L_axle_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_axle_short, D_AXLE_REAR / 2, D_AXLE_REAR / 2, center = true); + // axle extension fixing bolt + translate([L_axle_long / 2 - offset_axle_extension_fastener_axial, 0, -L_BOLT_EXTENSION / 2]) metric_bolt(SIZE_BOLT_REAR_WHEEL_POSITIONING, L_bolt_axle_extension, true, L_BOLT_EXTENSION); + // axle extension fixing bolt washers + translate([L_axle_long / 2 - offset_axle_extension_fastener_axial, 0, 0]) for (index_side_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_z]) { + translate([0, 0, D_AXLE_FRONT / 2 + T_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2]) washer(T_WASHER_BOLT_REAR_WHEEL_POSITIONING, D_WASHER_BOLT_REAR_WHEEL_POSITIONING, SIZE_BOLT_REAR_WHEEL_POSITIONING); + } + } + // inner wheel axis washers + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING / 2, 0, 0]) rotate([0, 90, 0]) washer(T_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_AXLE_REAR); + // wheels + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING + T_WHEEL / 2, 0, 0]) wheel(); + // outer wheel axis washers + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 3 / 2 + T_WHEEL, 0, 0]) rotate([0, 90, 0]) washer(T_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_AXLE_REAR); + + /* replaced with rear_wheel_fastener below + // wheel positioning bolts + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 2 + T_WHEEL + D_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2, 0, -L_BOLT_EXTENSION / 2]) metric_bolt(SIZE_BOLT_REAR_WHEEL_POSITIONING, L_bolt_wheel_positioning, true, L_BOLT_EXTENSION); + // wheel positioning bolt washers + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 2 + T_WHEEL + D_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2, 0, 0]) for (index_side_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_z]) { + translate([0, 0, D_AXLE_REAR / 2 + T_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2]) washer(T_WASHER_BOLT_REAR_WHEEL_POSITIONING, D_WASHER_BOLT_REAR_WHEEL_POSITIONING, SIZE_BOLT_REAR_WHEEL_POSITIONING); + } + } + */ + translate([L_axle_long / 2 + T_WASHER_AXLE_REAR_WHEEL_POSITIONING * 2 + T_WHEEL + D_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2, 0, 0]) rear_wheel_fastener(); + } + } + // axle + color(COLOUR_BEAM_ALUMINIUM) translate([0, 0, -Z_OFFSET_BED_TO_AXLE]) rotate([0, 90, 0]) cylinder(L_axle_long, D_AXLE_FRONT / 2, D_AXLE_FRONT / 2, center = true); + // tiller + translate([0, D_AXLE_FRONT / 2, -Z_OFFSET_BED_TO_AXLE]) tiller_assembly(angle_incline_tiller); + // joint axle to tiller + translate([0, 0, -Z_OFFSET_BED_TO_AXLE + L_BOLT_FRONT_AXLE_BEARING / 2 - D_AXLE_FRONT / 2 - T_JOINT_FRONT_AXLE_TO_TILLER - DEPTH_BOLT_FRONT_AXLE_BEARING - COUNT_WASHERS_JOINT_FRONT_AXLE_TO_TILLER * T_WASHER_JOINT_FRONT_AXLE_TO_TILLER]) mirror([0, 0, 1]) metric_bolt(SIZE_BOLT_FRONT_AXLE_BEARING, L_BOLT_FRONT_AXLE_BEARING, false); + // joint axle to tiller washers + for (index_washer = [0 : 1 : COUNT_WASHERS_JOINT_FRONT_AXLE_TO_TILLER - 1]) { + translate([0, 0, -Z_OFFSET_BED_TO_AXLE - D_AXLE_FRONT / 2 - T_JOINT_FRONT_AXLE_TO_TILLER - T_WASHER_JOINT_FRONT_AXLE_TO_TILLER * (index_washer + 1 / 2)]) washer(T_WASHER_JOINT_FRONT_AXLE_TO_TILLER, D_WASHER_JOINT_FRONT_AXLE_TO_TILLER, SIZE_BOLT_FRONT_AXLE_BEARING); + } + } + // Shopping + // front leg fixing + echo(str("Axle extension: Round Aluminium bar Φ", D_AXLE_REAR, "mm x ", L_axle_short, "mm - x2")); + // Axle extension fixing bolt + // echo(str("Axle extension fixing bolt washer: Washer Φ", D_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm x ", T_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm - x4")); // Axle extension fixing bolt washers + // echo(str("Wheel positioning washer: Washer Φ", D_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm x ", T_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm - x4")); // Wheel positioning washers + // wheels + // wheel positioning fastener + // echo(str("Wheel positioning bolt washer: Washer Φ", D_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm x ", T_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm - x4")); // Wheel positioning bolt washers + echo(str("Axle: Round Aluminium bar Φ", D_AXLE_FRONT, "mm x ", L_axle_long, "mm - x1")); + // tiller assembly + // front axis bearing bolt + // echo(str("Front axis bearing washers: Washer Φ", D_WASHER_JOINT_FRONT_AXLE_TO_TILLER, "mm x ", T_WASHER_JOINT_FRONT_AXLE_TO_TILLER, "mm - x", COUNT_WASHERS_JOINT_FRONT_AXLE_TO_TILLER)); // Front axis bearing washers +} + +front_drive_assembly(20); \ No newline at end of file diff --git a/models/front_drive/front_leg_fixing.scad b/models/front_drive/front_leg_fixing.scad new file mode 100644 index 0000000..930f0d9 --- /dev/null +++ b/models/front_drive/front_leg_fixing.scad @@ -0,0 +1,50 @@ +include <../../config.scad>; +use <../fixings/tube_clamp_round_3_way_through_116.scad>; +use <../fixings/tube_clamp_round_base_plate_132.scad>; +use <../common/metric_bolt.scad>; +use <../common/washer.scad>; + +module front_leg_fixing() { + echo("Front leg fixing assembly:"); + R_base_plate = get_R_plate_round_base_plate_132(D_AXLE_FRONT); + h_leg = Z_OFFSET_BED_TO_AXLE - D_AXLE_FRONT / 2 - R_base_plate[2]; + offset_y_hole_base_plate = get_offset_hole_y_round_base_plate_132(D_AXLE_FRONT); + size_hole_base_plate = get_diameter_hole_round_base_plate_132(D_AXLE_FRONT); + h_bolt_head = get_metric_bolt_head_height(size_hole_base_plate); + L_fastener = h_bolt_head * 2 + T_WASHER_BASE_PLATE * 2 + R_base_plate[2] + R_BED[2] + L_BOLT_EXTENSION; + difference() { + union() { + // bracket - top, under bed + // translate([0, 0, -R_fixing[2] / 2]) cylinder(R_fixing[2], R_fixing[0] / 2, R_fixing[0] / 2, center = true); + rotate([0, 180, 0]) tube_clamp_round_base_plate_132(D_AXLE_FRONT); + // bed bracket fastening bolt + for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + // bracket at bed fastener + translate([0, offset_y_hole_base_plate, L_fastener / 2 - R_base_plate[2] - L_BOLT_EXTENSION - h_bolt_head - T_WASHER_BASE_PLATE]) metric_bolt(size_hole_base_plate, L_fastener, true, L_BOLT_EXTENSION); + translate([0, offset_y_hole_base_plate, h_bolt_head / 2 - T_WASHER_BASE_PLATE / 2]) for (index_side_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_z]) { + // bracket fastener washers + translate([0, 0, L_fastener / 2 - L_BOLT_EXTENSION / 2 - h_bolt_head - T_WASHER_BASE_PLATE / 2]) washer(T_WASHER_BASE_PLATE, D_WASHER_BASE_PLATE, size_hole_base_plate); + } + } + } + } + // leg + color(COLOUR_BEAM_ALUMINIUM) translate([0, 0, -R_base_plate[2] - h_leg / 2]) cylinder(h_leg, D_AXLE_FRONT / 2, D_AXLE_FRONT / 2, center = true); + // bracket - bottom, against axle + translate([0, 0, -Z_OFFSET_BED_TO_AXLE]) rotate([0, 0, 0]) tube_clamp_round_3_way_through_116(D_AXLE_FRONT); // translate([0, 0, -R_fixing[2] * 3 / 2 - h_leg - T_PLATE * 2 - D_AXLE_FRONT + z_overlap_tee_clamp_round * 1]) cylinder(R_fixing[2], R_fixing[0] / 2, R_fixing[0] / 2, center = true); + } + // front axle bearing hole + translate([0, 0, -Z_OFFSET_BED_TO_AXLE + D_AXLE_FRONT / 2 + DEPTH_BOLT_FRONT_AXLE_BEARING - L_BOLT_FRONT_AXLE_BEARING]) cylinder(L_BOLT_FRONT_AXLE_BEARING, SIZE_BOLT_FRONT_AXLE_BEARING / 2, SIZE_BOLT_FRONT_AXLE_BEARING / 2, center = false); + } + // Shopping + // bed fixing + echo(str("Leg: Round Aluminium bar Φ", D_AXLE_FRONT, "mm x ", h_leg, "mm - x1")); + // Base plate fastening bolts and nuts + // echo(str("Base plate fastening washers: Washer Φ", D_WASHER_BASE_PLATE, "mm x ", T_WASHER_BASE_PLATE, "mm - x4")); // Base plate fastening washers + // axle fixing + echo(str("Tool: M", SIZE_BOLT_FRONT_AXLE_BEARING, " HSS tapping tool - x1")); +} + +front_leg_fixing(); diff --git a/models/front_drive/tiller_assembly.scad b/models/front_drive/tiller_assembly.scad new file mode 100644 index 0000000..44dc36f --- /dev/null +++ b/models/front_drive/tiller_assembly.scad @@ -0,0 +1,64 @@ +include <../../config.scad>; +use <./tiller_joint.scad>; +use <../common/metric_bolt.scad>; +use <../fixings/tube_clamp_round_tee_long_104.scad>; + +module tiller_assembly(angle_incline_tiller) { + echo("Tiller assembly:"); + /* + t_universal_joint = get_universal_joint_thickness(); + d_universal_joint = get_universal_joint_d(); + d_hole_universal_joint = get_universal_joint_d_hole(); + d_hole_bore_universal_joint = get_universal_joint_d_bore_hole(); + L_universal_joint = get_universal_joint_length(); + joint_axial_offset = get_universal_joint_joint_axial_offset(); + pin_axial_offset = get_universal_joint_pin_axial_offset(); + L_hole = t_universal_joint + d_hole_universal_joint / 2 + pin_axial_offset; + L_bolt_fastener = D_AXLE_FRONT + d_hole_universal_joint * 4 + T_WASHER_UNIVERSAL_JOINT; + echo("t_universal_joint", t_universal_joint, "mm"); + echo("d_hole_universal_joint", d_hole_universal_joint, "mm"); + echo("pin_axial_offset", pin_axial_offset, "mm"); + echo("L_hole", t_universal_joint + d_hole_universal_joint / 2 + pin_axial_offset, "mm"); + echo("L_universal_joint / 2 - joint_axial_offset - L_hole", L_universal_joint / 2 - joint_axial_offset - L_hole, "mm"); + */ + + union() { + // tiller + color(COLOUR_BEAM_ALUMINIUM) difference() { + // body + rotate([-90, 0, 0]) cylinder(L_TILLER, D_AXLE_FRONT / 2, D_AXLE_FRONT / 2, center = false); + // joint fastening hole normal + translate([L_TILLER - OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL, 0, 0]) cylinder(D_AXLE_FRONT, SIZE_BOLT_JOINT_TILLER_EXTENSION / 2, SIZE_BOLT_JOINT_TILLER_EXTENSION / 2, center = false); + } + /* + // universal joint + translate([L_TILLER - L_hole, 0, 0]) universal_joint(); + // tiller universal joint fastening + translate([L_TILLER - L_hole / 2, 0, 0]) metric_bolt(d_hole_universal_joint, L_bolt_fastener); + */ + // tiller joint + translate([0, L_TILLER + L_JOINT_TILLER_EXTENSION / 2 - OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL * 2, 0]) tiller_joint(); + // tiller extension + translate([0, L_TILLER + L_JOINT_TILLER_EXTENSION - OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL * 4, 0]) rotate([angle_incline_tiller, 0, 0]) { + color(COLOUR_BEAM_ALUMINIUM) difference() { + // body + rotate([-90, 0, 0]) cylinder(L_TILLER_EXTENSION, D_HANDLE_BAR / 2, D_HANDLE_BAR / 2, center = false); + // joint fastening hole normal + translate([0, OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL, 0]) cylinder(D_AXLE_FRONT, SIZE_BOLT_JOINT_TILLER_EXTENSION / 2, SIZE_BOLT_JOINT_TILLER_EXTENSION / 2, center = false); + } + // handle beam + color(COLOUR_BEAM_ALUMINIUM) translate([0, L_TILLER_EXTENSION + D_HANDLE_BAR / 2, 0]) rotate([0, 90, 0]) cylinder(W_HANDLE_BAR, D_HANDLE_BAR / 2, D_HANDLE_BAR / 2, center = true); + // handle fixing + translate([0, L_TILLER_EXTENSION + D_HANDLE_BAR / 2, 0]) rotate([90, 0, -90]) tube_clamp_round_tee_long_104(D_HANDLE_BAR); + } + } + // Shopping + echo(str("Tiller: Round Aluminium bar Φ", D_AXLE_FRONT, "mm x ", L_TILLER, "mm - x1")); + // Tiller extension joint + echo(str("Tiller extension: Round Aluminium bar Φ", D_HANDLE_BAR, "mm x ", L_TILLER_EXTENSION, "mm - x1")); + echo(str("Handle bar: Round Aluminium bar Φ", D_HANDLE_BAR, "mm x ", W_HANDLE_BAR, "mm - x1")); + // Handle fixing +} + +// $fn = 100; +tiller_assembly(20); \ No newline at end of file diff --git a/models/front_drive/tiller_joint.scad b/models/front_drive/tiller_joint.scad new file mode 100644 index 0000000..2289234 --- /dev/null +++ b/models/front_drive/tiller_joint.scad @@ -0,0 +1,50 @@ +include <../../config.scad>; +use <../common/metric_bolt.scad>; +use <../common/washer.scad>; + +module tiller_joint() { + echo("Tiller joint assembly:"); + R_plate_tiller = [T_PLATE, L_JOINT_TILLER_EXTENSION, 3 * SIZE_BOLT_JOINT_TILLER_EXTENSION]; + x_pos_plate = (D_AXLE_FRONT + R_plate_tiller[0]) / 2 + T_WASHER_TILLER_JOINT; + h_bolt_head = get_metric_bolt_head_height(SIZE_BOLT_JOINT_TILLER_EXTENSION); + L_bolt = D_AXLE_FRONT + 2 * (h_bolt_head + T_WASHER_TILLER_JOINT * 2 + R_plate_tiller[0]) + L_BOLT_EXTENSION; + y_pos_bolt = R_plate_tiller[1] / 2 - OFFSET_BOLT_JOINT_TILLER_EXTENSION_AXIAL; + x_pos_washer_internal = D_AXLE_FRONT / 2 + T_WASHER_TILLER_JOINT / 2; + x_pos_washer_external = L_bolt / 2 - L_BOLT_EXTENSION / 2 - h_bolt_head - T_WASHER_TILLER_JOINT / 2; + count_washers_each_side_front = 5; + union() { + for (index_side_x = [0 : 1 : 1]) { + mirror([index_side_x, 0, 0]) { + // plates + color(COLOUR_BEAM_ALUMINIUM) translate([x_pos_plate, 0, 0]) cube(R_plate_tiller, center = true); + + for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + // washers + // external + translate([x_pos_washer_external, y_pos_bolt, 0]) rotate([0, 90, 0]) washer(T_WASHER_TILLER_JOINT, D_WASHER_TILLER_JOINT, SIZE_BOLT_JOINT_TILLER_EXTENSION); + } + } + // rear internal washers + translate([x_pos_washer_internal, -y_pos_bolt, 0]) rotate([0, 90, 0]) washer(T_WASHER_TILLER_JOINT, D_WASHER_TILLER_JOINT, SIZE_BOLT_JOINT_TILLER_EXTENSION); + // front internal washers + for (index_washer_front = [0 : 1 : count_washers_each_side_front]) { + translate([x_pos_washer_internal - T_WASHER_TILLER_JOINT * index_washer_front, y_pos_bolt, 0]) rotate([0, 90, 0]) washer(T_WASHER_TILLER_JOINT, D_WASHER_TILLER_JOINT, SIZE_BOLT_JOINT_TILLER_EXTENSION); + } + } + } + for (index_side_y_only = [0 : 1 : 1]) { + mirror([0, index_side_y_only, 0]) { + // bolts + translate([-L_BOLT_EXTENSION / 2, y_pos_bolt, 0]) rotate([0, 90, 0]) metric_bolt(SIZE_BOLT_JOINT_TILLER_EXTENSION, L_bolt, true, L_BOLT_EXTENSION); + } + } + } + // Shopping + echo(str("Plate: Aluminium sheet ", R_plate_tiller[0], "mm x ", R_plate_tiller[1], "mm x ", R_plate_tiller[2], "mm - x2")); + // echo(str("Washer: Washer Φ", D_WASHER_TILLER_JOINT, "mm x ", T_WASHER_TILLER_JOINT, "mm - x8")); // Tiller joint washers + // Bolts +} + +// output +tiller_joint(); diff --git a/models/rear_drive/rear_drive_assembly.scad b/models/rear_drive/rear_drive_assembly.scad new file mode 100644 index 0000000..23c5dee --- /dev/null +++ b/models/rear_drive/rear_drive_assembly.scad @@ -0,0 +1,45 @@ + +include <../../config.scad>; +use <../fixings/tube_clamp_round_tee_long_104.scad>; +use <../fixings/tube_clamp_round_base_plate_132.scad>; +use <../rear_drive/rear_leg_fixing.scad>; +use <../rear_drive/rear_wheel_fastener.scad>; +use <../common/washer.scad>; +use <../common/wheel.scad>; + +module rear_drive_assembly() { + echo("Rear drive assembly:"); + L_shaft_short_leg_to_axle = get_L_shaft_short_round_tee_long_104(D_AXLE_REAR); + L_shaft_long_leg_to_axle = get_L_shaft_long_round_tee_long_104(D_AXLE_REAR); + // L_axial_rear_wheel_fastener = SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING + T_WASHER_AXLE_REAR_WHEEL_POSITIONING + D_WASHER_BOLT_REAR_WHEEL_POSITIONING; + // x_pos_wheel_centre = X_POS_AXLE_LEG_REAR + L_shaft_long_leg_to_axle / 2 + L_axial_rear_wheel_fastener + T_WHEEL / 2; + L_axle = 2 * (X_POS_WHEEL_CENTRE + T_WHEEL / 2 + SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING + T_WASHER_AXLE_REAR_WHEEL_POSITIONING + D_WASHER_BOLT_REAR_WHEEL_POSITIONING); + translate([0, Y_POS_AXLE_REAR, -R_BED[2] / 2]) union() { + for (index_side_bed = [0:1:1]) { + mirror([index_side_bed, 0, 0]) { + // leg fixings + translate([X_POS_AXLE_LEG_REAR, 0, 0]) rear_leg_fixing(); + // wheels + translate([X_POS_WHEEL_CENTRE, 0, -Z_OFFSET_BED_TO_AXLE]) wheel(); + translate([X_POS_WHEEL_CENTRE, 0, -Z_OFFSET_BED_TO_AXLE]) for(index_side_wheel = [0:1:1]) { + mirror([index_side_wheel, 0, 0]) translate([T_WHEEL / 2 + SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING + T_WASHER_AXLE_REAR_WHEEL_POSITIONING + D_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2, 0, 0]) { + // wheel positioning fasteners + rear_wheel_fastener(); + // washer + translate([-D_WASHER_BOLT_REAR_WHEEL_POSITIONING / 2 - T_WASHER_AXLE_REAR_WHEEL_POSITIONING / 2, 0, 0]) rotate([0, 90, 0]) washer(T_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_WASHER_AXLE_REAR_WHEEL_POSITIONING, D_AXLE_REAR); + } + } + } + } + // axle + color(COLOUR_BEAM_ALUMINIUM) translate([0, 0, -Z_OFFSET_BED_TO_AXLE]) rotate([0, 90, 0]) cylinder(L_axle, D_AXLE_REAR / 2, D_AXLE_REAR / 2, center = true); + } + // Shopping + // Rear leg fixing + // Wheel + // Rear wheel fastener + // echo(str("Rear wheel positioning axle washer: Washer Φ", D_WASHER_AXLE_REAR_WHEEL_POSITIONING, "mm x ", T_WASHER_AXLE_REAR_WHEEL_POSITIONING, "mm - x4")); // Rear wheel positioning axle washer + echo(str("Rear axle: Round Aluminium bar Φ", D_AXLE_REAR, "mm x ", L_axle, "mm - x1")); +} + +rear_drive_assembly(); diff --git a/models/rear_drive/rear_leg_fixing.scad b/models/rear_drive/rear_leg_fixing.scad new file mode 100644 index 0000000..9186a92 --- /dev/null +++ b/models/rear_drive/rear_leg_fixing.scad @@ -0,0 +1,45 @@ +include <../../config.scad>; +use <../fixings/tube_clamp_round_tee_long_104.scad>; +use <../fixings/tube_clamp_round_base_plate_132.scad>; +use <../common/metric_bolt.scad>; +use <../common/washer.scad>; + +module rear_leg_fixing() { + echo("Rear leg fixing:"); + R_base_plate = get_R_plate_round_base_plate_132(D_AXLE_REAR); + h_leg = Z_OFFSET_BED_TO_AXLE - R_base_plate[2] - D_AXLE_REAR / 2; + offset_y_hole_base_plate = get_offset_hole_y_round_base_plate_132(D_AXLE_REAR); + size_hole_base_plate = get_diameter_hole_round_base_plate_132(D_AXLE_REAR); + h_bolt_head = get_metric_bolt_head_height(size_hole_base_plate); + L_fastener = h_bolt_head * 2 + T_WASHER_BASE_PLATE * 2 + R_base_plate[2] + R_BED[2] + L_BOLT_EXTENSION; + union() { + // bracket bed + rotate([0, 180, 0]) tube_clamp_round_base_plate_132(D_AXLE_REAR); // cylinder(R_fixing[2], R_fixing[0] / 2, R_fixing[0] / 2, center = true); // cube(R_fixing, center = true); + + for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + // bracket at bed fastener + translate([0, offset_y_hole_base_plate, L_fastener / 2 - R_base_plate[2] - L_BOLT_EXTENSION - h_bolt_head - T_WASHER_BASE_PLATE]) metric_bolt(size_hole_base_plate, L_fastener, true, L_BOLT_EXTENSION); + translate([0, offset_y_hole_base_plate, h_bolt_head / 2 - 0* T_WASHER_BASE_PLATE / 2]) for (index_side_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_z]) { + // bracket fastener washers + translate([0, 0, L_fastener / 2 - L_BOLT_EXTENSION / 2 - h_bolt_head - T_WASHER_BASE_PLATE / 2]) washer(T_WASHER_BASE_PLATE, D_WASHER_BASE_PLATE, size_hole_base_plate); + } + } + } + } + // leg + color(COLOUR_BEAM_ALUMINIUM) translate([0, 0, -R_base_plate[2] - h_leg / 2]) cylinder(h_leg, D_AXLE_REAR / 2, D_AXLE_REAR / 2, center = true); // cube([t_beam, t_beam, h_leg], center = true); + // bracket axle-side + translate([0, 0, -Z_OFFSET_BED_TO_AXLE]) rotate([0, -90, 0]) tube_clamp_round_tee_long_104(D_AXLE_REAR); // cylinder(R_fixing[2], R_fixing[0] / 2, R_fixing[0] / 2, center = true); + } + // Shopping + // bracket at bed + // bracket bolt + // echo(str("Base plate fastening washers: Washer Φ", D_WASHER_BASE_PLATE, "mm x ", T_WASHER_BASE_PLATE, "mm - x4")); // Base plate fastening washers + echo(str("Leg: Round Aluminium bar Φ", D_AXLE_REAR, "mm x ", h_leg, "mm - x1")); + // bracket at axle +} + +rear_leg_fixing(); + diff --git a/models/rear_drive/rear_wheel_fastener.scad b/models/rear_drive/rear_wheel_fastener.scad new file mode 100644 index 0000000..2ec3401 --- /dev/null +++ b/models/rear_drive/rear_wheel_fastener.scad @@ -0,0 +1,28 @@ + +include <../../config.scad>; +use <../common/metric_bolt.scad>; +use <../common/washer.scad>; + +module rear_wheel_fastener() { + echo("Rear wheel fastener:"); + height_bolt_head = get_metric_bolt_head_height(SIZE_BOLT_REAR_WHEEL_POSITIONING); + count_washers_each_end = 7; + L_bolt = D_AXLE_REAR + 2 * height_bolt_head + 2 * T_WASHER_BOLT_REAR_WHEEL_POSITIONING * count_washers_each_end + L_BOLT_EXTENSION; + union() { + // bolt + translate([0, 0, -L_BOLT_EXTENSION / 2]) metric_bolt(SIZE_BOLT_REAR_WHEEL_POSITIONING, L_bolt, true, L_BOLT_EXTENSION); + for (index_side_bolt = [0 : 1 : 1]) { + mirror([0, 0, index_side_bolt]) { + // washer + for (index_washer = [0 : 1 : max(0, count_washers_each_end - 1)]) { + translate([0, 0, D_AXLE_REAR / 2 + T_WASHER_BOLT_REAR_WHEEL_POSITIONING * (index_washer + 1/2)]) washer(T_WASHER_BOLT_REAR_WHEEL_POSITIONING, D_WASHER_BOLT_REAR_WHEEL_POSITIONING, SIZE_BOLT_REAR_WHEEL_POSITIONING); + } + } + } + } + // Shopping + // bolt + // echo(str("Bolt washer: Washer Φ", D_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm x ", T_WASHER_BOLT_REAR_WHEEL_POSITIONING, "mm - x", 2 * count_washers_each_end)); // Rear wheel fastener bolt washers +} + +rear_wheel_fastener(); diff --git a/models/top_crate/fixing_top_crate_shaft.scad b/models/top_crate/fixing_top_crate_shaft.scad new file mode 100644 index 0000000..1abadde --- /dev/null +++ b/models/top_crate/fixing_top_crate_shaft.scad @@ -0,0 +1,30 @@ +include <../../config.scad>; +use <../common/metric_bolt_functions.scad>; +use <../common/metric_nut.scad>; +use <../common/washer.scad>; + +module fixing_top_crate_shaft() { + echo("Fixing top crate shaft:"); + h_nut = get_metric_bolt_head_height(D_SHAFT_TOP_CRATE); + union() { + // shaft (threaded rod) + color(COLOUR_ROD_THREADED) translate([0, 0, -R_BED[2] / 2 - T_WASHER_SHAFT_TOP_CRATE * COUNT_WASHERS_SHAFT_TOP_CRATE_EACH_END - h_nut]) cylinder(L_SHAFT_TOP_CRATE, D_SHAFT_TOP_CRATE / 2, D_SHAFT_TOP_CRATE / 2, center = false); + // fixing + for (index_side_bed_z = [0 : 1 : 1]) { + mirror([0, 0, index_side_bed_z]) { + // washers + for (index_washer = [0 : 1 : COUNT_WASHERS_SHAFT_TOP_CRATE_EACH_END]) { + translate([0, 0, R_BED[2] / 2 + T_WASHER_SHAFT_TOP_CRATE * index_washer]) washer(T_WASHER_SHAFT_TOP_CRATE, D_WASHER_SHAFT_TOP_CRATE, D_SHAFT_TOP_CRATE, centre = false); + } + // nuts + translate([0, 0, R_BED[2] / 2 + T_WASHER_SHAFT_TOP_CRATE * COUNT_WASHERS_SHAFT_TOP_CRATE_EACH_END]) metric_nut(D_SHAFT_TOP_CRATE, centre = false); + } + } + } + // Shopping + echo(str("Top crate shaft: Threaded Steel rod M", D_SHAFT_TOP_CRATE, " x ", L_SHAFT_TOP_CRATE, "mm - x1")); + // Fixing washers + // Fixing nuts +} + +fixing_top_crate_shaft(); \ No newline at end of file diff --git a/models/top_crate/top_crate_shaft_assembly.scad b/models/top_crate/top_crate_shaft_assembly.scad new file mode 100644 index 0000000..4b8b922 --- /dev/null +++ b/models/top_crate/top_crate_shaft_assembly.scad @@ -0,0 +1,29 @@ +include <../../config.scad>; +use <./fixing_top_crate_shaft.scad>; + +module top_crate_shaft_assembly() { + echo("Top crate shaft assembly:"); + union() { + // shafts along y + for (index_side_x = [0 : 1 : 1]) { + mirror([index_side_x, 0, 0]) { + translate([R_BED[0] / 2 - D_WASHER_SHAFT_TOP_CRATE / 2, 0, 0]) for (index_shaft_y = [0 : 1 : COUNT_SHAFTS_TOP_CRATE_Y - 1]) { + translate([0, -R_BED[1] / 2 + D_WASHER_SHAFT_TOP_CRATE / 2 + index_shaft_y * (R_BED[1] - D_WASHER_SHAFT_TOP_CRATE) / (COUNT_SHAFTS_TOP_CRATE_Y - 1), 0]) fixing_top_crate_shaft(); + } + } + } + // shafts along x + if (COUNT_SHAFTS_TOP_CRATE_X > 2) { + for (index_side_y = [0 : 1 : 1]) { + mirror([0, index_side_y, 0]) { + translate([0, R_BED[1] / 2 - D_WASHER_SHAFT_TOP_CRATE / 2, 0]) for (index_shaft_x = [1 : 1 : COUNT_SHAFTS_TOP_CRATE_X - 2]) { + translate([-R_BED[0] / 2 + D_WASHER_SHAFT_TOP_CRATE / 2 + index_shaft_x * (R_BED[0] - D_WASHER_SHAFT_TOP_CRATE) / (COUNT_SHAFTS_TOP_CRATE_X - 1), 0, 0]) fixing_top_crate_shaft(); + } + } + } + } + } + // Shopping +} + +top_crate_shaft_assembly(); \ No newline at end of file