// VARIABLES //
///////////////////////////////////////////////////////////////////////////////
-/* Set output quality */
+// Set output quality
$fn = 150;
-/* Distance between key centers. */
+// Distance between key centers.
column_spacing = 19;
row_spacing = column_spacing;
/* This number should exceed row_spacing and column_spacing. The default gives
- a 1mm = (20mm - 19mm) gap between keycaps and cuts in the top plate. */
+ a 1mm = (20mm - 19mm) gap between keycaps and cuts in the top plate. */
key_hole_size = 20;
-/* The angle between the halves is twice this number */
+// The angle between the halves is twice this number
angle = 10;
/* This constant allows tweaking the location of the screw holes near the USB
- cable. Only useful with small `angle` values. Try the value of 10 with
- angle=0. */
+ cable. Only useful with small `angle` values. Try the value of 10 with
+ angle=0. */
back_screw_hole_offset = 0;
/* The radius of screw holes. Holes will be slightly bigger due to the cut
- width. */
+ width. */
screw_hole_radius = 1.5;
/* Each screw hole is a hole in a "washer". How big these "washers" depends on
- the material used: this parameter and the `switch_hole_size` determine the
- spacer wall thickness. */
+ the material used: this parameter and the `switch_hole_size` determine the
+ spacer wall thickness. */
washer_radius = 4 * screw_hole_radius;
/* The approximate size of switch holes. Used to determine how thick walls can
- be, i.e. how much room around each switch hole to leave. See spacer(). */
+ be, i.e. how much room around each switch hole to leave. See spacer(). */
switch_hole_size = 14;
-/* Distance between halves. */
+// Distance between halves.
hand_separation = key_hole_size - switch_hole_size;
-/* Sets whether the case should use notched holes. As far as I can tell these
- notches are not all that useful... */
-use_notched_holes = true;
-
/* Number of rows and columns in the matrix. You need to update
- staggering_offsets if you change n_cols. */
+ staggering_offsets if you change n_cols. */
n_rows = 4;
n_cols = 5;
-/* The width of the USB cable hole in the spacer. */
+// The width of the USB cable hole in the spacer.
cable_hole_width = 12;
-/* Vertical column staggering offsets. The first element should be zero. */
+// Vertical column staggering offsets. The first element should be zero.
staggering_offsets = [0, 5, 11, 6, 3];
-/* Width and height between screw holes of OLED */
+// Width and height between screw holes of OLED
oled_width = 20;
-oled_height = 20;
-
-/* Width and height between screw holes of pointer */
-pointer_width = 10.5;
-pointer_height = 10.5;
+oled_height = 18;
///////////////////////////////////////////////////////////////////////////////
// META MODULES //
///////////////////////////////////////////////////////////////////////////////
module rz(angle, center=undef) {
- /* Rotate children `angle` degrees around `center`. */
- translate(center) {
- rotate(angle) {
- translate(-center) {
- for (i=[0:$children-1])
- children(i);
- }
- }
- }
+ // Rotate children `angle` degrees around `center`.
+ translate(center) {
+ rotate(angle) {
+ translate(-center) {
+ for (i=[0:$children-1])
+ children(i);
+ }
+ }
+ }
}
/* Compute coordinates of a point obtained by rotating p angle degrees around
- center. Used to compute locations of screw holes near the USB cable hole. */
+ center. Used to compute locations of screw holes near the USB cable hole. */
function rz_fun(p, angle, center) = [
- cos(angle) * (p[0] - center[0]) - sin(angle) * (p[1] - center[1]) + center[0],
- sin(angle) * (p[0] - center[0]) + cos(angle) * (p[1] - center[1])+ center[1]];
+ cos(angle) * (p[0] - center[0]) - sin(angle) * (p[1] - center[1]) + center[0],
+ sin(angle) * (p[0] - center[0]) + cos(angle) * (p[1] - center[1])+ center[1]];
/* Cherry MX switch hole with the center at `position`. Sizes come from the
- ErgoDox design. */
-module switch_hole(position, notches=use_notched_holes) {
- hole_size = 13.97;
- notch_width = 3.5001;
- notch_offset = 4.2545;
- notch_depth = 0.8128;
- translate(position) {
- union() {
- square([hole_size, hole_size], center=true);
- if (notches == true) {
- translate([0, notch_offset]) {
- square([hole_size+2*notch_depth, notch_width], center=true);
- }
- translate([0, -notch_offset]) {
- square([hole_size+2*notch_depth, notch_width], center=true);
- }
- }
- }
- }
+ ErgoDox design. */
+module switch_hole(position) {
+ hole_size = 13.97;
+ notch_width = 3.5001;
+ notch_offset = 4.2545;
+ notch_depth = 0.8128;
+ translate(position) {
+ square([hole_size, hole_size], center=true);
+ }
};
-/* Create a hole for a regular key */
+// Create a hole for a regular key
module regular_key(position, size) {
- translate(position) {
- square([size, size], center=true);
- }
+ translate(position) {
+ square([size, size], center=true);
+ }
}
-/* Create a column of keys */
+// Create a column of keys
module column (bottom_position, switch_holes, key_size=key_hole_size,
- rows=n_rows) {
- translate(bottom_position) {
- for (i = [0:(rows-1)]) {
- if (switch_holes == true) {
- switch_hole([0, i*column_spacing]);
- } else {
- regular_key([0, i*column_spacing], key_size);
- }
- }
- }
+ rows=n_rows) {
+ translate(bottom_position) {
+ for (i = [0:(rows-1)]) {
+ if (switch_holes == true) {
+ switch_hole([0, i*column_spacing]);
+ } else {
+ regular_key([0, i*column_spacing], key_size);
+ }
+ }
+ }
}
/* Rotate the right half of the keys around the top left corner of the thumb
- key. Assumes that the thumb key is a 1x1.5 key and that it is shifted
- 0.5*column_spacing up relative to the nearest column. */
+ key. Assumes that the thumb key is a 1x1.5 key and that it is shifted
+ 0.5*column_spacing up relative to the nearest column. */
module rotate_half() {
- rotation_y_offset = 1.75 * column_spacing;
- for (i=[0:$children-1]) {
- rz(angle, [hand_separation, rotation_y_offset]) {
- children(i);
- }
- }
+ rotation_y_offset = 1.75 * column_spacing;
+ for (i=[0:$children-1]) {
+ rz(angle, [hand_separation, rotation_y_offset]) {
+ children(i);
+ }
+ }
}
-/* Shift everything right to get desired hand separation */
+// Shift everything right to get desired hand separation
module add_hand_separation() {
- for (i=[0:$children-1]) {
- /* Half the value because when it is mirrored, it gets cancelled out */
- translate([0.5*hand_separation, 0]) children(i);
- }
+ for (i=[0:$children-1]) {
+ // Half the value because when it is mirrored, it gets cancelled out
+ translate([0.5*hand_separation, 0]) children(i);
+ }
}
-module screw_hole(radius, offset_radius, position, direction) {
- /* Create a screw hole of radius `radius` at a location `offset_radius` from
- `position`, (diagonally), in the direction `direction`. Oh, what a mess
- this is.
-
- direction is the 2-element vector specifying to which side of position to
- move to, [-1, -1] for bottom left, etc.
-
- radius_offset is the offset in the x (or y) direction so that we're
- offset_radius from position */
- radius_offset = offset_radius / sqrt(2);
-
- /* key_hole_offset if the difference between key spacing and key hole edge */
- key_hole_offset = 0.5*(row_spacing - key_hole_size);
- x = position[0] + (radius_offset - key_hole_offset) * direction[0];
- y = position[1] + (radius_offset - key_hole_offset) * direction[1];
- translate([x,y]) {
- circle(radius);
- }
+module screw_hole(radius, offset_radius, position=[0,0], direction=[0,0]) {
+ /* Create a screw hole of radius `radius` at a location `offset_radius` from
+ `position`, (diagonally), in the direction `direction`. Oh, what a mess
+ this is.
+
+ direction is the 2-element vector specifying to which side of position to
+ move to, [-1, -1] for bottom left, etc.
+
+ radius_offset is the offset in the x (or y) direction so that we're
+ offset_radius from position */
+ radius_offset = offset_radius / sqrt(2);
+
+ // key_hole_offset if the difference between key spacing and key hole edge
+ key_hole_offset = 0.5*(row_spacing - key_hole_size);
+ x = position[0] + (radius_offset - key_hole_offset) * direction[0];
+ y = position[1] + (radius_offset - key_hole_offset) * direction[1];
+ translate([x,y]) {
+ circle(radius);
+ }
}
-/* Create screw holes for the oled screen */
+// Create screw holes for the oled screen
module oled_holes(hole_radius) {
- translate([0,85]) {
- translate([-oled_width/2,-oled_height/2]) {
- translate([0, oled_height]) {
- screw_hole(hole_radius, washer_radius);
- }
- translate([oled_width, oled_height]) {
- screw_hole(hole_radius, washer_radius);
- }
- translate([oled_width, 0]) {
- screw_hole(hole_radius, washer_radius);
- }
- screw_hole(hole_radius, washer_radius);
- }
- }
- oled_passthrough();
+ translate([0,85]) {
+ translate([-oled_width/2,-oled_height/2]) {
+ translate([0, oled_height]) {
+ screw_hole(hole_radius, washer_radius);
+ }
+ translate([oled_width, oled_height]) {
+ screw_hole(hole_radius, washer_radius);
+ }
+ translate([oled_width, 0]) {
+ screw_hole(hole_radius, washer_radius);
+ }
+ screw_hole(hole_radius, washer_radius);
+ }
+ }
+ oled_passthrough();
}
-/* Passthrough in switch plate for the OLED cables */
+// Passthrough in switch plate for the OLED cables
module oled_passthrough() {
- translate([0, 97]) {
- square([14, 8], center=true);
- }
-}
-
-/* Create screw holes for the pointer module */
-module pointer_holes(hole_radius) {
- rotate(angle) {
- translate([column_spacing*1.95, row_spacing*2.5]) {
- translate([-pointer_width/2,-pointer_height/2]) {
- translate([0, pointer_height]) {
- screw_hole(hole_radius, washer_radius);
- }
- translate([pointer_width, pointer_height]) {
- screw_hole(hole_radius, washer_radius);
- }
- translate([pointer_width, 0]) {
- screw_hole(hole_radius, washer_radius);
- }
- screw_hole(hole_radius, washer_radius);
- }
- }
- }
- pointer_passthrough();
-}
-
-module pointer_passthrough() {
- rotate(angle) {
- translate([column_spacing*1.95-4, 16+row_spacing*2.5]) {
- square([pointer_width+5, 15], center=true);
- }
- }
-}
-
-// Arduino Pro mini
-module promini(){
- square([20, 30], center=true);
-}
-
-module prominis(){
- translate([-18, 60]) {
- rotate(-angle-90) {
- promini();
- }
- }
- translate([30, 95]) {
- rotate(90) {
- promini();
- }
- }
+ translate([0, 97]) {
+ square([14, 8], center=true);
+ }
}
module right_screw_holes(hole_radius) {
- /* Coordinates of the back right screw hole before rotation... */
- back_right = [(n_cols+2)*row_spacing,
- staggering_offsets[n_cols-1] + n_rows * column_spacing];
-
- /* ...and after */
- tmp = rz_fun(back_right, angle, [0, 2.25*column_spacing]);
-
- nudge = 0.75;
-
- rotate_half() {
- add_hand_separation() {
- screw_hole(hole_radius, washer_radius,
- [row_spacing, 0],
- [-nudge, -nudge]);
- screw_hole(hole_radius, washer_radius,
- [(n_cols+2)*row_spacing, staggering_offsets[n_cols-1]],
- [nudge, -nudge]);
- screw_hole(hole_radius, washer_radius,
- back_right,
- [nudge, nudge]);
- }
- }
-
- /* Add the screw hole near the cable hole */
- translate([washer_radius - tmp[0] - 0.5*hand_separation,
- back_screw_hole_offset]) {
- rotate_half() {
- add_hand_separation() {
- screw_hole(hole_radius, washer_radius, back_right, [nudge, nudge]);
- }
- }
- }
+ // Coordinates of the back right screw hole before rotation...
+ back_right = [(n_cols+2)*row_spacing,
+ staggering_offsets[n_cols-1] + n_rows * column_spacing];
+
+ // ...and after
+ tmp = rz_fun(back_right, angle, [0, 2.25*column_spacing]);
+
+ nudge = 0.75;
+
+ rotate_half() {
+ add_hand_separation() {
+ screw_hole(hole_radius, washer_radius,
+ [row_spacing, 0],
+ [-nudge, -nudge]);
+ screw_hole(hole_radius, washer_radius,
+ [(n_cols+2)*row_spacing, staggering_offsets[n_cols-1]],
+ [nudge, -nudge]);
+ screw_hole(hole_radius, washer_radius,
+ back_right,
+ [nudge, nudge]);
+ }
+ }
+
+ // Add the screw hole near the cable hole
+ translate([washer_radius - tmp[0] - 0.5*hand_separation,
+ back_screw_hole_offset]) {
+ rotate_half() {
+ add_hand_separation() {
+ screw_hole(hole_radius, washer_radius, back_right, [nudge, nudge]);
+ }
+ }
+ }
}
-/* Create all the screw holes */
+// Create all the screw holes
module screw_holes(hole_radius) {
- right_screw_holes(hole_radius);
- mirror ([1,0,0]) { right_screw_holes(hole_radius); }
+ right_screw_holes(hole_radius);
+ mirror ([1,0,0]) { right_screw_holes(hole_radius); }
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/* Create switch holes or key holes for the right half of the
- keyboard. Different key_sizes are used in top_plate() and
- spacer(). */
+ keyboard. Different key_sizes are used in top_plate() and
+ spacer(). */
module right_half(switch_holes=true, key_size=key_hole_size) {
- x_offset = 0.5 * row_spacing;
- y_offset = 0.5 * column_spacing;
- thumb_key_offset = y_offset + 0.25 * column_spacing;
- rotate_half() {
- add_hand_separation() {
- // Add thumb keys
- for (j=[0:(2-1)]) {
- column([x_offset + (j)*row_spacing, y_offset], switch_holes,
- key_size, 2);
- }
- // Add thumb keys
- for (j=[0:(n_cols-1)]) {
- column([x_offset + (j+2)*row_spacing,
- y_offset + staggering_offsets[j]], switch_holes, key_size);
- }
- }
- }
+ x_offset = 0.5 * row_spacing;
+ y_offset = 0.5 * column_spacing;
+ thumb_key_offset = y_offset + 0.25 * column_spacing;
+ rotate_half() {
+ add_hand_separation() {
+ // Add thumb keys
+ for (j=[0:(2-1)]) {
+ column([x_offset + (j)*row_spacing, y_offset], switch_holes,
+ key_size, 2);
+ }
+ // Add thumb keys
+ for (j=[0:(n_cols-1)]) {
+ column([x_offset + (j+2)*row_spacing,
+ y_offset + staggering_offsets[j]], switch_holes, key_size);
+ }
+ }
+ }
}
-/* Mirror the right half to create the left half */
+// Mirror the right half to create the left half
module left_half(switch_holes=true, key_size=key_hole_size) {
- mirror ([1,0,0]) {
- right_half(switch_holes, key_size);
- }
+ mirror ([1,0,0]) {
+ right_half(switch_holes, key_size);
+ }
}
-/* Create the bottom layer of the case */
+// Create the bottom layer of the case
module bottom_plate() {
- difference() {
- hull() {
- screw_holes(washer_radius);
- }
- screw_holes(screw_hole_radius);
- }
+ difference() {
+ hull() {
+ screw_holes(washer_radius);
+ }
+ screw_holes(screw_hole_radius);
+ }
}
-/* Create the top layer of the case */
+// Create the top layer of the case
module top_plate() {
- difference() {
- bottom_plate();
- right_half(false);
- left_half(false);
- oled_holes(screw_hole_radius);
- pointer_holes(screw_hole_radius);
- }
+ difference() {
+ bottom_plate();
+ right_half(false);
+ left_half(false);
+ oled_holes(screw_hole_radius);
+ }
}
-/* Create the switch plate */
+// Create the switch plate
module switch_plate() {
- difference() {
- bottom_plate();
- right_half();
- left_half();
- oled_passthrough();
- pointer_passthrough();
- /* prominis(); */
- }
+ difference() {
+ bottom_plate();
+ right_half();
+ left_half();
+ oled_passthrough();
+ }
}
-/* Create a spacer layer */
+// Create a spacer layer
module spacer() {
- difference() {
- union() {
- difference() {
- bottom_plate();
- hull() {
- right_half(switch_holes=false, key_size=switch_hole_size + 3);
- left_half(switch_holes=false, key_size=switch_hole_size + 3);
- }
- /* Add the USB cable hole */
- translate([-0.5*cable_hole_width+100, 2*column_spacing]) {
- square([cable_hole_width, (2*n_rows) * column_spacing]);
- }
- }
- screw_holes(washer_radius);
- }
- screw_holes(screw_hole_radius);
- }
+ difference() {
+ union() {
+ difference() {
+ bottom_plate();
+ hull() {
+ right_half(switch_holes=false, key_size=switch_hole_size + 3);
+ left_half(switch_holes=false, key_size=switch_hole_size + 3);
+ }
+ // Add the USB cable hole
+ translate([-0.5*cable_hole_width+100, 2*column_spacing]) {
+ square([cable_hole_width, (2*n_rows) * column_spacing]);
+ }
+ }
+ screw_holes(washer_radius);
+ }
+ screw_holes(screw_hole_radius);
+ }
}
-/* Display all four layers */
+module cover() {
+ square([10,10]);
+}
+
+// Display all five layers
top_plate();
translate([350, 0]) {
- switch_plate();
+ switch_plate();
}
translate([0, 175]) {
- bottom_plate();
+ bottom_plate();
}
translate([350, 175]) {
- spacer();
+ spacer();
}
+/* translate([550, 0]) { */
+/* cover(); */
+/* } */
+
///////////////////////////////////////////////////////////////////////////////