diff --git a/generic-helpers.scad b/generic-helpers.scad index cd3302c..fbab526 100644 --- a/generic-helpers.scad +++ b/generic-helpers.scad @@ -166,6 +166,8 @@ function affine_translate(vector) = [ * Centered on origin. */ module sweep_rounded(width=10, length=10) { + assert(width > 0 && length > 0); + half_width = width/2; half_length = length/2; path_points = [ diff --git a/gridfinity-rebuilt-baseplate.scad b/gridfinity-rebuilt-baseplate.scad index e9ce842..de3802e 100644 --- a/gridfinity-rebuilt-baseplate.scad +++ b/gridfinity-rebuilt-baseplate.scad @@ -18,9 +18,9 @@ $fs = 0.25; /* [General Settings] */ // number of bases along x-axis -gridx = 5; +gridx = 1; // number of bases along y-axis -gridy = 5; +gridy = 1; /* [Screw Together Settings - Defaults work for M3 and 4-40] */ // screw diameter @@ -48,11 +48,11 @@ fity = 0; // [-1:0.1:1] /* [Styles] */ // baseplate styles -style_plate = 0; // [0: thin, 1:weighted, 2:skeletonized, 3: screw together, 4: screw together minimal] +style_plate = 2; // [0: thin, 1:weighted, 2:skeletonized, 3: screw together, 4: screw together minimal] // hole styles -style_hole = 2; // [0:none, 1:countersink, 2:counterbore] +style_hole = 0; // [0:none, 1:countersink, 2:counterbore] /* [Magnet Hole] */ // Baseplate will have holes for 6mm Diameter x 2mm high magnets. @@ -69,7 +69,6 @@ hole_options = bundle_hole_options(refined_hole=false, magnet_hole=enable_magnet color("tomato") gridfinityBaseplate(gridx, gridy, l_grid, distancex, distancey, style_plate, hole_options, style_hole, fitx, fity); - // ===== CONSTRUCTION ===== // module gridfinityBaseplate(gridx, gridy, length, dix, diy, sp, hole_options, sh, fitx, fity) { @@ -87,44 +86,62 @@ module gridfinityBaseplate(gridx, gridy, length, dix, diy, sp, hole_options, sh, offsetx = dix < dx ? 0 : (gx*length-bp_xy_clearance-dix)/2*fitx*-1; offsety = diy < dy ? 0 : (gy*length-bp_xy_clearance-diy)/2*fity*-1; + screw_together = sp == 3 || sp == 4; + minimal = sp == 0 || sp == 4; + difference() { - translate([offsetx,offsety,h_base]) - mirror([0,0,1]) - rounded_rectangle(dx, dy, h_base+off, r_base); - - gridfinityBase(gx, gy, length, 1, 1, bundle_hole_options(), 0.5, false); - - translate([offsetx,offsety,h_base-0.6]) - rounded_rectangle(dx*2, dy*2, h_base*2, r_base); - pattern_linear(gx, gy, length) { - render(convexity = 6) { + difference() { + if (minimal) { + square_baseplate_lip(off); + } else { + solid_square_baseplate(off); + } - if (sp == 1) - translate([0,0,-off]) + // Bottom/through pattern for the solid baseplates. + if (sp == 1) { cutter_weight(); - else if (sp == 2 || sp == 3) - linear_extrude(10*(h_base+off), center = true) + } else if (sp == 2 || sp == 3) { + translate([0,0,-TOLLERANCE]) + linear_extrude(off+2*TOLLERANCE) profile_skeleton(); - else if (sp == 4) - translate([0,0,-5*(h_base+off)]) - rounded_square(length-2*r_c2-2*r_c1, 10*(h_base+off), r_fo3); - + } + // Add holes to the solid baseplates. hole_pattern(){ + // Manget hole + translate([0, 0, off+TOLLERANCE]) mirror([0, 0, 1]) block_base_hole(hole_options); - translate([0,0,-off-TOLLERANCE]) - if (sh == 1) cutter_countersink(); - else if (sh == 2) cutter_counterbore(); + translate([0,0,-TOLLERANCE]) + if (sh == 1) { + cutter_countersink(); + } else if (sh == 2) { + cutter_counterbore(); + } } + } } - screw_together = sp == 3 || sp == 4; - if (screw_together) cutter_screw_together(gx, gy, off); - } + // Round the outside corners + corner_center_distance = length/2; + copy_mirror([0, 1, 0]) + copy_mirror([1, 0, 0]) + translate([ + (gx*length/2) - BASEPLATE_OUTSIDE_RADIUS, + (gy*length/2) - BASEPLATE_OUTSIDE_RADIUS, + -TOLLERANCE + ]) + scale([1+TOLLERANCE, 1+TOLLERANCE, 1+2*TOLLERANCE]) + square_baseplate_corner(off); + + if (screw_together) { + translate([0, 0, off]) + cutter_screw_together(gx, gy, off); + } + } } function calculate_offset(style_plate, enable_magnet, style_hole) = @@ -182,20 +199,95 @@ module cutter_counterbore(){ } } +/** + * @brief Added or removed from the baseplate to square off or round the corners. + * @param height Baseplate's height excluding lip and clearance height. + */ +module square_baseplate_corner(height=0) { + assert(height >= 0); + linear_extrude(height + BASEPLATE_LIP_MAX.y) + difference() { + square(BASEPLATE_OUTSIDE_RADIUS, center=false); + circle(r=BASEPLATE_OUTSIDE_RADIUS-TOLLERANCE); + } +} + +/** + * @brief Outer edge/lip of the baseplate. + * @details Includes clearance to ensure the base touches the lip + * instead of the bottom. + * @param height Baseplate's height excluding lip and clearance height. + * @param width How wide a single baseplate is. Only set if deviating from the standard! + * @param length How long a single baseplate is. Only set if deviating from the standard! + */ +module baseplate_lip(height=0, width=l_grid, length=l_grid) { + assert(height >= 0); + + // How far, in the +x direction, + // the lip needs to be from it's [0, 0] point + // such that when swept by 90 degrees to produce a corner, + // the outside edge has the desired radius. + translation_x = BASEPLATE_OUTSIDE_RADIUS - BASEPLATE_LIP_MAX.x; + + additional_height = height + BASEPLATE_CLEARANCE_HEIGHT; + + sweep_rounded(width-2*BASEPLATE_OUTSIDE_RADIUS, length-2*BASEPLATE_OUTSIDE_RADIUS) + translate([translation_x, additional_height, 0]) + polygon(concat(BASEPLATE_LIP, [ + [0, -additional_height], + [BASEPLATE_LIP_MAX.x, -additional_height], + [BASEPLATE_LIP_MAX.x, 0] + ])); +} + +/** + * @brief Outer edge/lip of the baseplate, with square corners. + * @details Needed to prevent gaps when joining multiples together. + * @param height Baseplate's height excluding lip and clearance height. + * @param size Width/Length of a single baseplate. Only set if deviating from the standard! + */ +module square_baseplate_lip(height=0, size = l_grid) { + assert(height >= 0 && size/2 >= BASEPLATE_OUTSIDE_RADIUS); + corner_center_distance = size/2 - BASEPLATE_OUTSIDE_RADIUS; + union() { + baseplate_lip(height, size, size); + pattern_circular(4) + translate([corner_center_distance, corner_center_distance, 0]) + square_baseplate_corner(height); + } +} + +/** + * @brief A single baseplate with square corners, a solid inner section, lip and the set clearance height. + * @param height Baseplate's height excluding lip and clearance height. + * @details A height of zero is the equivalent of just calling square_baseplate_lip() + */ +module solid_square_baseplate(height=0, length = l_grid) { + assert(height >= 0); + union() { + square_baseplate_lip(height, length); + if (height > 0) { + linear_extrude(height) + square(length - BASEPLATE_OUTSIDE_RADIUS, center=true); + } + } +} + /** * @brief 2d Cutter to skeletonize the baseplate. + * @param size Width/Length of a single baseplate. Only set if deviating from the standard! * @example difference(){ * cube(large_number); * linear_extrude(large_number+TOLLERANCE) * profile_skeleton(); * } */ -module profile_skeleton() { - l = l_grid-2*r_c2-2*r_c1; +module profile_skeleton(size=l_grid) { + l = size - 2*BASEPLATE_LIP_MAX.x; offset(r_skel) difference() { - square(l-2*r_skel+2*d_clear, center = true); + square(l-2*r_skel, center = true); hole_pattern() offset(MAGNET_HOLE_RADIUS+r_skel+2) diff --git a/standard.scad b/standard.scad index 1ceb504..f80f2c8 100644 --- a/standard.scad +++ b/standard.scad @@ -88,8 +88,11 @@ h_lip = 3.548; d_wall2 = r_base-r_c1-d_clear*sqrt(2); d_magic = -2*d_clear-2*d_wall+d_div; -// Stacking Lip + +// **************************************** +// Stacking Lip Constants // Based on https://gridfinity.xyz/specification/ +// **************************************** stacking_lip_inner_slope_height_mm = 0.7; stacking_lip_wall_height_mm = 1.8; stacking_lip_outer_slope_height_mm = 1.9; @@ -106,8 +109,40 @@ stacking_lip_support_wall_height_mm = 1.2; stacking_lip_support_height_mm = stacking_lip_support_wall_height_mm + d_wall2; - +// **************************************** // Baseplate constants +// Based on https://gridfinity.xyz/specification/ +// **************************************** +BASEPLATE_OUTSIDE_RADIUS = 8 / 2; + +// Polygon describing the raw baseplate lip. +// Does NOT include clearance height. +BASEPLATE_LIP = [ + [0, 0], // Innermost bottom point + [0.7, 0.7], // Up and out at a 45 degree angle + [0.7, (0.7+1.8)], // Straight up + [(0.7+2.15), (0.7+1.8+2.15)], // Up and out at a 45 degree angle + [(0.7+2.15), 0], // Straight down + [0, 0] //Back to start +]; + +// Height of the baseplate lip. +// This ads clearance height to the polygon +// that ensures the base makes contact with the baseplate lip. +BASEPLATE_LIP_HEIGHT = 5; + +// The minimum height between the baseplate lip and anything below it. +// Needed to make sure the base always makes contact with the baseplate lip. +BASEPLATE_CLEARANCE_HEIGHT = BASEPLATE_LIP_HEIGHT - BASEPLATE_LIP[3].y; +assert(BASEPLATE_CLEARANCE_HEIGHT > 0, "Negative clearance doesn't make sense."); + +// Maximum [x,y] values/size of the baseplate lip. +// Includes clearance height! +BASEPLATE_LIP_MAX = [BASEPLATE_LIP[3].x, BASEPLATE_LIP_HEIGHT]; + +// **************************************** +// Weighted Baseplate +// **************************************** // Baseplate bottom part height (part added with weigthed=true) bp_h_bot = 6.4; @@ -121,6 +156,9 @@ bp_rcut_width = 8.5; bp_rcut_length = 4.25; // Baseplate bottom cutout rounded thingy depth bp_rcut_depth = 2; + +// **************************************** + // Baseplate clearance offset bp_xy_clearance = 0.5; // radius of cutout for skeletonized baseplate