///////////////////////////////////////////////////////////////////////////////
-// Atreides case file, OpenSCAD laser cut format
-// Copyright 2014-2020 Phil Hagelberg, 2021 Armaan Bhojwani, GPLv3
-// All distances are in mm
+// Atreides case file, OpenSCAD laser cut format //
+// Copyright 2014-2020 Phil Hagelberg, 2021 Armaan Bhojwani, GPLv3 //
+// All distances are in mm //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-// VARIABLES
+// VARIABLES //
///////////////////////////////////////////////////////////////////////////////
-/* set output quality */
-$fn = 100;
+/* Set output quality */
+$fn = 150;
/* 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. */
+/* 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. */
key_hole_size = 20;
-/* the angle between the halves is twice this number */
-angle = 15;
+/* The angle between the halves is twice this number */
+angle = 10;
-/* The radius of screw holes. Holes will be slightly bigger due
- to the cut width. */
+/* 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. */
+back_screw_hole_offset = 0;
+
+/* The radius of screw holes. Holes will be slightly bigger due to the cut
+ width. */
screw_hole_radius = 1.5;
-/* Each screw hole is a hole in a "washer". How big these "washers"
- should be depends on the material used: this parameter and the
- `switch_hole_size` determine the spacer wall thickness. */
+
+/* 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. */
washer_radius = 4 * screw_hole_radius;
-/* 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. */
-back_screw_hole_offset = 0;
+/* 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(). */
+switch_hole_size = 14;
/* Distance between halves. */
-hand_separation = 10;
+hand_separation = key_hole_size - switch_hole_size;
-/* 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(). */
-switch_hole_size = 14;
-
-/* Sets whether the case should use notched holes. As far as I can
- tell these notches are not all that useful... */
+/* 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
n_rows = 4;
n_cols = 5;
-/* Number of thumb keys (per hand), try 1 or 2. */
-n_thumb_keys = 1;
-
/* 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 */
-oled_width = 23;
-oled_height = 23;
+oled_width = 20;
+oled_height = 20;
/* Width and height between screw holes of pointer */
-pointer_width = 20;
-pointer_height = 20;
+pointer_width = 10.5;
+pointer_height = 10.5;
///////////////////////////////////////////////////////////////////////////////
-// META MODULES
+// META MODULES //
///////////////////////////////////////////////////////////////////////////////
module rz(angle, center=undef) {
}
}
-/* 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. */
-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]];
+/* 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. */
+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]];
+/* Cherry MX switch hole with the center at `position`. Sizes come from the
+ ErgoDox design. */
module switch_hole(position, notches=use_notched_holes) {
- /* Cherry MX switch hole with the center at `position`. Sizes come
- from the ErgoDox design. */
hole_size = 13.97;
notch_width = 3.5001;
notch_offset = 4.2545;
}
};
+/* Create a hole for a regular key */
module regular_key(position, size) {
- /* Create a hole for a regular key. */
translate(position) {
square([size, size], center=true);
}
}
-module column (bottom_position, switch_holes, key_size=key_hole_size) {
- /* 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:(n_rows-1)]) {
+ for (i = [0:(rows-1)]) {
if (switch_holes == true) {
switch_hole([0, i*column_spacing]);
} else {
}
}
+/* 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. */
module rotate_half() {
- /* 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. */
rotation_y_offset = 1.75 * column_spacing;
for (i=[0:$children-1]) {
rz(angle, [hand_separation, rotation_y_offset]) {
}
}
+/* Shift everything right to get desired hand separation */
module add_hand_separation() {
- /* Shift everything right to get desired hand separation. */
for (i=[0:$children-1]) {
- translate([0.5*hand_separation, /* we get back the full separation
- because of mirroring */
- 0]) children(i);
+ /* 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.
+ /* 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.
+ 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 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 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];
}
}
+/* Create screw holes for the oled screen */
module oled_holes(hole_radius) {
- translate([0,100]) {
+ translate([0,85]) {
translate([-oled_width/2,-oled_height/2]) {
translate([0, oled_height]) {
screw_hole(hole_radius, washer_radius);
}
screw_hole(hole_radius, washer_radius);
}
- translate([0, -8]) {
- square(oled_width-5, center=true);
- }
}
+ oled_passthrough();
}
+/* 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) {
- translate([0, 65]) {
- 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]) {
+ 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);
}
- screw_hole(hole_radius, washer_radius);
- }
- translate([0, -12]) {
- square(pointer_width-5, center=true);
}
}
+ pointer_passthrough();
}
-module passthrough() {
- translate([0, 75]) {
- square(15, center=true);
+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();
+ }
+ }
+}
+
module right_screw_holes(hole_radius) {
- /* coordinates of the back right screw hole before rotation... */
- back_right = [(n_cols+n_thumb_keys)*row_spacing,
+ /* 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 */
+
+ /* ...and after */
tmp = rz_fun(back_right, angle, [0, 2.25*column_spacing]);
nudge = 0.75;
[row_spacing, 0],
[-nudge, -nudge]);
screw_hole(hole_radius, washer_radius,
- [(n_cols+n_thumb_keys)*row_spacing, staggering_offsets[n_cols-1]],
+ [(n_cols+2)*row_spacing, staggering_offsets[n_cols-1]],
[nudge, -nudge]);
screw_hole(hole_radius, washer_radius,
back_right,
}
}
- /* add the screw hole near the cable hole */
+ /* 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]);
+ screw_hole(hole_radius, washer_radius, back_right, [nudge, nudge]);
}
}
}
}
+/* Create all the screw holes */
module screw_holes(hole_radius) {
- /* Create all the screw holes. */
right_screw_holes(hole_radius);
mirror ([1,0,0]) { right_screw_holes(hole_radius); }
}
///////////////////////////////////////////////////////////////////////////////
-// PLATE MODULES
+// PLATE MODULES //
///////////////////////////////////////////////////////////////////////////////
+/* Create switch holes or key holes for the right half of the
+ keyboard. Different key_sizes are used in top_plate() and
+ spacer(). */
module right_half(switch_holes=true, key_size=key_hole_size) {
- /* Create switch holes or key holes for the right half of the
- keyboard. Different key_sizes are used in top_plate() and
- spacer(). */
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() {
- for (j=[0:(n_thumb_keys-1)]) {
- switch_hole([x_offset + j*row_spacing, thumb_key_offset]);
- switch_hole([x_offset + j*row_spacing, thumb_key_offset+2*y_offset]);
+ // 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+n_thumb_keys)*row_spacing, y_offset + staggering_offsets[j]], switch_holes, key_size);
+ 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 */
module left_half(switch_holes=true, key_size=key_hole_size) {
mirror ([1,0,0]) {
right_half(switch_holes, key_size);
}
}
+/* Create the bottom layer of the case */
module bottom_plate() {
- /* bottom layer of the case */
difference() {
hull() {
screw_holes(washer_radius);
}
}
+/* Create the top layer of the case */
module top_plate() {
- /* top layer of the case */
difference() {
bottom_plate();
right_half(false);
}
}
+/* Create the switch plate */
module switch_plate() {
- /* the switch plate */
difference() {
bottom_plate();
right_half();
left_half();
- passthrough();
+ oled_passthrough();
+ pointer_passthrough();
+ /* prominis(); */
}
}
+/* Create a spacer layer */
module spacer() {
- /* Create a spacer. */
difference() {
union() {
difference() {
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, 2*column_spacing]) {
+ /* Add the USB cable hole */
+ translate([-0.5*cable_hole_width+100, 2*column_spacing]) {
square([cable_hole_width, (2*n_rows) * column_spacing]);
}
}
}
}
-/* Create all four layers. */
+/* Display all four layers */
top_plate();
-translate([300, 0]) {
+
+translate([350, 0]) {
switch_plate();
}
-translate([0, 150]) {
+
+translate([0, 175]) {
bottom_plate();
}
-translate([300, 150]) {
+
+translate([350, 175]) {
spacer();
}