diff --git a/README.md b/README.md index a88138d..69c717c 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,6 @@ Prints from this library are still challenging, despite all efforts to the contr That's it, if you have any questions feel free to open an issue or leave a comment on thingiverse! ## TODO: - * enable customizer to print spacebars * switch dishing logic from a super large cube to a bounding box intersection * update this documentation! * replace linear_extrude_shape_hull with skin_extrude_shape_hull or something, to enable concave extrusions diff --git a/customizer.scad b/customizer.scad index 79a6cb5..61dba62 100644 --- a/customizer.scad +++ b/customizer.scad @@ -116,7 +116,7 @@ $dish_overdraw_height = 0; /* Misc */ // how tall in mm the brim is, if there is one. brim sits around the keystem and helps to secure it while printing. -$brim_height = 0.4; +$stem_support_height = 0.4; // font used for text $font="DejaVu Sans Mono:style=Book"; // whether or not to render fake keyswitches to check clearances @@ -492,7 +492,7 @@ module translate_u(x=0, y=0, z=0){ module brimmed(height = 0.2) { $has_brim = true; - $brim_height = height; + $stem_support_height = height; children(); } @@ -779,7 +779,7 @@ module cherry_stem(depth, has_brim, slop) { // brim, if applicable if(has_brim) { - linear_extrude(height = $brim_height){ + linear_extrude(height = $stem_support_height){ offset(r=1){ square(outer_cherry_stem(slop) + [2,2], center=true); } @@ -815,7 +815,7 @@ module rounded_cherry_stem(depth, has_brim, slop) { union(){ cylinder(d=$rounded_cherry_stem_d, h=depth); if(has_brim) { - cylinder(d=$rounded_cherry_stem_d * 2, h=$brim_height); + cylinder(d=$rounded_cherry_stem_d * 2, h=$stem_support_height); } } @@ -831,7 +831,7 @@ module rounded_cherry_stem(depth, has_brim, slop) { } module alps_stem(depth, has_brim, slop){ if(has_brim) { - linear_extrude(height=$brim_height) { + linear_extrude(height=$stem_support_height) { offset(r=1){ square($alps_stem + [2,2], center=true); } @@ -1661,7 +1661,7 @@ $dish_overdraw_height = 0; /* Misc */ // how tall in mm the brim is, if there is one. brim sits around the keystem and helps to secure it while printing. -$brim_height = 0.4; +$stem_support_height = 0.4; // font used for text $font="DejaVu Sans Mono:style=Book"; // whether or not to render fake keyswitches to check clearances diff --git a/keys.scad b/keys.scad index e0a19e7..765a365 100644 --- a/keys.scad +++ b/keys.scad @@ -13,16 +13,9 @@ include include include -translate_u(0, 0) sa_row(3) stepped_caps_lock() { - key(); -} -translate_u(0, 1) sa_row(2) lshift() { - $stem_type = false; - key(); -} - -translate_u(0, 2) sa_row(1) spacebar() alps() { - $support_type = false; - key(); +//$has_brim=true; +sa_row(3) { + $stem_slop = 0; + key(); } diff --git a/src/functions.scad b/src/functions.scad new file mode 100644 index 0000000..6f99736 --- /dev/null +++ b/src/functions.scad @@ -0,0 +1,25 @@ +// I use functions when I need to compute special variables off of other special variables +// functions need to be explicitly included, unlike special variables, which +// just need to have been set before they are used. hence this file + +// cherry stem dimensions +function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; + +// box (kailh) switches have a bit less to work with +function outer_box_cherry_stem(slop) = [6 - slop, 6 - slop]; + +// .005 purely for aesthetics, to get rid of that ugly crosshatch +function cherry_cross(slop, extra_vertical = 0) = [ + // horizontal tine + [4.03 + slop, 1.15 + slop / 3], + // vertical tine + [1.25 + slop / 3, 4.23 + extra_vertical + slop / 3 + .005], +]; + +// actual mm key width and height +function total_key_width(delta = 0) = $bottom_key_width + $unit * ($key_length - 1) - delta; +function total_key_height(delta = 0) = $bottom_key_height + $unit * ($key_height - 1) - delta; + +// actual mm key width and height at the top +function top_total_key_width() = $bottom_key_width + ($unit * ($key_length - 1)) - $width_difference; +function top_total_key_height() = $bottom_key_height + ($unit * ($key_height - 1)) - $height_difference; diff --git a/src/key.scad b/src/key.scad index 5f31a42..e8bd96d 100644 --- a/src/key.scad +++ b/src/key.scad @@ -1,6 +1,8 @@ // files +include include include +include include include include @@ -10,34 +12,23 @@ include /* [Hidden] */ $fs = .1; -unit = 19.05; -color1 = [.2667,.5882,1]; +$unit = 19.05; +blue = [.2667,.5882,1]; color2 = [.5412, .4784, 1]; -color3 = [.4078, .3569, .749]; -color4 = [1, .6941, .2]; +purple = [.4078, .3569, .749]; +yellow = [1, .6941, .2]; transparent_red = [1,0,0, 0.15]; -// derived values. can't be variables if we want them to change when the special variables do - -// actual mm key width and height -function total_key_width(delta = 0) = $bottom_key_width + unit * ($key_length - 1) - delta; -function total_key_height(delta = 0) = $bottom_key_height + unit * ($key_height - 1) - delta; - -// actual mm key width and height at the top -function top_total_key_width() = $bottom_key_width + (unit * ($key_length - 1)) - $width_difference; -function top_total_key_height() = $bottom_key_height + (unit * ($key_height - 1)) - $height_difference; - - // key shape including dish. used as the ouside and inside shape in keytop(). allows for itself to be shrunk in depth and width / height module shape(thickness_difference, depth_difference){ dished(depth_difference, $inverted_dish) { - color(color1) shape_hull(thickness_difference, depth_difference, 2); + color(blue) shape_hull(thickness_difference, depth_difference, 2); } } // shape of the key but with soft, rounded edges. much more realistic, MUCH more complex. orders of magnitude more complex module rounded_shape() { - color(color1) minkowski(){ + color(blue) minkowski(){ // half minkowski in the z direction shape($minkowski_radius * 2, $minkowski_radius/2); difference(){ @@ -130,7 +121,7 @@ module top_placement(depth_difference) { // just to DRY up the code module _dish() { - color(color3) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); + color(purple) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish); } // for when you want to take the dish out of things @@ -144,9 +135,9 @@ module dished(depth_difference, inverted = false) { difference(){ union() { // this weird math here is so Customizer doesn't see a giant shape and zoom out a million miles. could just be cube(1000) - translate([-$key_length * unit, -$key_height * unit]) cube([ - $key_length*2 * unit, - $key_height*2 * unit, + translate([-$key_length * $unit, -$key_height * $unit]) cube([ + $key_length*2 * $unit, + $key_height*2 * $unit, 50 ]); if (!inverted) _dish(); @@ -192,13 +183,16 @@ module keystem_positions(positions) { module support_for(positions, stem_type) { keystem_positions(positions) { - color(color4) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw); + color(yellow) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw); } } module stems_for(positions, stem_type) { keystem_positions(positions) { - color(color4) stem(stem_type, $total_depth, $has_brim, $stem_slop); + color(yellow) stem(stem_type, $total_depth, $stem_slop); + if ($stem_support_type != "disable") { + color(color2) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop); + } } } diff --git a/src/key_transformations.scad b/src/key_transformations.scad index 489fb10..3c9495d 100644 --- a/src/key_transformations.scad +++ b/src/key_transformations.scad @@ -7,9 +7,15 @@ module translate_u(x=0, y=0, z=0){ translate([x * unit, y*unit, z*unit]) children(); } -module brimmed(height = 0.2) { - $has_brim = true; - $brim_height = height; +module brimmed_stem_support(height = 0.4) { + $stem_support_type = "brim"; + $stem_support_height = height; + children(); +} + +module tined_stem_support(height = 0.4) { + $stem_support_type = "tines"; + $stem_support_height = height; children(); } @@ -49,7 +55,7 @@ module stabilized(mm=12, vertical = false, type="cherry") { } module dishless() { - $dish_type = "no dish"; + $dish_type = "disable"; children(); } @@ -64,7 +70,7 @@ module filled() { } module blank() { - $stem_type = "blank"; + $stem_type = "disable"; children(); } @@ -86,6 +92,12 @@ module rounded_cherry(slop) { children(); } +module box_cherry(slop) { + $stem_slop = slop ? slop : $stem_slop; + $stem_type = "box_cherry"; + children(); +} + module flared_support() { $support_type = "flared"; children(); diff --git a/src/key_types.scad b/src/key_types.scad index 51bc02f..d6e568e 100644 --- a/src/key_types.scad +++ b/src/key_types.scad @@ -47,7 +47,7 @@ module iso_enter() { $key_shape_type = "iso_enter"; $linear_extrude_shape = true; $linear_extrude_height_adjustment = 19.05 * 0.5; - // (unit_length(1.5) - unit_length(1.25)) / 2 + // this equals (unit_length(1.5) - unit_length(1.25)) / 2 $dish_overdraw_width = 2.38125; diff --git a/src/settings.scad b/src/settings.scad index e744d82..631e276 100644 --- a/src/settings.scad +++ b/src/settings.scad @@ -1,7 +1,7 @@ /* [Basic-Settings] */ // what type of stem you want. Most people want Cherry. -$stem_type = "cherry"; // [cherry, alps, rounded_cherry, filled, disable] +$stem_type = "cherry"; // [cherry, alps, rounded_cherry, box_cherry, filled, disable] // support type. default is "flared" for easy FDM printing; bars are more realistic, and flat could be for artisans $support_type = "flared"; // [flared, bars, flat, disable] @@ -9,9 +9,8 @@ $support_type = "flared"; // [flared, bars, flat, disable] // length in units of key. A regular key is 1 unit; spacebar is usually 6.25 $key_length = 1.0; // range not working in thingiverse customizer atm [1:0.25:16] -// print brim for connector to help with bed adhesion -$has_brim = false; - +// supports for the stem, as it often comes off during printing. disabled by default, but highly reccommended. +$stem_support_type = "disable"; // [brim, tines, disabled] // the stem is the hardest part to print, so this variable controls how much 'slop' there is in the stem $stem_slop = 0.3; // not working in thingiverse customizer atm [0:0.01:1] @@ -101,9 +100,11 @@ $dish_overdraw_width = 0; $dish_overdraw_height = 0; /* Misc */ +// there's a bevel on the cherry stems to aid insertion / guard against first layer squishing making a hard-to-fit stem. +$cherry_bevel = true; -// how tall in mm the brim is, if there is one. brim sits around the keystem and helps to secure it while printing. -$brim_height = 0.4; +// how tall in mm the stem support is, if there is any. stem support sits around the keystem and helps to secure it while printing. +$stem_support_height = 0.4; // font used for text $font="DejaVu Sans Mono:style=Book"; // whether or not to render fake keyswitches to check clearances diff --git a/src/stem_supports.scad b/src/stem_supports.scad new file mode 100644 index 0000000..4e24a61 --- /dev/null +++ b/src/stem_supports.scad @@ -0,0 +1,16 @@ +include +include + + +//whole stem, alps or cherry, trimmed to fit +module stem_support(support_type, stem_type, stem_support_height, slop){ + if (support_type == "brim") { + brim_support(stem_type, stem_support_height, slop); + } else if (support_type == "tines") { + tines_support(stem_type, stem_support_height, slop); + } else if (support_type == "disable") { + children(); + } else { + echo("Warning: unsupported $stem_support_type"); + } +} diff --git a/src/stem_supports/brim.scad b/src/stem_supports/brim.scad new file mode 100644 index 0000000..327d054 --- /dev/null +++ b/src/stem_supports/brim.scad @@ -0,0 +1,37 @@ +include <../functions.scad> +include <../stems/cherry.scad> + +module brim_support(stem_type, stem_support_height, slop) { + if(stem_type == "alps") { + linear_extrude(height=stem_support_height) { + offset(r=1){ + square($alps_stem + [2,2], center=true); + } + } + } else if (stem_type == "cherry") { + difference() { + linear_extrude(height = stem_support_height){ + offset(r=1){ + square(outer_cherry_stem(slop) + [2,2], center=true); + } + } + + inside_cherry_cross(slop); + } + } else if (stem_type == "rounded_cherry") { + difference() { + cylinder(d=$rounded_cherry_stem_d * 2, h=stem_support_height); + inside_cherry_cross(slop); + } + } else if (stem_type == "box_cherry") { + difference() { + linear_extrude(height = stem_support_height){ + offset(r=1){ + square(outer_box_cherry_stem(slop) + [2,2], center=true); + } + } + + inside_cherry_cross(slop); + } + } +} diff --git a/src/stem_supports/tines.scad b/src/stem_supports/tines.scad new file mode 100644 index 0000000..a12ee13 --- /dev/null +++ b/src/stem_supports/tines.scad @@ -0,0 +1,35 @@ +include <../functions.scad> +include <../cherry.scad> + +module centered_tines(stem_support_height) { + translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness), 1, $stem_support_height], center = true); + translate([0,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); +} + +module tines_support(stem_type, stem_support_height, slop) { + if (stem_type == "cherry") { + difference () { + union() { + translate([0,0,$stem_support_height / 2]) cube([total_key_width($wall_thickness), 1, $stem_support_height], center = true); + translate([2,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); + translate([-2,0,$stem_support_height / 2]) cube([1, total_key_height($wall_thickness), $stem_support_height], center = true); + } + + inside_cherry_cross(slop); + } + } else if (stem_type == "box_cherry") { + difference () { + centered_tines(stem_support_height); + + inside_cherry_cross(slop); + } + } else if (stem_type == "rounded_cherry") { + difference () { + centered_tines(stem_support_height); + + inside_cherry_cross(slop); + } + } else if (stem_type == "alps"){ + centered_tines(stem_support_height); + } +} diff --git a/src/stems.scad b/src/stems.scad index a82e012..0f36c2f 100644 --- a/src/stems.scad +++ b/src/stems.scad @@ -1,17 +1,20 @@ include include +include include include //whole stem, alps or cherry, trimmed to fit -module stem(stem_type, depth, has_brim, slop){ +module stem(stem_type, depth, slop){ if (stem_type == "alps") { - alps_stem(depth, has_brim, slop); - } else if (stem_type == "rounded_cherry") { - rounded_cherry_stem(depth, has_brim, slop); + alps_stem(depth, slop); } else if (stem_type == "cherry") { - cherry_stem(depth, has_brim, slop); + cherry_stem(depth, slop); + } else if (stem_type == "rounded_cherry") { + rounded_cherry_stem(depth, slop); + } else if (stem_type == "box_cherry") { + box_cherry_stem(depth, slop); } else if (stem_type == "filled") { filled_stem(); } else if (stem_type == "disable") { diff --git a/src/stems/alps.scad b/src/stems/alps.scad index 7b0debd..404ad0e 100644 --- a/src/stems/alps.scad +++ b/src/stems/alps.scad @@ -1,11 +1,4 @@ module alps_stem(depth, has_brim, slop){ - if(has_brim) { - linear_extrude(height=$brim_height) { - offset(r=1){ - square($alps_stem + [2,2], center=true); - } - } - } linear_extrude(height=depth) { square($alps_stem, center = true); } diff --git a/src/stems/box_cherry.scad b/src/stems/box_cherry.scad new file mode 100644 index 0000000..f7db595 --- /dev/null +++ b/src/stems/box_cherry.scad @@ -0,0 +1,16 @@ +include <../functions.scad> +include + +module box_cherry_stem(depth, slop) { + difference(){ + // outside shape + linear_extrude(height = depth) { + offset(r=1){ + square(outer_box_cherry_stem(slop) - [2,2], center=true); + } + } + + // inside cross + inside_cherry_cross(slop); + } +} diff --git a/src/stems/cherry.scad b/src/stems/cherry.scad index 64843d0..1f006ae 100644 --- a/src/stems/cherry.scad +++ b/src/stems/cherry.scad @@ -1,46 +1,37 @@ -// cherry stem dimensions -function outer_cherry_stem(slop) = [7.2 - slop * 2, 5.5 - slop * 2]; +include <../functions.scad> -// .005 purely for aesthetics, to get rid of that ugly crosshatch -function cherry_cross(slop) = [ - // horizontal tine - [4.03 + slop, 1.15 + slop / 3], - // vertical tine - [1.25 + slop / 3, 4.9 + slop / 3 + .005], -]; +// extra length to the vertical tine of the inside cherry cross +// splits the stem into halves - allows easier fitment +extra_vertical = 0.6; -module cherry_stem(depth, has_brim, slop) { - difference(){ - union() { - // outside shape - linear_extrude(height = depth) { - offset(r=1){ - square(outer_cherry_stem(slop) - [2,2], center=true); - } - } - - // brim, if applicable - if(has_brim) { - linear_extrude(height = $brim_height){ - offset(r=1){ - square(outer_cherry_stem(slop) + [2,2], center=true); - } - } - } +module inside_cherry_cross(slop) { + // inside cross + // translation purely for aesthetic purposes, to get rid of that awful lattice + translate([0,0,-0.005]) { + linear_extrude(height = $stem_throw) { + square(cherry_cross(slop, extra_vertical)[0], center=true); + square(cherry_cross(slop, extra_vertical)[1], center=true); } + } - // inside cross - // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-0.005]) { - linear_extrude(height = $stem_throw) { - square(cherry_cross(slop)[0], center=true); - square(cherry_cross(slop)[1], center=true); - } - // Guides to assist insertion and mitigate first layer squishing - for (i = cherry_cross(slop)) hull() { - linear_extrude(height = 0.01, center = false) offset(delta = 0.4) square(i, center=true); - translate([0, 0, 0.5]) linear_extrude(height = 0.01, center = false) square(i, center=true); - } + // Guides to assist insertion and mitigate first layer squishing + if ($cherry_bevel){ + for (i = cherry_cross(slop, extra_vertical)) hull() { + linear_extrude(height = 0.01, center = false) offset(delta = 0.4) square(i, center=true); + translate([0, 0, 0.5]) linear_extrude(height = 0.01, center = false) square(i, center=true); } } } + +module cherry_stem(depth, slop) { + difference(){ + // outside shape + linear_extrude(height = depth) { + offset(r=1){ + square(outer_cherry_stem(slop) - [2,2], center=true); + } + } + + inside_cherry_cross(slop); + } +} diff --git a/src/stems/filled.scad b/src/stems/filled.scad index 5dc9152..e12bfde 100644 --- a/src/stems/filled.scad +++ b/src/stems/filled.scad @@ -5,5 +5,5 @@ module filled_stem() { // cube. shape() works but means that you certainly couldn't render this // stem without the presence of the entire library - shape(); + shape($wall_thickness); } diff --git a/src/stems/rounded_cherry.scad b/src/stems/rounded_cherry.scad index d470688..3d6aab7 100644 --- a/src/stems/rounded_cherry.scad +++ b/src/stems/rounded_cherry.scad @@ -1,27 +1,12 @@ -// .005 purely for aesthetics, to get rid of that ugly crosshatch -function cherry_cross(slop) = [ - // horizontal tine - [4.03 + slop, 1.15 + slop / 3], - // vertical tine. can't really afford much slop - [1.25 + slop / 3, 4.9 + slop / 6 + .005], -]; +include <../functions.scad> +include -module rounded_cherry_stem(depth, has_brim, slop) { +module rounded_cherry_stem(depth, slop) { difference(){ - union(){ - cylinder(d=$rounded_cherry_stem_d, h=depth); - if(has_brim) { - cylinder(d=$rounded_cherry_stem_d * 2, h=$brim_height); - } - } + cylinder(d=$rounded_cherry_stem_d, h=depth); // inside cross // translation purely for aesthetic purposes, to get rid of that awful lattice - translate([0,0,-0.005]) { - linear_extrude(height = $stem_throw) { - square(cherry_cross(slop)[0], center=true); - square(cherry_cross(slop)[1], center=true); - } - } + inside_cherry_cross(slop); } } diff --git a/src/supports/flared.scad b/src/supports/flared.scad index 73cccc9..4d6a232 100644 --- a/src/supports/flared.scad +++ b/src/supports/flared.scad @@ -1,6 +1,4 @@ -// cherry stem dimensions -// don't wanna introduce slop here so $stem_slop it is I guess -function outer_cherry_stem() = [7.2 - $stem_slop * 2, 5.5 - $stem_slop * 2]; +include <../functions.scad> // figures out the scale factor needed to make a 45 degree wall function scale_for_45(height, starting_size) = (height * 2 + starting_size) / starting_size; @@ -18,13 +16,22 @@ module flared(stem_type, loft, height) { linear_extrude(height=height, scale = alps_scale){ square($alps_stem, center=true); } + } else if (stem_type == "box_cherry") { + // always render cherry if no stem type. this includes stem_type = false! + // this avoids a bug where the keycap is rendered filled when not desired + cherry_scale = [scale_for_45(height, outer_box_cherry_stem($stem_slop)[0]), scale_for_45(height, outer_box_cherry_stem($stem_slop)[1])]; + linear_extrude(height=height, scale = cherry_scale){ + offset(r=1){ + square(outer_box_cherry_stem($stem_slop) - [2,2], center=true); + } + } } else { // always render cherry if no stem type. this includes stem_type = false! // this avoids a bug where the keycap is rendered filled when not desired - cherry_scale = [scale_for_45(height, outer_cherry_stem()[0]), scale_for_45(height, outer_cherry_stem()[1])]; + cherry_scale = [scale_for_45(height, outer_cherry_stem($stem_slop)[0]), scale_for_45(height, outer_cherry_stem($stem_slop)[1])]; linear_extrude(height=height, scale = cherry_scale){ offset(r=1){ - square(outer_cherry_stem() - [2,2], center=true); + square(outer_cherry_stem($stem_slop) - [2,2], center=true); } } }