-
Notifications
You must be signed in to change notification settings - Fork 6
/
stenoboard.scad
471 lines (423 loc) · 31.6 KB
/
stenoboard.scad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
/**
* Stenoboard is an open source stenographic keyboard.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2014 Emanuele Caruso. See LICENSE for details.
*/
// VALUES
hKeyDistance = 18.325;
vowelsKeyDistance = 15.5;
framePosition = [-17.75, -69.5, 0];
drawKeySupport = false;
drawKeySurfaceTopBevel = true;
drawKeySurfaceDifference = true;
keySurfaceDifferenceFn = 256;
scaleKeyTopBevel = 1.4;
boardCenter = [46,-41.25,0];
rightRReference = boardCenter + [-hKeyDistance * 1.5, -22, 0];
rightEReference = rightRReference + [-11.3, -27, 0];
screwFrameVerticalOffset = 8.7;
leftVowelsOffset = 11.3 * 2 + hKeyDistance * 3 - 14.5 - 0.65;
screw1 = [103.9, 2.5, 0];
screw2 = [-12.75, 2.5, 0];
screw3 = [-12.75, -62.5, 0];
screw4 = [103.9, -62.5, 0];
frameScrewPositions = [screw1, screw2, screw3, screw4];
frameScrewD = 3.2;
mainRightScrewPositions = [[-37.465,11.43,0], [40.64,13.97,0], [-34.29,-10.795,0], [34.925,-10.795,0]];
mainRightScrewBevels = [[false, false, true, false], [true, false, false, true], [false, true, true, true], [true, false, true, true]];
mainRightScrewH = 20.1;
mainRightScrewD = 3.0;
mainLeftScrewPositions = [[-16.51,12.065,0], [40.005,13.335,0], [-34.29,-10.795,0], [36.83,-11.43,0]];
mainLeftScrewBevels = [[true, true, true, true], [true, true, true, true], [true, true, true, true], [true, true, true, true]];
rightVowelsScrewPositions = [[-1.27,9.525,0], [16.51,9.525,0], [7.62,-9.525,0]];
rightVowelsScrewBevels = [[true, true, true, true], [true, true, true, true], [true, true, false, false]];
rightVowelsScrewH = mainRightScrewH - 9.3;
rightVowelsScrewD = 3.2;
arduinoScrewPositions = [[0, 0, 0], [50.8, -15.2, 0], [50.8, -15.2 - 27.9, 0], [-1.3, -15.2 -27.9 -5.1, 0]];
arduinoScrewOffset = [-17.5, 45, 0];
arduinoScrewH = 6;
arduinoScrewD = 3.15;
rightVowelsBasePosition = [-8.5, -107, 0];
rightVowelsBaseScrewD = 3.0;
dustCoverGap = 0.8;
%translate(boardCenter) cylinder(r=1,h=10,$fn=6);
%translate(rightRReference) cylinder(r=1,h=10,$fn=6);
%translate(rightEReference + [0, 0, 30]) cylinder(r=1,h=10,$fn=6);
%translate(frameScrewPositions[0]) cylinder(r=1,h=50,$fn=6);
%translate(frameScrewPositions[1]) cylinder(r=1,h=50,$fn=6);
%translate(frameScrewPositions[2]) cylinder(r=1,h=50,$fn=6);
%translate(frameScrewPositions[3]) cylinder(r=1,h=50,$fn=6);
// MODULE CALLS
//translate([-46, 35, 0]) consonantsKeyboard(keys = 6, numberKeyIndex = 3, rightWideKeyIndex = 0, leftWideKeyIndex = 5, drawTopRow = true, drawBottomRow = true, drawFrame = true);
//color("gray")
//translate([-46, 35, 0]) translate([0,0,2])
//translate([-46, 10, 0])
//barKeyboard();
//barButtonContact();
//rightBaseBridgeTest();
//translate([-45.73, 50, 0]) base();
//translate([0, 130, 0])
//translate([-45.73, 50, 0]) base(isRight = false);
//translate([0, 0, rightVowelsScrewH + screwFrameVerticalOffset + 0.2])
//translate([-14.5, 75, 0])
translate([-14.5, 24, 0]) vowelsKeyboard();
//translate([-45.73, 50, 0]) cover();
//rightAssembly(drawConsonants = true, drawNumbers = true);
// vowels plate
//translate([-14.5, 24, 0]) vowelsKeyboard();
//translate([40, 24, 0]) vowelsKeyboard();
//translate([-14.5, -24, 0]) vowelsKeyboard();
//translate([40, -24, 0]) vowelsKeyboard();
// numbers bar plate
//barKeyboard();
//translate([86, -55, 0]) rotate([0, 0, 180]) barKeyboard();
// printing module calls, delete these when finished
//translate([-34.5, 24, 0]) vowelsKeyboard();
//translate([14.5, 24, 0]) vowelsKeyboard();
// MODULES
module keyArm(armWidth = 4, armLength = 50, armHeight = 5, pivotDepth = 4) {
translate([0, -armLength / 2, armHeight / 2]) beveledCube([armWidth, armLength, armHeight], center = true, bevelY = [true, false]);
}
module beveledCube(cubeEdges, center = false, bevelR = 2, bevelSegments = 10, bevelX = [true, true], bevelY = [true, true]) {
difference() {
cube(cubeEdges, center = center);
translate([center ? 0 : cubeEdges[0] / 2, center ? 0 : cubeEdges[1] / 2, 0])
for (i = [0 : 1]) for (j = [0 : 1]) if(bevelX[i] && bevelY[j]) {
mirror([i, 0, 0]) mirror([0, j, 0]) translate(center ? [-cubeEdges[0] / 2, -cubeEdges[1] / 2, 0] : [-cubeEdges[0] / 2, -cubeEdges[1] / 2, cubeEdges[2] / 2]) bevel(r = bevelR, length = cubeEdges[2] + 0.01, segments = bevelSegments);
}
}
}
module advancedBeveledCube(cubeEdges, center = false, bevelR = 2, bevelSegments = 10, bevelX = [true, true], bevelY = [true, true], topBevels = [true, true, true, true], topBevelR = 0.8, topBevelSegments = 4, scaleTopBevel = 1) {
difference() {
beveledCube(cubeEdges = cubeEdges, center = center, bevelR = bevelR, bevelSegments = bevelSegments, bevelX = bevelX, bevelY = bevelY);
// Top bevels
if(topBevels[2]) translate([center ? -cubeEdges[0] / 2 : 0, 0, cubeEdges[2] / (center ? 2 : 1)]) rotate([-90, 0, 0]) scale([1, scaleTopBevel, 1]) bevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[0]) translate([center ? cubeEdges[0] / 2 : cubeEdges[0], 0, cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, 180]) rotate([-90, 0, 0]) scale([1, scaleTopBevel, 1]) bevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[3]) translate([0, (center ? -cubeEdges[1] / 2 : 0), cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 90, 0]) scale([scaleTopBevel, 1, 1]) bevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[1]) translate([0, (center ? cubeEdges[1] / 2 : cubeEdges[1]), cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, 180]) rotate([0, 90, 0]) scale([scaleTopBevel, 1, 1]) bevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
// Top corner bevels
if(topBevels[0] && topBevels[1]) for(i = [0 : bevelSegments - 1]) translate([cubeEdges[0] / (center ? 2 : 1) - bevelR, cubeEdges[1] / (center ? 2 : 1) - bevelR, cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, (90 / bevelSegments / 2) + i * (90 / bevelSegments)]) translate([bevelR, bevelR, 0]) scale([1, 1, scaleTopBevel]) cornerBevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[1] && topBevels[2]) translate([(!center ? cubeEdges[0] / 2 : 0), (!center ? cubeEdges[1] / 2 : 0), 0]) mirror([1, 0, 0]) for(i = [0 : bevelSegments - 1]) translate([cubeEdges[0] / 2 - bevelR, cubeEdges[1] / 2 - bevelR, cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, (90 / bevelSegments / 2) + i * (90 / bevelSegments)]) translate([bevelR, bevelR, 0]) scale([1, 1, scaleTopBevel]) cornerBevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[2] && topBevels[3]) translate([(!center ? cubeEdges[0] / 2 : 0), (!center ? cubeEdges[1] / 2 : 0), 0]) mirror([1, 0, 0]) mirror([0, 1, 0]) for(i = [0 : bevelSegments - 1]) translate([cubeEdges[0] / 2 - bevelR, cubeEdges[1] / 2 - bevelR, cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, (90 / bevelSegments / 2) + i * (90 / bevelSegments)]) translate([bevelR, bevelR, 0]) scale([1, 1, scaleTopBevel]) cornerBevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
if(topBevels[0] && topBevels[3]) translate([(!center ? cubeEdges[0] / 2 : 0), (!center ? cubeEdges[1] / 2 : 0), 0]) mirror([0, 1, 0]) for(i = [0 : bevelSegments - 1]) translate([cubeEdges[0] / 2 - bevelR, cubeEdges[1] / 2 - bevelR, cubeEdges[2] / (center ? 2 : 1)]) rotate([0, 0, (90 / bevelSegments / 2) + i * (90 / bevelSegments)]) translate([bevelR, bevelR, 0]) scale([1, 1, scaleTopBevel]) cornerBevel(r = topBevelR, length = (cubeEdges[0] + cubeEdges[1]) * 3, segments = topBevelSegments, minThickness = 0);
}
}
module cornerBevel(r = 2, length = 100, segments = 10, minThickness = 0) {
#rotate([0, 0, 180]) rotate([-90, 0, 0]) bevel(r = r, length = length, segments = segments, minThickness = minThickness);
}
module bevel(r = 2, length = 100, segments = 10, minThickness = 0) {
difference() {
cube([(r + minThickness) * 2, (r + minThickness) * 2, length], center = true);
translate([r, r, 0]) cylinder(r = r, h = length * 2, center = true, $fn = segments * 4);
for (i = [0, 1]) rotate([0, 0, i * -90]) translate([-0, -r * 2 - 0.001, 0]) cube([r * 4, r * 4, length*2], center = true);
}
}
module topRowKeySurface(keyW = 13, keyD = 25, keyH = 1.25, drawDifference = true, isRightWideKey = false, isLeftWideKey = false, drawDifference = true, isNearNumberSwitchKey = [false, false]) {
difference() {
translate([-keyW / 2 + (isLeftWideKey ? -2.4 : 0) + (isNearNumberSwitchKey[1] ? 1 : 0), -keyD / 2, 0]) advancedBeveledCube([keyW + (isLeftWideKey ? 2.4 : 0) + (isRightWideKey ? 2.4 : 0) - (isNearNumberSwitchKey[0] ? 1 : 0) - (isNearNumberSwitchKey[1] ? 1 : 0), keyD, keyH], topBevels = [drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false], scaleTopBevel = scaleKeyTopBevel);
if(drawKeySurfaceDifference && drawDifference) translate([0, 0, 29.5 + keyH]) rotate([90, 0, 0]) cylinder(r = 30, h = 50, center = true, $fn = keySurfaceDifferenceFn);
}
}
module bottomRowKeySurface(keyW = 13, keyD = 25, keyH = 1.25, isRightWideKey = false, isLeftWideKey = false, drawDifference = true) {
difference() {
//translate([-keyW / 2 + (isLeftWideKey ? -3.7 : 0), -keyD / 2, 0]) advancedBeveledCube([keyW + (isLeftWideKey ? 3.7 : 0) + (isRightWideKey ? 3.7 : 0), keyD, keyH]);
union() {
translate([-keyW / 2 + (isLeftWideKey ? -2.4 : 0), 0, 0]) advancedBeveledCube([keyW + (isLeftWideKey ? 2.4 : 0) + (isRightWideKey ? 2.4 : 0), keyD / 2, keyH], bevelY = [false, true], topBevels = [drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, false], scaleTopBevel = scaleKeyTopBevel);
translate([-keyW / 2 + (isLeftWideKey ? -2.4 : 0), -keyD / 2, 0]) advancedBeveledCube([keyW + (isLeftWideKey ? 2.4 : 0) + (isRightWideKey ? 2.4 : 0), keyD / 2 + 2, keyH], bevelY = [true, false], topBevels = [drawKeySurfaceTopBevel ? true : false, false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false], bevelR = keyW / 2, bevelSegments = 24, scaleTopBevel = scaleKeyTopBevel);
}
if(drawKeySurfaceDifference && drawDifference) {
translate([0, 25 - (keyD / 2 - keyW / 2), 29.5 + keyH]) rotate([90, 0, 0]) cylinder(r = 30, h = 50, center = true, $fn = keySurfaceDifferenceFn);
translate([0, -(keyD / 2 - keyW / 2), 29.49 + keyH]) rotate([90, 0, 0]) sphere(r = 30, $fn = keySurfaceDifferenceFn);
}
}
}
module numberBarSurface(keyW = 13, keyD = 25, keyH = 1.25, drawDifference = true, keys = 5, drawDifference = true) {
rotate([0, 0, 180]) difference() {
translate([-keyW / 2 - hKeyDistance * (keys - 1) - 1.2, -keyD / 2, 0]) advancedBeveledCube([keyW + hKeyDistance * (keys - 1) + 2.4, keyD, keyH], topBevels = [drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false, drawKeySurfaceTopBevel ? true : false], scaleTopBevel = scaleKeyTopBevel);
if(drawKeySurfaceDifference && drawDifference) {
for (i = [0 : keys - 1]) translate([-i * hKeyDistance, -(keyD / 2 - keyW / 2) +1, 29.53 + keyH]) rotate([90, 0, 0]) sphere(r = 30, $fn = keySurfaceDifferenceFn);
}
}
}
module topRowKeyAssembly(pivotLength = 16.5, pivotHeight = 5, pivotDepth = 3.25, coneR1 = 2.5, coneH = 3, tolerancePerSide = 0.25, armWidth = 12, armLength = 40, armHeight = 1.5, topKeyW = 15.2, topKeyD = 26, topKeyH = 2, keySupportH = 0, verticalKeySupportH = 0, backlash = 0.0, isRightWideKey = false, isLeftWideKey = false, isNearNumberSwitchKey = [false, false]) {
translate([0,1,0]) carvedArm(armL = armLength - 3, armW = armWidth, levelH = 0.4, firstLevelH = 0.6, levelTranslateIncrement = 2.5, levels = 2, drawFakeKey = false);
armHeight = 1 + 2 * 0.25;
translate([0, -armLength + topKeyD / 2 - 0.5, verticalKeySupportH + keySupportH]) topRowKeySurface(keyW = topKeyW, keyD = topKeyD, keyH = topKeyH, isRightWideKey = isRightWideKey, isLeftWideKey = isLeftWideKey, isNearNumberSwitchKey = isNearNumberSwitchKey);
echo("top row h:", verticalKeySupportH + keySupportH + topKeyH);
}
module bottomRowKeyAssembly(pivotLength = 16.5, pivotHeight = 5, pivotDepth = 3.25, coneR1 = 2.5, coneH = 3, tolerancePerSide = 0.25, armWidth = 12, topArmLength = 35, armLength = 20, keyW = 15.2, keyD = 21.75, keyH = 2, topKeyD = 25, keySupportH = 0, verticalKeySupportH = 0, armsGap = 1, bridgeGap = 2, isRightWideKey = false, isLeftWideKey = false) {
rotate([0, 0, 180]) translate([0, topArmLength + armLength + 0.5, 0]) carvedArm(armL = armLength, armW = armWidth, levelH = 0.8, firstLevelH = 0.4, levelTranslateIncrement = 3, levels = 2, drawFakeKey = false);
armHeight = 1;
translate([0, -0.25, 0]) difference() {
union() {
translate([0, 5 - topArmLength - keyD / 2 - 2.5 + 0.75, verticalKeySupportH + keySupportH]) bottomRowKeySurface(keyW = keyW, keyD = keyD, keyH = keyH, isRightWideKey = isRightWideKey, isLeftWideKey = isLeftWideKey);
}
if (!isRightWideKey) for (i = [0, -1]) mirror([i, 0, 0]) translate([-keyW / 2 + (isLeftWideKey && i == 0 ? - 3.7 : 0), 5 - topArmLength - keyD - 1.75, armHeight]) bevel(r = keyW / 2, segments = 24);
else for (i = [0, -1]) mirror([i, 0, 0]) translate([-keyW / 2 + (isRightWideKey && i == 0 ? 0 : -3.7), 5 - topArmLength - keyD - 1.75, armHeight]) bevel(r = keyW / 2, segments = 24);
}
echo("bottom row h:", verticalKeySupportH + keySupportH + keyH);
}
module numberBarAssembly(pivotLength = 16.5, pivotHeight = 5, pivotDepth = 3.25, coneR1 = 2.5, coneH = 3, tolerancePerSide = 0.25, armWidth = 3.5, armLength = 40, topKeyW = 13, keyD = 7.5, topKeyH = 2, keySupportH = 0, verticalKeySupportH = 0.4, backlash = 0.0, keys = 5, numberKeyIndex = 2) {
armHeight = 1 + 2 * 0.25;
translate([-0.1,0.01,0]) union() {
translate([-9.14 + numberKeyIndex * hKeyDistance, 0, 0]) carvedArm(armL = armLength, armW = 3.5, levelH = 1.6, firstLevelH = 0.4, levelTranslateIncrement = 2, levels = 2, drawFakeKey = false);
translate([9 + -hKeyDistance, 0, 0]) mirror([0, 0, 0]) union() {
translate([3.8, 0.5, 0]) carvedArm(armL = 10, armW = 2, levelH = 0.25, firstLevelH = 0.4, levelTranslateIncrement = 9.99, levels = 2, drawFakeKey = false, bevel = false);
}
translate([9 + hKeyDistance * (keys - 1), 0, 0]) mirror([-1, 0, 0]) union() {
translate([3.5, 0.5, 0]) carvedArm(armL = 10, armW = 2, levelH = 0.25, firstLevelH = 0.4, levelTranslateIncrement = 9.99, levels = 2, drawFakeKey = false, bevel = false);
}
for (i = [0 : -1]) for (j = [0 : keys - 2]) translate([9 + j * hKeyDistance, 0, 0]) mirror([i, 0, 0]) union() {
if(j != numberKeyIndex - 1) translate([0, 0.25, 0]) carvedArm(armL = 8, armW = armWidth, levelH = 0.8, firstLevelH = 0.4, levelTranslateIncrement = 2, levels = 2, drawFakeKey = false, bevel = false);
}
translate([10.75 + dustCoverGap, -5.35 - 0.4 + dustCoverGap, 0]) cube([14.8 - dustCoverGap * 2, 8, 0.6]);
translate([-4.45 + dustCoverGap, -5.35 - 0.4 + dustCoverGap, 0]) cube([11.65 - dustCoverGap * 2, 8, 0.6]);
translate([10.75 + dustCoverGap + 1 * hKeyDistance, -5.35 - 0.4 + dustCoverGap, 0]) cube([15 - dustCoverGap * 2, 8, 0.6]);
translate([10.75 + dustCoverGap + 2 * hKeyDistance + 0.2, -5.35 - 0.4 + dustCoverGap, 0]) cube([14.6 - dustCoverGap * 2, 8, 0.6]);
translate([10.6 + dustCoverGap + 3 * hKeyDistance + 0.2, -5.35 - 0.4 + dustCoverGap, 0]) cube([14.35 - dustCoverGap * 2, 8, 0.6]);
translate([10.6 + dustCoverGap + 4 * hKeyDistance + 0.2, -5.35 - 0.4 + dustCoverGap, 0]) cube([11.6 - dustCoverGap * 2, 8, 0.6]);
translate([0, -9.5, 0]) numberBarSurface(keyW = topKeyW, keyD = keyD, keyH = topKeyH, keys = keys);
echo("bar h:", keySupportH + topKeyH);
}
}
module topRowKeysAssembly(keys = 2, rightWideKeyIndex = 0, leftWideKeyIndex = 4, keyH = 4) {
union() {
for (i = [0 : keys - 1]) translate([hKeyDistance * i - 0.1, 0, 0]) topRowKeyAssembly(armHeight = 0.25 + i * 0.25, isRightWideKey = (i == rightWideKeyIndex ? true : false), isLeftWideKey = (i == leftWideKeyIndex ? true : false), topKeyH = keyH, isNearNumberSwitchKey = [(i == 2 ? true : false), (i == 3 ? true : false)]);
}
}
module bottomRowKeysAssembly3(keys = 2, rightWideKeyIndex = 0, leftWideKeyIndex = 4, keyH = 5.2) {
for (i = [0 : keys - 1]) translate([hKeyDistance * i - 0.1, 0, 0]) bottomRowKeyAssembly(armHeight = 0.25 + i * 0.25, isRightWideKey = (i == rightWideKeyIndex ? true : false), isLeftWideKey = (i == leftWideKeyIndex ? true : false), keyH = keyH);
}
module carvedArm(armL, armW, levelH, firstLevelH, levelTranslateIncrement, levels, drawFakeKey = false, bevel = true) {
union() {
difference() {
union() {
keyArm(armWidth = armW, armLength = armL + 3, armHeight = firstLevelH, pivotDepth = 0);
for(i = [1 : levels - 1]) translate([0, -(i * levelTranslateIncrement), (i - 1) * levelH + firstLevelH]) keyArm(armWidth = armW, armLength = armL + 10, armHeight = levelH, pivotDepth = 0);
}
translate([-armW, -armL * 11, -1]) cube([armW * 2, armL * 10, 50]);
if (bevel) for (i = [0, -1]) mirror([i, 0, 0]) translate([-armW / 2, -armL, 0]) bevel();
}
if (drawFakeKey) translate([0, -armL, 0]) fakeKey(armL = armL, armW = armW);
}
}
module fakeKey(armL, armW) {
keyArm(armWidth = armW, armLength = 23, armHeight = 3, pivotDepth = 0);
}
module frame(keys = 6, differenceH = -1, holeIncrease = [-0.8 , 0], frameH = 2, cutTopFrame = 2, cutBottomFrame = 0, topBevelsTopFrame = [false, false, false, false]) {
difference() {
advancedBeveledCube([17 + hKeyDistance * keys, 79, frameH], center = false, bevelR = 8, bevelSegments = 20, topBevelR = 2, topBevelSegments = 16, topBevels = topBevelsTopFrame);
translate([8.94 - holeIncrease[0] / 2, 5, differenceH]) beveledCube([-1 + hKeyDistance * keys + holeIncrease[0], 64 + holeIncrease[1], frameH * 2], center = false);
if (cutTopFrame > 0) translate([-1,65,frameH - cutTopFrame]) cube([150,100,100]);
else if (cutBottomFrame > 0) translate([-1,65+0.5,10]) rotate([180, 0, 0]) cube([150,100,100]);
if (cutBottomFrame > 0) translate([-1,65+0.5,2]) rotate([20, 0, 0]) cube([150,100,100]);
}
}
module consonantsKeyboard(keys = 5, numberKeyIndex = 2, rightWideKeyIndex = 0, leftWideKeyIndex = 4, drawTopRow = true, drawBottomRow = true, drawFrame = true, frameH = 4, keyH = 5.2, cutTopFrame = 2) {
union() {
if (drawTopRow) topRowKeysAssembly(keys = keys, rightWideKeyIndex = rightWideKeyIndex, leftWideKeyIndex = leftWideKeyIndex, keyH = keyH);
if (drawBottomRow) translate([0, -10, 0]) bottomRowKeysAssembly3(keys = keys, rightWideKeyIndex = rightWideKeyIndex, leftWideKeyIndex = leftWideKeyIndex, keyH = keyH);
if (drawFrame) translate(framePosition) difference() {
frame(keys = keys, frameH = frameH, cutTopFrame = cutTopFrame, topBevelsTopFrame = [false, false, false, true]);
#for (i = [0 : 1]) for (j = [0 : 1]) translate([5 + (25 + hKeyDistance * (keys - 1)) * i, 7 + (65) * j, -1]) cylinder(r = 3.3 / 2, h=50, $fn = 18);
for (i = [0 : 1]) for (j = [0 : 1]) translate([5 + (25 + hKeyDistance * (keys - 1)) * i, 7 + (65) * j, 2]) cylinder(r = 7 / 2, h=50, $fn = 36);
}
//scale([1, 1, 2]) dustCover();
dustCover();
}
}
module barKeyboard(keys = 6, numberKeyIndex = 3, rightWideKeyIndex = 0, leftWideKeyIndex = 5, drawBar = true, drawFrame = true, frameH = 4, keyH = 3.2, cutTopFrame = 0, cutBottomFrame = 3, logoH = 0.9) {
union() {
color("red") translate([-5,-177.75,3.99]) scale([0.54 * 1.5, 0.62 * 1.5, 1]) difference() {
linear_extrude(height = logoH, center = false, convexity = 10) import(file = "stenoboardcom_logo.dxf");
translate([123.25,120,-1]) cube([100,100,100]);
}
color("red") translate([-5,0.25,0]) scale([0.35, 0.35, 1]) linear_extrude(height = logoH + 4, center = false, convexity = 10) import(file = "utopen_logo.dxf");
if (drawBar) numberBarAssembly(keys = keys, numberKeyIndex = numberKeyIndex, topKeyH = keyH);
if (drawFrame) translate(framePosition) difference() {
frame(keys = keys, frameH = frameH, cutTopFrame = cutTopFrame, cutBottomFrame = cutBottomFrame, topBevelsTopFrame = [false, true, false, false]);
for (i = [0 : 1]) for (j = [0 : 1]) translate([5 + (25 + hKeyDistance * (keys - 1)) * i, 6 + (66) * j, -1]) cylinder(r = 3.3 / 2, h=50, $fn = 18);
for (i = [0 : 1]) for (j = [0 : 1]) translate([5 + (25 + hKeyDistance * (keys - 1)) * i, 6 + (66) * j, 2]) cylinder(r = 7 / 2, h=50, $fn = 36);
}
}
}
module barButtonContact() {
beveledCube([3,6,2], bevelR = 1.5);
}
module screwHole(id, od, h, topOd, coneH, bevel = [false, false, false, false], holeStartH = -1) {
difference() {
union() {
cylinder(r = od / 2, h = h - coneH, $fn =30);
translate([0,0,h - coneH - 0.001]) cylinder(r1 = od / 2, r2 = topOd/2, h= coneH + 0.001, $fn =30);
for (i = [0 : 3]) if(bevel[i]) rotate([0, 0, 45 + i * 90]) translate([od / 2 - 0.9, 0, 0]) rotate([90, 0, 0]) scale([1, 1, 1]) {
bevel(r = h * 0.9, length = 4, segments = 50);
rotate([0, 180, 0]) translate([-1, 0, -2]) cube([2, h * 0.9, 4]);
}
}
translate([0, 0, holeStartH]) cylinder(r = id / 2, h = h*3, $fn =12);
}
}
module vowelsFrame(baseH = -1, frameH = 6.3, isKeyboard = false) {
union() {
difference() {
union() {
translate([3, 7.5, 0]) beveledCube([40, 36, frameH], center = false, bevelR = 4, bevelSegments = 20);
//translate([-1, 40, 0]) beveledCube([48, 1.5, frameH], center = false, bevelR = 1);
translate([-0.5, 37.5, 0]) beveledCube([47, 8 + (isKeyboard ? 1 : 0), frameH], center = false, bevelR = 0);
}
translate([0, 8, 0]) if (isKeyboard) translate([7, -4, baseH]) beveledCube([32, 41 - (isKeyboard ? 2 : 0), rightVowelsScrewH * 2], center = false);
else {
translate([7, 2, baseH]) beveledCube([32, 31, rightVowelsScrewH * 2], center = false);
translate([8, 2, baseH]) cube([30, 61, rightVowelsScrewH * 2], center = false);
translate([1 + 0.01, -1, frameH +0.01]) scale([1, 0.7, 1]) rotate([0, 0, 90]) rotate([-90,0,0]) bevel(r = 10, length = 100, segments = 40);
}
if (isKeyboard) translate([-20, -10.3, -1]) cube([100,50.5,100]);
}
if (!isKeyboard) difference() {
union() {
translate([17 + 6 + 0.01, 7.75, frameH +0.01-2.1]) scale([1, 0.7, 1]) rotate([0, 0, 90]) rotate([-90,0,0]) bevel(r = 10, length = 32.25, segments = 40);
translate([6.75 + 0.01, 7.75, frameH +0.01-2.1]) scale([1, 0.7, 1]) cube([32.25,10,2.1]);
}
translate([1 + 0.01, 7, frameH +0.01]) scale([1, 0.7, 1]) rotate([0, 0, 90]) rotate([-90,0,0]) bevel(r = 10, length = 100, segments = 40);
translate([6.85, 13.5, frameH +0.01-1.2-20]) beveledCube([32.3,10,50]);
}
}
}
module vowelsBase(baseH) {
union() {
translate(rightVowelsBasePosition) difference() {
vowelsFrame(baseH = baseH, frameH = rightVowelsScrewH + screwFrameVerticalOffset);
for(i = [0, 1]) for(j = [1]) translate([4 + 38 * i, 6 + 37 * j, -1]) cylinder(r=rightVowelsBaseScrewD / 2, h = 100, $fn =12);
}
for(i = [0:1]) translate(rightEReference + rightVowelsScrewPositions[i]) {
screwHole(rightVowelsScrewD, rightVowelsScrewD + 2.6, rightVowelsScrewH - 1, rightVowelsScrewD + 2, rightVowelsScrewD + 1, rightVowelsScrewBevels[i], rightVowelsScrewH - 12);
translate([0,4.5,rightVowelsScrewH/2]) cube([4,5,rightVowelsScrewH], center = true);
}
translate(rightEReference + rightVowelsScrewPositions[2]) {
translate([0,11,rightVowelsScrewH/2]) cube([5,3,rightVowelsScrewH], center = true);
translate([0,11,rightVowelsScrewH/4]) cube([5,8,rightVowelsScrewH/2], center = true);
}
}
}
module vowelsKeyboard() {
union() {
difference() {
union() {
translate(rightVowelsBasePosition) vowelsFrame(isKeyboard = true);
translate(rightEReference + [0, 9, 0]) {
translate([-0.5, 0, 0]) difference() {
union() {
bottomRowKeySurface(keyW = 14, keyD = 23, keyH = 5.2);
translate([-3.5, 23 / 2 - 0.1, 0]) cube([7, 7,0.4]);
translate([-3.5, 23 / 2 - 0.1 - 2, 0]) cube([7, 7,1]);
}
translate([-14 / 2, -23 / 2, 0,]) bevel(r = 14 / 2, length = 20, segments = 24);
translate([14 / 2, -23 / 2, 0,]) rotate([0, 0, 90]) bevel(r = 13 / 2, length = 20, segments = 24);
}
translate([vowelsKeyDistance - 0.5, 0, 0]) difference() {
union() {
bottomRowKeySurface(keyW = 14, keyD = 23, keyH = 5.2);
translate([-3.5, 23 / 2 - 0.1, 0]) cube([7, 7,0.4]);
translate([-3.5, 23 / 2 - 0.1 - 2, 0]) cube([7, 7,1]);
}
translate([-14 / 2, -23 / 2, 0,]) bevel(r = 14 / 2, length = 20, segments = 24);
translate([14 / 2, -23 / 2, 0,]) rotate([0, 0, 90]) bevel(r = 13 / 2, length = 20, segments = 24);
}
}
}
translate(rightVowelsBasePosition) {
for(i = [0, 1]) for(j = [0, 1]) translate([4 + 38 * i, 6 + 37 * j, -1]) cylinder(r=3.5 / 2, h = 100);
translate([-2, 39, -1]) cylinder(r = 4, h = 10);
translate([2 + 46, 39, -1]) cylinder(r = 4, h = 10);
}
}
difference() {
translate(rightVowelsBasePosition + [8 + 15, 13.2 + 15 + 0.1 - (dustCoverGap - 0.4) / 2, 0.3]) beveledCube([31.25-0.4, 28.75-0.2-(dustCoverGap-0.4), 0.6], center = true, bevelY = [true, true], bevelR = 1.5);
translate(rightVowelsBasePosition + [8 + 15, 13.2 + 15, 0]) cube([dustCoverGap, 28.75, 10], center = true);
translate(rightVowelsBasePosition + [6.56, 41.5, 0]) cylinder(h = 10, r = 2 + dustCoverGap - 0.4, center = true, $fn = 24);
translate(rightVowelsBasePosition + [(23 - 6.56) + 23, 41.5, 0]) cylinder(h = 10, r = 2 + dustCoverGap - 0.4, center = true, $fn = 24);
translate(rightVowelsBasePosition + [23 - 7.3, 56, 0]) beveledCube([7.5, 28.75, 10], center = true, bevelR = 1);
translate(rightVowelsBasePosition + [23 + 7.2, 56, 0]) beveledCube([7.5, 28.75, 10], center = true, bevelR = 1);
}
}
}
module base(keys = 6, baseH = 1.2, baseFrameH = mainRightScrewH + screwFrameVerticalOffset, isRight = true, drawVowels = true) {
difference() {
union() {
difference() {
translate(framePosition) frame(keys, differenceH = baseH, holeIncrease = [2, 7], frameH = baseFrameH, cutTopFrame = 0);
translate(framePosition) translate([9 - 1.5 / 2 + (isRight ? 0 : 64 - 2/2), 2, baseH + 4]) beveledCube([46+1.5, 50, baseFrameH * 2], center = false);
if(isRight) translate([-40, -27, -1]) cube([55,26,23]);
if(isRight) translate([-6, 10, baseFrameH]) rotate([0, 0, -90]) rotate([0, 90, 0]) cylinder(r=3.75, h = 30, center = true, $fn=100);
else translate([97.3, -10, baseFrameH]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(r=3.75, h = 50, center = true, $fn=100);
translate([-1.5 + 0.01 + (isRight ? 0 : leftVowelsOffset), -85, baseH]) cube([32 - 0.02,25,50]);
}
translate([5,3,12.5]) cube([15,7.2,25], center=true);
translate([isRight ? 90 : 85,3,12.5]) cube([15,7.2,25], center=true);
translate([isRight ? 70.5 : 20.9,-65.2,12.5]) cube([62,4,25], center=true);
translate([isRight ? 39 : 53,-65.2,9]) cube([3,4,18], center=true);
if (drawVowels) translate([isRight ? 0 : leftVowelsOffset, 0, 0]) vowelsBase(baseH = baseH);
if(isRight) for(i = [0:3]) translate(boardCenter + mainRightScrewPositions[i]) screwHole(mainRightScrewD, mainRightScrewD + 6, mainRightScrewH, mainRightScrewD + 2.6, 2, mainRightScrewBevels[i], mainRightScrewH - 12);
else for(i = [0:3]) translate(boardCenter + mainLeftScrewPositions[i]) screwHole(mainRightScrewD, mainRightScrewD + 6, mainRightScrewH, mainRightScrewD + 2.6, 2, mainLeftScrewBevels[i], mainRightScrewH - 12);
if(isRight) for(i = [0:3]) translate(boardCenter + arduinoScrewOffset + arduinoScrewPositions[i]) screwHole(arduinoScrewD, arduinoScrewD + 6, arduinoScrewH, arduinoScrewD + 2.6, arduinoScrewD + 1);
%translate(boardCenter + arduinoScrewOffset + arduinoScrewPositions[0] + [-15.3, 2.5 - 53.3, arduinoScrewH]) cube([68.6, 53.3, 1.4]);
}
for(i = [0:3]) translate(frameScrewPositions[i] + [0, 0, -1]) cylinder(r = frameScrewD / 2, h = 100);
}
}
module dustCover() {
color("red") difference() {
translate([-7.85 + dustCoverGap / 2, -64.1 + dustCoverGap / 2, 0]) beveledCube([hKeyDistance * 6 - 2.9 - ((dustCoverGap - 0.4) * 2), 64 + 0 - (dustCoverGap * 2), 0.6], center = false, bevelR = 1.5);
for (i = [-1 : 1]) translate([-6.85 + (- 1 + hKeyDistance * 6 - 3.8) / 2 + hKeyDistance * i, -66.1 + (66 - 0.8) / 2, 0]) cube([dustCoverGap, 66 - 0.8, 5], center = true);
for (i = [-0.995, 1]) translate([-6.85 + (- 1 + hKeyDistance * 6 - 3.8) / 2 + hKeyDistance * 1.94 * i, -66.1 + (66 - 0.8) / 2, 0]) cube([dustCoverGap, 66 - 0.8, 5], center = true);
translate([45.75, -41.25, 0.15]) cube([120, dustCoverGap, 10], center = true);
for (i = [-2 : 3]) translate([-6.85 + (- 1 + hKeyDistance * 6 - 3.8) / 2 - hKeyDistance / 2 + i * hKeyDistance, -77, 0]) beveledCube([12.8 + (dustCoverGap * 2 - 0.8), 29.25, 10], center = true, bevelR = 1);
for (i = [-2 : 3]) translate([-6.85 + (- 1 + hKeyDistance * 6 - 3.8) / 2 - hKeyDistance / 2 + i * hKeyDistance, 5, 0]) mirror([0, -1, 0]) beveledCube([12.8 + (dustCoverGap * 2 - 0.8), 29.25, 10], center = true, bevelR = 1);
translate([45.75 - 1.5 - 0.6, -40.8, -4.5]) scale([1.4, 1.5, 10]) barButtonContact();
}
}
module rightBaseBridgeTest() {
intersection() {
base(drawVowels = true);
translate([-20,-37, 18]) cube([12, 47, 7]);
}
}
// This is meant to serve as a cheap shipping cover, to protect the keys
module cover(keys = 6, baseH = 0.6, lowScrewH = 1.2 + 2, highScrewH = 1.2 + 2 + 2, screwHolderR1 = 3.5, screwHolderR2 = 2.75) {
difference() {
union() {
translate(framePosition) beveledCube([17 + hKeyDistance * keys, 79, highScrewH + baseH], center = false, bevelR = 8, bevelSegments = 20);
}
for(i = [0:3]) translate(frameScrewPositions[i] + [0, 0, -1]) cylinder(r = frameScrewD / 2 + 0.5, h = 100);
difference() {
translate(framePosition + [-0.5, -0.5, baseH]) beveledCube([17 + hKeyDistance * keys + 1, 79 + 1, highScrewH + baseH], center = false, bevelR = 8, bevelSegments = 20);
translate(frameScrewPositions[0]) cylinder(r1=screwHolderR1 , r2=screwHolderR2, h = baseH + lowScrewH);
translate(frameScrewPositions[1]) cylinder(r1=screwHolderR1 , r2=screwHolderR2, h = baseH + lowScrewH);
translate(frameScrewPositions[2]) cylinder(r1=screwHolderR1 , r2=screwHolderR2, h = baseH + highScrewH);
translate(frameScrewPositions[3]) cylinder(r1=screwHolderR1 , r2=screwHolderR2, h = baseH + highScrewH);
}
}
}
module rightAssembly(drawConsonants = true, drawNumbers = true) {
translate([-45.73, 50, 0]) union() {
if (drawConsonants) color("white") translate([0, 0, 28.8 - 0]) consonantsKeyboard(keys = 6, numberKeyIndex = 3, rightWideKeyIndex = 0, leftWideKeyIndex = 5, drawTopRow = true, drawBottomRow = true, drawFrame = true);
if (drawNumbers) color("white") translate([0, 0, 0]) translate([0, 0, 2+28.8 + 0]) barKeyboard();
color("green") translate([44.35, -39.75, 28.8]) barButtonContact();
color("red") base();
//translate([-45.73, 50, 0]) base(isRight = false);
color("white") translate([0, 0, 19.5]) vowelsKeyboard();
}
}