mirror of
https://github.com/mon/PocketVoltex.git
synced 2026-09-22 22:57:58 +03:00
Update art and case
art to fit within 1mm boundary case to be pretty
This commit is contained in:
@@ -20,3 +20,5 @@ Hardware/Case/case.scad.*
|
||||
Costs.xlsx
|
||||
Hardware/Case/outputs/
|
||||
Old/
|
||||
Hardware/datasheets/
|
||||
Hardware/Case/Laser Templates/
|
||||
|
||||
@@ -37,6 +37,18 @@ For tracks:
|
||||
Cap: round
|
||||
Path->Combine
|
||||
Path->Stroke to path
|
||||
|
||||
For artwork:
|
||||
Cross reference with altium to make layers for tracks
|
||||
1.5mm
|
||||
1.2mm
|
||||
1mm
|
||||
0.75mm
|
||||
0.5mm
|
||||
0.254mm
|
||||
Raster Fill
|
||||
Path->Combine each individual letter (todo: actually needed?)
|
||||
Also do long lines in 0.75mm layer
|
||||
|
||||
You may need to Path->Union everything for artwork layers to render nicely
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
SET scad="C:\Program Files\OpenSCAD\openscad.exe"
|
||||
SET folder=outputs
|
||||
|
||||
for %%i in (art_trimmed,bottom_plate,bottom_ring,top_plate,top_ring) DO (
|
||||
for %%i in (bottom_plate,bottom_ring,top_plate,top_ring,holes_internal,holes_surface) DO (
|
||||
%scad% -o "%folder%\%%i.dxf" "%%i.scad"
|
||||
)
|
||||
+66
-15
@@ -1,12 +1,17 @@
|
||||
use <imports/cherry_mx.scad>
|
||||
include <imports/mx_keycap.scad>
|
||||
key_profile_index = 11;
|
||||
|
||||
$fn = 64;
|
||||
|
||||
switches = [[0,0],
|
||||
[-42.862,-37.592],
|
||||
[ 42.862,-37.592],
|
||||
[-14.287,-37.592],
|
||||
[ 14.287,-37.592],
|
||||
[-28.5,-75.692],
|
||||
[ 28.5,-75.692]];
|
||||
// x, y, keycap width in units, isBlack
|
||||
switches = [[0,0, 1],
|
||||
[-42.862,-37.592, 1.25],
|
||||
[ 42.862,-37.592, 1.25],
|
||||
[-14.287,-37.592, 1.25],
|
||||
[ 14.287,-37.592, 1.25],
|
||||
[-28.5,-75.692, 1.75, 1],
|
||||
[ 28.5,-75.692, 1.75, 1]];
|
||||
bolts = [[30.025, 6.65],
|
||||
[71, -16.925],
|
||||
[71, 16.5],
|
||||
@@ -21,8 +26,8 @@ encoderRadius = 13;
|
||||
encoderHoles = [[71.6, 0.4, 3.4],
|
||||
[69, -10.1, 1.6]];
|
||||
|
||||
switchHole = [0,-75.692];
|
||||
switchDiam = 3;
|
||||
macroHole = [0,-75.692];
|
||||
macroDiam = 3;
|
||||
|
||||
usbWidth = 9;
|
||||
usbPos = [-21.311, 10.3];
|
||||
@@ -87,6 +92,22 @@ module switches() {
|
||||
}
|
||||
}
|
||||
|
||||
module switch_models() {
|
||||
for(sw = switches) {
|
||||
translate([sw[0], sw[1]])
|
||||
cherry_mx_model();
|
||||
}
|
||||
}
|
||||
|
||||
module switch_keycaps() {
|
||||
for(sw = switches) {
|
||||
color(sw[3] ? [0.1,0.1,0.1] : [1,1,1])
|
||||
translate([sw[0], sw[1], 11.5])
|
||||
scale([sw[2],1,1])
|
||||
key();
|
||||
}
|
||||
}
|
||||
|
||||
module bolt_spacers() {
|
||||
for(bolt = bolts) {
|
||||
translate([bolt[0], bolt[1]])
|
||||
@@ -135,6 +156,22 @@ module encoderHoles_half() {
|
||||
}
|
||||
}
|
||||
|
||||
module encoder_model() {
|
||||
translate([0,0,5.5])
|
||||
rotate([90,0,0])
|
||||
import("imports/PEC16.stl");
|
||||
|
||||
translate([0,0,13])
|
||||
cylinder(20, d = 25);
|
||||
}
|
||||
|
||||
module encoder_model_full() {
|
||||
for(enc = encoders) {
|
||||
translate([enc[0], enc[1]])
|
||||
encoder_model();
|
||||
}
|
||||
}
|
||||
|
||||
// don't do the same thing twice
|
||||
module usb_half() {
|
||||
w = usbWidth / 2;
|
||||
@@ -161,7 +198,7 @@ module usb() {
|
||||
}
|
||||
|
||||
module board() {
|
||||
import("BOARD_SHAPE.dxf");
|
||||
import("imports/BOARD_SHAPE.dxf");
|
||||
}
|
||||
|
||||
module board_encoderhole() {
|
||||
@@ -180,8 +217,8 @@ module top_plate() {
|
||||
}
|
||||
switches();
|
||||
bolts();
|
||||
translate([switchHole[0], switchHole[1], 0])
|
||||
circle(d = switchDiam, center = true);
|
||||
translate([macroHole[0], macroHole[1], 0])
|
||||
circle(d = macroDiam, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +232,7 @@ module top_ring() {
|
||||
// Room for FX/START
|
||||
switches();
|
||||
};
|
||||
import("RING_TOP_SUPPORTS.dxf");
|
||||
import("imports/RING_TOP_SUPPORTS.dxf");
|
||||
bolts_expansion();
|
||||
}
|
||||
bolt_spacers();
|
||||
@@ -210,7 +247,7 @@ module pcb() {
|
||||
}
|
||||
|
||||
module artwork() {
|
||||
import("Artwork.dxf");
|
||||
import("imports/Artwork.dxf");
|
||||
}
|
||||
|
||||
module bottom_ring() {
|
||||
@@ -221,7 +258,7 @@ module bottom_ring() {
|
||||
offset(delta = -wallStrength)
|
||||
board();
|
||||
};
|
||||
import("RING_BOT_SUPPORTS.dxf");
|
||||
import("imports/RING_BOT_SUPPORTS.dxf");
|
||||
bolts_expansion();
|
||||
}
|
||||
bolt_spacers();
|
||||
@@ -264,7 +301,21 @@ module full_stack() {
|
||||
color([1,1,1, 1])
|
||||
linear_extrude(plate_thickness[2])
|
||||
pcb();
|
||||
// not-as-pretty model of macro key
|
||||
translate([macroHole[0], macroHole[1], plate_thickness[2]])
|
||||
color([1,0.5,0])
|
||||
cylinder(h = 5.2, d = macroDiam);
|
||||
|
||||
translate([0, 0, plate_thickness[2] + boom]) {
|
||||
// pretty models of stuff
|
||||
translate([0, 0, boom*2]) {
|
||||
color([0.8,0.8,0.8,1])
|
||||
encoder_model_full();
|
||||
|
||||
switch_models();
|
||||
switch_keycaps();
|
||||
};
|
||||
|
||||
color([1, 1, 1, 0.4])
|
||||
linear_extrude(plate_thickness[3])
|
||||
top_ring();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
use <case.scad>;
|
||||
|
||||
bolt_spacers();
|
||||
@@ -1,3 +1,3 @@
|
||||
use <case.scad>;
|
||||
|
||||
art_trimmed();
|
||||
bolts();
|
||||
Binary file not shown.
@@ -0,0 +1,123 @@
|
||||
$fn=60;
|
||||
/**
|
||||
a cherry mx switch.
|
||||
|
||||
most of the measurements done with a caliper. some taken from
|
||||
http://geekhack.org/index.php?topic=47744.0
|
||||
|
||||
This is just to illustrate and to drop in a a gross reference. It is mostly artistic apart from the steam and mounting plate dimensions
|
||||
*/
|
||||
|
||||
module cherry_mx_model() {
|
||||
|
||||
translate([0,0,14.85])
|
||||
{
|
||||
|
||||
//1. steam
|
||||
color("brown"){
|
||||
//1.1. l-r tab is 1.35mm
|
||||
translate([0,0,-3.62/2])
|
||||
cube([1.35,4.5,3.62], center=true);
|
||||
//1.2. f-b tab is 1.15mm. it has a smal notch that i will ignore.
|
||||
translate([0,0,-3.62/2])
|
||||
cube([4.5,1.15,3.62], center=true);
|
||||
//1.3. base. it has a chamfered top that i will ignore.
|
||||
translate([0,0,-5.62])
|
||||
cube([7.2,5.56,4], center=true);
|
||||
}
|
||||
// 2. top
|
||||
color("grey"){
|
||||
difference(){
|
||||
// make a trapezoid with the general shape (volume?) of the top
|
||||
hull(){
|
||||
translate([0,0,-4]) //distance from top of switch... some i measured 3.9 others 4.2... so leaving at 4
|
||||
cube([9.87,10.62,0.1], center=true);
|
||||
translate([0,0,-4 -5.2]) // bottom has a measured 5.3... so move 5.2 and use the 0.1 bellow
|
||||
cube([14.58,14.58,0.1], center=true);
|
||||
}
|
||||
|
||||
// and subtract:
|
||||
// the front led. NOTE: totally off... measured by eye. just for astetics
|
||||
// adding just so there is a visual cue of the direction
|
||||
translate([0,-4.7,-6])
|
||||
cylinder(r=3/2, h=6, center=true);
|
||||
translate([0,-5.5,-6])
|
||||
cube([8,4,5], center=true);
|
||||
// the four corners
|
||||
// TODO waste of time? this is all for looks, you shouldn't invade any of that space anyway...
|
||||
}
|
||||
}
|
||||
|
||||
// 3. bottom
|
||||
color("green")
|
||||
// 3.1 main body volume
|
||||
hull(){
|
||||
translate([0,0,-4 -5.3]) //steam + top
|
||||
cube([13.98,13.98,0.1], center=true);
|
||||
translate([0,0,-4 -5.3 -2.2]) //steam + top + straigth part
|
||||
cube([13.98,13.98,0.1], center=true);
|
||||
translate([0,0,-4 -5.3 -5.5]) //steam + top + bottom (measured 5.5)
|
||||
cube([12.74,13.6,0.1], center=true);
|
||||
}
|
||||
// 3.2 tabs
|
||||
// note: only measured the lenght, if they are slightly off-center, this will be all wrong :)
|
||||
color("black")
|
||||
difference(){
|
||||
translate([0,0,-4 -5.3 -0.82/2]) //steam + top
|
||||
cube([15.64,15.64,0.82], center=true);
|
||||
translate([0,0,-4 -5.3 -0.82/2 ]) // front-back cut
|
||||
cube([5.64,20,0.82 +2], center=true);
|
||||
translate([0,0,-4 -5.3 -0.82/2 ]) //side cut
|
||||
cube([20,11.64,0.82 +2], center=true);
|
||||
}
|
||||
|
||||
// 3.3 tab (plate snap on). to use this mechanically, you have to take into account the bending (as it will move the bottom part slightly up...) just for gross reference here for now
|
||||
color("white"){
|
||||
// 3.3.1 top
|
||||
translate([0,0,-4 -5.3 -0.82/2 ]) // front-back cut
|
||||
cube([1.82,16.33,0.82], center=true);
|
||||
// 3.3.2 bottom
|
||||
difference(){
|
||||
hull(){
|
||||
translate([0,0,-4 -5.3 -0.82/2 -1.76 ]) // front-back cut
|
||||
cube([3.65,14,0.1], center=true);
|
||||
translate([0,0,-4 -5.3 -0.82/2 -2.2 ]) // front-back cut
|
||||
cube([3.65,14.74,0.1], center=true);
|
||||
translate([0,0,-4 -5.3 -0.82/2 -2.89 ]) // front-back cut
|
||||
cube([3.65,14,0.1], center=true);
|
||||
}
|
||||
translate([0,0,-4 -5.3 -0.82/2 -1.76 ]) // front-back cut
|
||||
cube([2.2,20,4], center=true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 4. bottom guides
|
||||
// again, i'm assuming everything is centered...
|
||||
color("darkGreen"){
|
||||
// 4.1 cylinder
|
||||
translate([0,0,-4 -5.3 -5.5 -2/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r=3.85/2, h=2, center=true);
|
||||
translate([0,0,-4 -5.3 -5.5 -2 -1/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r2=3.85/2, r=2.8/2, h=1, center=true);
|
||||
// 4.2 PCB pins
|
||||
translate([4.95,0,-4 -5.3 -5.5 -2/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r=1.6/2, h=2, center=true);
|
||||
translate([4.95,0,-4 -5.3 -5.5 -2 -1/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r2=1.6/2, r=1/2, h=1, center=true);
|
||||
translate([-4.95,0,-4 -5.3 -5.5 -2/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r=1.6/2, h=2, center=true);
|
||||
translate([-4.95,0,-4 -5.3 -5.5 -2 -1/2]) //steam + top + bottom (measured 5.5)
|
||||
cylinder(r2=1.6/2, r=1/2, h=1, center=true);
|
||||
}
|
||||
|
||||
// 5. pins
|
||||
color("orange"){
|
||||
translate([-3.77,2.7,-4 -5.3 -5.5 -3.1/2]) //steam + top + bottom (measured 5.5)
|
||||
cube([.86, 0.2,3.1], center=true);
|
||||
translate([2.7,5.2,-4 -5.3 -5.5 -3.1/2]) //steam + top + bottom (measured 5.5)
|
||||
cube([.86, 0.2,3.1], center=true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,670 @@
|
||||
/* [Key] */
|
||||
|
||||
//length in units of key
|
||||
key_length = 1;
|
||||
//height in units of key. should remain 1 for most uses
|
||||
key_height = 1;
|
||||
//keycap type, [0:DCS Row 5, 1:DCS Row 1, 2:DCS Row 2, 3:DCS Row 3, 4:DCS Row 4, 5:DSA Row 3, 6:SA Row 1, 7:SA Row 2, 8:SA Row 3, 9:SA Row 4, 10:DCS Row 4 Spacebar, 11: g20 key (faked)]
|
||||
key_profile_index = 0;
|
||||
|
||||
// keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key
|
||||
keytop_thickness = 1;
|
||||
|
||||
// wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls
|
||||
wall_thickness = 3;
|
||||
|
||||
/* [Brim] */
|
||||
//enable brim for connector
|
||||
has_brim = 0;
|
||||
//brim radius. 11 ensconces normal keycap stem in normal keycap
|
||||
brim_radius = 11;
|
||||
//brim depth
|
||||
brim_depth = .3;
|
||||
|
||||
/* [Stabilizers] */
|
||||
//whether stabilizer connectors are enabled
|
||||
stabilizers = 0;
|
||||
//stabilizer distance in mm
|
||||
stabilizer_distance = 50;
|
||||
|
||||
/* [Dish] */
|
||||
// invert dishing. mostly for spacebar
|
||||
inverted_dish = 0;
|
||||
|
||||
/* [Stem] */
|
||||
// cherry MX or Alps stem, or totally broken circular cherry stem [0..2]
|
||||
stem_profile = 0;
|
||||
// how inset the stem is from the bottom of the key. experimental. requires support
|
||||
stem_inset = 0;
|
||||
// stem offset in units NOT MM. for stepped caps lock
|
||||
stem_offset = 0;
|
||||
|
||||
/* [Hidden] */
|
||||
//change to round things better
|
||||
$fn = 32;
|
||||
//beginning to use unit instead of baked in 19.05
|
||||
unit = 19.05;
|
||||
|
||||
//minkowski radius. radius of sphere used in minkowski sum for minkowski_key function. 1.75 default for faux G20
|
||||
minkowski_radius = 1.75;
|
||||
|
||||
//profile specific stuff
|
||||
|
||||
/*
|
||||
Here we have, for lack of a better implementation, an array
|
||||
that defines the more intimate aspects of a key.
|
||||
order is thus:
|
||||
1. Bottom Key Width: width of the immediate bottom of the key
|
||||
2. Bottom Key Height: height of the immediate bottom of the key
|
||||
3. Top Key Width Difference: mm to subtract from bottom key width to create top key width
|
||||
4. Top Key Height Difference: mm to subtract from bottom key height to create top key height
|
||||
5. total Depth: how tall the total in the switch is before dishing
|
||||
6. Top Tilt: X rotation of the top. Top and dish obj are rotated
|
||||
7. Top Skew: Y skew of the top of the key relative to the bottom. DCS has some, DSA has none (its centered)
|
||||
8. Dish Type: type of dishing. check out dish function for the options
|
||||
9. Dish Depth: how many mm to cut into the key with
|
||||
10. Dish Radius: radius of dish obj, the Sphere or Cylinder that cuts into the keycap
|
||||
*/
|
||||
|
||||
key_profiles = [
|
||||
|
||||
//DCS Profile
|
||||
|
||||
[ //DCS ROW 5
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
11.5, // total Depth
|
||||
-6, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //DCS ROW 1
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
8.5, // total Depth
|
||||
-1, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //DCS ROW 2
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6.2, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
7.5, // total Depth
|
||||
3, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //DCS ROW 3
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
6.2, // total Depth
|
||||
7, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //DCS ROW 4
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
6.2, // total Depth
|
||||
16, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
|
||||
//DSA Profile
|
||||
|
||||
[ //DSA ROW 3
|
||||
18.4, // Bottom Key Width
|
||||
18.4, // Bottom Key Height
|
||||
5.7, // Top Key Width Difference
|
||||
5.7, // Top Key Height Difference
|
||||
7.4, // total Depth
|
||||
0, // Top Tilt
|
||||
0, // Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
1, // Dish Type
|
||||
1.2, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
|
||||
//SA Proile
|
||||
|
||||
[ //SA ROW 1
|
||||
18.4, // Bottom Key Width
|
||||
18.4, // Bottom Key Height
|
||||
5.7, // Top Key Width Difference
|
||||
5.7, // Top Key Height Difference
|
||||
13.73, // total Depth, fudged
|
||||
-14, // Top Tilt
|
||||
0, // Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
1, // Dish Type
|
||||
1.2, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //SA ROW 2
|
||||
18.4, // Bottom Key Width
|
||||
18.4, // Bottom Key Height
|
||||
5.7, // Top Key Width Difference
|
||||
5.7, // Top Key Height Difference
|
||||
11.73, // total Depth
|
||||
-7, // Top Tilt
|
||||
0, // Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
1, // Dish Type
|
||||
1.2, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //SA ROW 3
|
||||
18.4, // Bottom Key Width
|
||||
18.4, // Bottom Key Height
|
||||
5.7, // Top Key Width Difference
|
||||
5.7, // Top Key Height Difference
|
||||
11.73, // total Depth
|
||||
0, // Top Tilt
|
||||
0, // Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
1, // Dish Type
|
||||
1.2, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //SA ROW 4
|
||||
18.4, // Bottom Key Width
|
||||
18.4, // Bottom Key Height
|
||||
5.7, // Top Key Width Difference
|
||||
5.7, // Top Key Height Difference
|
||||
11.73, // total Depth
|
||||
7, // Top Tilt
|
||||
0, // Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
1, // Dish Type
|
||||
1.2, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //DCS ROW 4 SPACEBAR
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
6, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
6.2, // total Depth
|
||||
16, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
2, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //G20 AKA DCS Row 2 with no dish and shorter
|
||||
18.16, // Bottom Key Width
|
||||
18.16, // Bottom Key Height
|
||||
2, // Top Key Width Difference
|
||||
2, // Top Key Height Difference
|
||||
6, // total Depth
|
||||
2.5, // Top Tilt
|
||||
0.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
3, // Dish Type
|
||||
0, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
[ //NONWORKING fake ISO enter
|
||||
18.16 * 1.5, // Bottom Key Width
|
||||
18.16 * 2, // Bottom Key Height
|
||||
4, // Top Key Width Difference
|
||||
4, // Top Key Height Difference
|
||||
7, // total Depth
|
||||
0, // Top Tilt
|
||||
1.75,// Top Skew
|
||||
|
||||
//Dish Profile
|
||||
|
||||
0, // Dish Type
|
||||
1, // Dish Depth
|
||||
0, // Dish Skew X
|
||||
0 // DIsh Skew Y
|
||||
],
|
||||
];
|
||||
|
||||
// derived variables
|
||||
//key profile selected
|
||||
key_profile = key_profiles[key_profile_index];
|
||||
|
||||
// names, so I don't go crazy
|
||||
bottom_key_width = key_profile[0];
|
||||
bottom_key_height = key_profile[1];
|
||||
width_difference = key_profile[2];
|
||||
height_difference = key_profile[3];
|
||||
total_depth = key_profile[4];
|
||||
top_tilt = key_profile[5] / key_height;
|
||||
top_skew = key_profile[6];
|
||||
dish_type = key_profile[7];
|
||||
dish_depth = key_profile[8];
|
||||
dish_skew_x = key_profile[9];
|
||||
dish_skew_y = key_profile[10];
|
||||
|
||||
// actual mm key width and height
|
||||
total_key_width = bottom_key_width + (unit * (key_length - 1));
|
||||
total_key_height = bottom_key_height + (unit * (key_height - 1));
|
||||
|
||||
// actual mm key width and height at the top
|
||||
top_total_key_width = bottom_key_width + (unit * (key_length - 1)) - width_difference;
|
||||
top_total_key_height = bottom_key_height + (unit * (key_height - 1)) - height_difference;
|
||||
|
||||
//centered
|
||||
module roundedRect(size, radius) {
|
||||
x = size[0];
|
||||
y = size[1];
|
||||
z = size[2];
|
||||
|
||||
translate([-x/2,-y/2,0])
|
||||
linear_extrude(height=z)
|
||||
hull() {
|
||||
translate([radius, radius, 0])
|
||||
circle(r=radius);
|
||||
|
||||
translate([x - radius, radius, 0])
|
||||
circle(r=radius);
|
||||
|
||||
translate([x - radius, y - radius, 0])
|
||||
circle(r=radius);
|
||||
|
||||
translate([radius, y - radius, 0])
|
||||
circle(r=radius);
|
||||
}
|
||||
}
|
||||
|
||||
// stem related stuff
|
||||
|
||||
// bottom we can use to anchor the stem, just a big ol cube with the inside of
|
||||
// the keycap hollowed out
|
||||
module inside(){
|
||||
difference(){
|
||||
translate([0,0,50]) cube([100000,100000,100000],center=true);
|
||||
// NOTE: you're saying hey, if this is the inside why aren't we doing
|
||||
// wall_thickness, keytop_thickness? well first off congratulations for
|
||||
// figuring that out cuz it's a rat's nest in here. second off
|
||||
// due to how the minkowski_key function works that isn't working out right
|
||||
// now. it's a simple change if is_minkowski is implemented though
|
||||
shape(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
module cherry_stem(){
|
||||
// cross length
|
||||
cross_length = 4.4;
|
||||
//extra vertical cross length - the extra length of the up/down bar of the cross
|
||||
extra_vertical_cross_length = 1.1;
|
||||
//dimensions of connector
|
||||
// outer cross extra length in x
|
||||
extra_outer_cross_width = 2.10;
|
||||
// outer cross extra length in y
|
||||
extra_outer_cross_height = 1.0;
|
||||
// dimensions of cross
|
||||
// horizontal cross bar width
|
||||
horizontal_cross_width = 1.4;
|
||||
// vertical cross bar width
|
||||
vertical_cross_width = 1.3;
|
||||
// cross depth, stem height is 3.4mm
|
||||
cross_depth = 4;
|
||||
|
||||
difference(){
|
||||
union(){
|
||||
if (stem_profile != 2){
|
||||
translate([
|
||||
-(cross_length+extra_outer_cross_width)/2,
|
||||
-(cross_length+extra_outer_cross_height)/2,
|
||||
stem_inset
|
||||
])
|
||||
cube([ // the base of the stem, the part the cruciform digs into
|
||||
cross_length+extra_outer_cross_width,
|
||||
cross_length+extra_outer_cross_height,
|
||||
50
|
||||
]);
|
||||
} else {
|
||||
cylinder(
|
||||
d = cross_length+extra_outer_cross_height,
|
||||
h = 50
|
||||
);
|
||||
}
|
||||
if (has_brim == 1){ cylinder(r=brim_radius,h=brim_depth); }
|
||||
}
|
||||
//the cross part of the steam
|
||||
translate([0,0,(cross_depth)/2 + stem_inset]){
|
||||
cube([vertical_cross_width,cross_length+extra_vertical_cross_length,cross_depth], center=true );
|
||||
cube([cross_length,horizontal_cross_width,cross_depth], center=true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module alps_stem(){
|
||||
cross_depth = 40;
|
||||
width = 4.45;
|
||||
height = 2.25;
|
||||
|
||||
base_width = 12;
|
||||
base_height = 15;
|
||||
|
||||
translate([0,0,cross_depth/2 + stem_inset]){
|
||||
cube([width,height,cross_depth], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
//whole connector, alps or cherry, trimmed to fit
|
||||
module connector(has_brim){
|
||||
difference(){
|
||||
//TODO can I really not do an array index here?
|
||||
translate([-unit * stem_offset, 0, 0])
|
||||
union(){
|
||||
if(stem_profile == 0 || stem_profile == 2) cherry_stem();
|
||||
if(stem_profile == 1) alps_stem();
|
||||
}
|
||||
inside();
|
||||
}
|
||||
}
|
||||
|
||||
//stabilizer connectors
|
||||
module stabilizer_connectors(has_brim){
|
||||
translate([stabilizer_distance,0,0]) connector(has_brim);
|
||||
translate([-stabilizer_distance,0,0]) connector(has_brim);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//shape related stuff
|
||||
|
||||
|
||||
|
||||
|
||||
//general shape of key. used for inside and outside
|
||||
module shape(thickness_difference, depth_difference){
|
||||
if (inverted_dish == 1){
|
||||
difference(){
|
||||
union(){
|
||||
shape_hull(thickness_difference, depth_difference, 1);
|
||||
dish(depth_difference);
|
||||
}
|
||||
outside(thickness_difference);
|
||||
}
|
||||
} else{
|
||||
difference(){
|
||||
shape_hull(thickness_difference, depth_difference, 1);
|
||||
dish(depth_difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// conicalish clipping shape to trim things off the outside of the keycap
|
||||
// literally just a key with height of 2 to make sure nothing goes awry with dishing etc
|
||||
module outside(thickness_difference){
|
||||
difference(){
|
||||
cube([100000,100000,100000],center = true);
|
||||
shape_hull(thickness_difference, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
// super basic hull shape without dish
|
||||
// modifier multiplies the height and top differences of the shape,
|
||||
// which is only used for dishing to cut the dish off correctly
|
||||
// height_difference used for keytop thickness
|
||||
module shape_hull(thickness_difference, depth_difference, modifier){
|
||||
hull(){
|
||||
// bottom_key_width + (key_length -1) * unit is the correct length of the
|
||||
// key. only 1u of the key should be bottom_key_width long; all others
|
||||
// should be 1u
|
||||
roundedRect([total_key_width - thickness_difference, total_key_height - thickness_difference, .001],1.5);
|
||||
|
||||
//height_difference outside of modifier because that doesnt make sense
|
||||
translate([0,top_skew,total_depth * modifier - depth_difference])
|
||||
rotate([-top_tilt,0,0])
|
||||
roundedRect([total_key_width - thickness_difference - width_difference * modifier, total_key_height - thickness_difference - height_difference * modifier, .001],1.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//dish related stuff
|
||||
|
||||
|
||||
|
||||
//dish selector
|
||||
module dish(depth_difference){
|
||||
if(dish_type == 0){ // cylindrical dish
|
||||
cylindrical_dish(depth_difference);
|
||||
}
|
||||
else if (dish_type == 1) { // spherical dish
|
||||
spherical_dish(depth_difference);
|
||||
}
|
||||
else if (dish_type == 2){ // SIDEWAYS cylindrical dish - used for spacebar
|
||||
sideways_cylindrical_dish(depth_difference);
|
||||
}
|
||||
else if (dish_type == 3){
|
||||
// no dish
|
||||
}
|
||||
}
|
||||
|
||||
module cylindrical_dish(depth_difference){
|
||||
/* we do some funky math here
|
||||
* basically you want to have the dish "dig in" to the keycap x millimeters
|
||||
* in order to do that you have to solve a small (2d) system of equations
|
||||
* where the chord of the spherical cross section of the dish is
|
||||
* the width of the keycap.
|
||||
*/
|
||||
// the distance you have to move the dish up so it digs in dish_depth millimeters
|
||||
chord_length = (pow(top_total_key_width, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
//the radius of the dish
|
||||
rad = (pow(top_total_key_width, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
|
||||
if (inverted_dish == 1){
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([90-top_tilt,0,0])
|
||||
translate([0,-chord_length,0])
|
||||
cylinder(h=100,r=rad, $fn=1024, center=true);
|
||||
}
|
||||
else{
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([90-top_tilt,0,0])
|
||||
translate([0,chord_length,0])
|
||||
cylinder(h=100,r=rad, $fn=1024, center=true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module spherical_dish(depth_difference){
|
||||
//same thing as the cylindrical dish here, but we need the corners to just touch - so we have to find the hypotenuse of the top
|
||||
chord = pow((pow(top_total_key_width,2) + pow(top_total_key_height, 2)),0.5); //getting diagonal of the top
|
||||
|
||||
// the distance you have to move the dish up so it digs in dish_depth millimeters
|
||||
chord_length = (pow(chord, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
//the radius of the dish
|
||||
rad = (pow(chord, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
|
||||
if (inverted_dish == 1){
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([-top_tilt,0,0])
|
||||
translate([0,0,-chord_length])
|
||||
//NOTE: if your dish is long at all you might need to increase this number
|
||||
sphere(r=rad, $fn=512);
|
||||
}
|
||||
else{
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([-top_tilt,0,0])
|
||||
translate([0,0,chord_length])
|
||||
sphere(r=rad, $fn=256);
|
||||
}
|
||||
}
|
||||
|
||||
module sideways_cylindrical_dish(depth_difference){
|
||||
chord_length = (pow(top_total_key_height, 2) - 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
rad = (pow(top_total_key_height, 2) + 4 * pow(dish_depth, 2)) / (8 * dish_depth);
|
||||
|
||||
if (inverted_dish == 1){
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([90,top_tilt,90])
|
||||
translate([0,-chord_length,0])
|
||||
cylinder(h=total_key_width + 20,r=rad, $fn=1024, center=true); // +20 just cuz
|
||||
}
|
||||
else{
|
||||
translate([dish_skew_x, top_skew + dish_skew_y, total_depth - depth_difference])
|
||||
rotate([90,top_tilt,90])
|
||||
translate([0,chord_length,0])
|
||||
cylinder(h=total_key_width + 20,r=rad, $fn=1024, center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//actual full key with space carved out and keystem/stabilizer connectors
|
||||
module key(){
|
||||
union(){
|
||||
difference(){
|
||||
shape(0, 0);
|
||||
shape(wall_thickness, keytop_thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ACTUAL OUTPUT
|
||||
//difference(){
|
||||
// key();
|
||||
// preview cube, for seeing inside the keycap
|
||||
//cube([100,100,100]);
|
||||
//}
|
||||
|
||||
//minkowski_key();
|
||||
|
||||
|
||||
|
||||
|
||||
// Experimental stuff
|
||||
|
||||
|
||||
// key rounded with minkowski sum. still supports wall and keytop thickness.
|
||||
// use in actual output section. takes a long time to render with dishes.
|
||||
// required for keycap 11, G20 keycap.
|
||||
module minkowski_key(){
|
||||
union(){
|
||||
difference(){
|
||||
minkowski(){
|
||||
shape(minkowski_radius*2, minkowski_radius);
|
||||
difference(){
|
||||
sphere(r=minkowski_radius, $fn=24);
|
||||
translate([0,0,-minkowski_radius])
|
||||
cube([2*minkowski_radius,2*minkowski_radius,2*minkowski_radius], center=true);
|
||||
}
|
||||
}
|
||||
shape(wall_thickness, keytop_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
connector(has_brim);
|
||||
|
||||
if (stabilizers == 1){
|
||||
stabilizer_connectors(has_brim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOT 3D, NOT CENTERED
|
||||
// corollary is roundedRect
|
||||
module fakeISOEnter(thickness_difference){
|
||||
z = 0.001;
|
||||
radius = 2;
|
||||
/*TODO I figured it out. 18.16 is the actual keycap width / height,
|
||||
whereas 19.01 is the unit. ISO enter obeys that just like everything else,
|
||||
which means that it's height is 18.16 * 2 + (19.01 - 18.16) or, two
|
||||
keycap heights plus the space between them, also known as 18.16 +
|
||||
(19.01 * (key_height - 1)). this is followed by the width too. should fix
|
||||
to make this finally work*/
|
||||
unit = 18.16; // TODO probably not
|
||||
|
||||
// t is all modifications to the polygon array
|
||||
t = radius + thickness_difference/2;
|
||||
|
||||
pointArray = [
|
||||
[0 + t,0 + t],
|
||||
[unit*1.25 - t, 0 + t],
|
||||
[unit*1.25 - t, unit*2 - t],
|
||||
[unit*-.25 + t, unit*2 - t],
|
||||
[unit*-.25 + t, unit*1 + t],
|
||||
[0 + t, unit*1 + t]
|
||||
];
|
||||
|
||||
minkowski(){
|
||||
circle(r=radius, $fn=24);
|
||||
polygon(points=pointArray);
|
||||
}
|
||||
}
|
||||
|
||||
//corollary is shape_hull
|
||||
module ISOEnterShapeHull(thickness_difference, depth_difference, modifier){
|
||||
unit = 18.16; // TODO probably not
|
||||
height = 8 - depth_difference;
|
||||
length = 1.5 * unit; // TODO not used. need for dish
|
||||
|
||||
translate([-0.125 * unit, unit*.5]) linear_extrude(height=height*modifier, scale=[.8, .9]){
|
||||
translate([-unit*.5, -unit*1.5]) minkowski(){
|
||||
fakeISOEnter(thickness_difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user