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
|
---
description: Adjustable column position, thumb clusters
created: 2024-01-24
---
 <iframe src="pcb/index.html" style="width: 100%; max-width: 40em; height: 40em; border: none;" scrolling="no"></iframe>
Checkout [V1 of this keyboard](https://blog.node5.net/Custom%20keyboard/).
### Parts list
- [aliexpress.com/ - Horizontal scrollers EVQWGD001](https://www.aliexpress.com/item/32990950196.html)
- [keychron.com - Gateron Low Profile 2.0 Mechanical Switch](https://www.keychron.com/products/low-profile-gateron-mechanical-switch-set?variant=40587643355225)
- [keychron.com - Keychron Low Profile Mechanical Switch](https://www.keychron.com/products/keychron-low-profile-mechanical-switch?variant=40561882595417)
With the first edition i validated that i like ortholinear layout, this enables me to offset the columns relative to
each other, but i cannot settle on how much to offset it, therefore i got the idea to make it adjustable,
I've not seen this done before.


The keyboard base will have GPIO + I²C pulled out on a connector, allowing any kind of expansion
I'll make the following modules: trackpoint, mouse buttons, thumb clusters, rollers for vertical scrolling and volume.
### Desiging a switch holder

### Trackpoint

The trackpoint module is a PS/2 device, see [QMK documentation](https://docs.qmk.fm/#/feature_ps2_mouse) and
[Trackpoint pinout](https://deskthority.net/wiki/TrackPoint_Hardware)
### Height

### Keycaps

To print legends, multi color on the same layer see this cool blog:
[Creating a Keyboard - docs.juliaebert.com](https://docs.juliaebert.com/projects/keyboard#making-them-prettier)
### Switches

[product page](https://www.gateron.co/products/gateron-low-profile-mechanical-switch-set)

I ought to use a PCB for this, but that doesn't play nice with my rapid proto typing.


Testing if this method can be manufactured on my 3D printer, it's only 2 lines wide.
### 3D printed "PCB" feasability

### Other keyboards with adjustable columns
Apparently I'm not the first to think of adjustable columns, bummer see this
[ReSummit/Seismos GitHub repo](https://github.com/ReSummit/Seismos)
And this [nezumee/zebra GitHub repo](https://github.com/nezumee/zebra)
### Design goals
- Low profile
- Modular additions
- Indents for anti slip feet, to keep it low profile
- Joinable halves perhaps
- Tactile difference for different types of keys
- Smaller function key row
- Concave and convex keys, to indicate type
- Lots of homing indicators
### Meta
This article is more of a timeline of how it actually happened,
by meerly appending, instead of going back, and changing stuff
### Column module prototype






### Printing Keycaps


Again, printed on its side for greater dimensional accuracy
### Thumb cluster design vision
Came across this really cool keyboard called Dygma Defy
[youtube.com - video](https://www.youtube.com/watch?v=9-h5RVu_HBA)
[dygma.com - Blog post](https://dygma.com/blogs/product-development/how-we-developed-the-defys-16-thumbkeys)
they show their design iterations on thumb clusters they seem to align with what i envisioned,
namely ergonomically shaped buttons, which is possible due to the 3D printing manufacturing. They've done lots
### GPIO expander chip ordered
Ordered an [MCP23017](https://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf)
I²C GPIO expander in [DIP28](https://en.wikipedia.org/wiki/Dual_in-line_package)
package format. To use on the left side of the keyboard.
### Layout designed

This layout avoids having 2 unit wide buttons, which would interfere with the column sliding mechanism.
Instead these buttons are moved to 2 thumb clusters. Which i I'm eager to try out.
### Prototype pile

Here's the pile of prototypes it took to get a satisfying and functional mechanism and keycaps.
### Module wired


Soldered up the first module. I used stranded wire due to metal fatigue. This methodology seems to be feasible.
I'm going to add pin header connectors to connect it to the board, so it can be disconnected and the module removed.
Spanning the top is gonna be a prototype board PCB with all the diodes, connectors for modules, DIP28 GPIO expander and
the TRRS headphone jack.
### Modules for left side printed

Done printing and cleaning up all the modules for the left side.


Printed the bottom for the left side it unfortunately bent slightly when the modules were put in place,
even tho i was patient letting it cool down after printing. I held it over the stove, and counter bend it.
Then placed it on a flat surface. Which fixed the curve.

Planned out the circuit diagram for the left side of the keyboard, everything fit really nicely.
I'm excited to make it a reality. The top features pin headers for each sliding module. Which has 6 pins, 1 for the
column, and 5 for the rows. The rows are connected to the diodes, which bridge the gap to their respective colored bus
bars on the bottom side. Which forms a natural ╲ ╲ ╲ ╲ ╲ pattern. The columns have busbars on the bottom left side.
Both bus bar clusters are terminated in 2 flex cable connections, one for the GPIO expander chip, and one for a male pin
header for testing and debugging, it's also pin compatible with my old keyboard, allowing me to do an agile partial
goal, and get success feeling of trying it out, motivating me to keep working, and getting to test it
before i add to many variables and unknowns, which could lead to multiple failure points,
making me have to debug multiple possible error sources at the same time. There's 2 rows of connection points next to
the debug connector, which is a fine place to extend the connection on to thumb cluster module, which differs because it
has the diodes on the module as opposed to on the circuit board. It has 1 pin for the row, and the rest for the columns.
Because it's wired up like it was a row at the bottom of the keyboard. Finally the headphone jack fits in the top
right corner, pointing upwards, since there's already going to be the cables from the sliding modules looping that way.
### Circuit board initial test


Painted the circuit board, to indicate where the busbars on the bottom are routed.
Wired up a test setup to test the first 4x4 buttons, and it works, yay ^-^

## Full stop
So up to this point, i had the intention of making this into a full hand wired keyboard.
But I don't like how the wires at the top ended up looking,
so I've chosen to cut my losses and use my prototype to decide how I want the offsets to be,
and as a test bed to remove my last few unknowns, namely, thumb cluster and I/O expander chip.
I should have cut more corners, to test the core concept, before spending time, on the niceties.
## MCP23017
Using this tutorial:
[makerhacks.com ─ Use the MCP23017 GPIO Port Expander to Add 16 IO Pins](https://www.makerhacks.com/mcp23017/)
i was able to make the [MicroPython](https://en.wikipedia.org/wiki/MicroPython) example work, but issues arise.
It keeps throwing the exception: `[Errno 5] EIO`, furthermore `i2c.scan()` is not consistent with what it returns.
All this is despite forgoing the breadboard, in favor of directly soldered connections :/
### MCP23017 MicroPython code snippet
```py
# https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-micropython-code-snippet
# Based on: https://www.makerhacks.com/mcp23017#h-using-mcp23017-with-raspberry-pi-pico-and-micropython
import time
import machine
i2c = machine.I2C(1,
sda=machine.Pin(0),
scl=machine.Pin(1),
)
i2cdevices = i2c.scan()
print(i2cdevices)
time.sleep(0.50)
i = 0
while 1:
try:
i2c.writeto_mem(0x20, 0x00, b'\xFF')
i2c.writeto_mem(0x20, 0x01, b'\x00')
i2c.writeto_mem(0x20, 0x13, b'\x00')
while 1:
i2c.writeto_mem(0x20, 0x13, b'\xFF')
time.sleep(0.50)
i2c.writeto_mem(0x20, 0x13, b'\x00')
time.sleep(0.50)
except Exception as ex:
i += 1
print(i, ex)
```
> [github.com ─ dhylands / rshell](https://github.com/dhylands/rshell) Can be used to make it easier, to work
> with [MicroPython](https://en.wikipedia.org/wiki/MicroPython)
The issues persisted, and i decided to move from MicroPython to C++ using the
[Adafruit library](https://github.com/adafruit/Adafruit─MCP23017─Arduino─Library)
And since the [github.com ─ earlephilhower/arduino─pico](https://github.com/earlephilhower/arduino─pico) functions
[`bool SetSDA` and `bool SetSCL`](https://arduino─pico.readthedocs.io/en/latest/wire.html)
didn't work to change I²C 0 pins,
i change to the default pins `GP4` for `SDA` and `GP4` for `SCL` denoted by the Raspberry PI Pico pinout.

Still the issues persisted, still working sporadically for a bit, and then stopped working.
I then tried using pull─up resistors with a value of `4.7KΩ`. Still didn't work consistently.
I then searched around, and came across this forum post:
[forum.arduino.cc ─ Problems with MCP23017 ─ Solved](https://forum.arduino.cc/t/problems─with─mcp23017─solved/21997)
And i followed the wiring described therein. Namely, tie `A0`, `A1` and `A2` to ground,
`Reset` to `3.3v` using a `1KΩ` pull-up resistor, and finally tie `SDA` and `SCL` to 3.3v using a `1KΩ` pull-up resistor
(see the following ascii art diagram)
### MCP23017 wiring diagram
```
┌── U ──┐
[ LED Anode ] GPB0 ( 8 ) ┤1 28├ GPA7 ( 7 )
GPB1 ( 9 ) ┤2 27├ GPA6 ( 6 )
GPB2 ( 10 ) ┤3 26├ GPA5 ( 5 )
GPB3 ( 11 ) ┤4 25├ GPA4 ( 4 )
GPB4 ( 12 ) ┤5 24├ GPA3 ( 3 )
GPB5 ( 13 ) ┤6 23├ GPA2 ( 2 )
GPB6 ( 14 ) ┤7 22├ GPA1 ( 1 )
GPB7 ( 15 ) ┤8 21├ GPA0 ( 0 )
[ 3.3v ] VDD ┤9 20├ INTA
[ GND ] VSS ┤10 19├ INTB
NC ┤11 18├ RESET [ 1KΩ → 3.3v ]
[ GP5 & 1KΩ → 3.3v ] SCL ┤12 17├ A2 [ GND ]
[ GP4 & 1KΩ → 3.3v ] SDA ┤13 16├ A1 [ GND ]
NC ┤14 15├ A0 [ GND ]
└───────┘
( x ) = Adafruit library number for this pin
[ x ] = Microcontroller pin
```
### MCP23017 C++ code snippet
```c++
// https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-c-code-snippet
// Based on: https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/examples/mcp23xxx_blink/mcp23xxx_blink.ino
// Blinks an LED attached to a MCP23017 pin.
#include <Adafruit_MCP23X17.h>
#define LED_PIN 8 // MCP23XXX pin LED is attached to
Adafruit_MCP23X17 mcp;
void setup() {
Serial.begin(9600);
// while (!Serial); // Wait for Serial connection, enable for debug of early code
Serial.println("MCP23017 Blink Test!");
// Find ID, by attempting initialization sequentially
int i = 0;
while (!mcp.begin_I2C(i)) {
Serial.print("Error with ID:");
Serial.println(i);
i++;
delay(10);
}
Serial.print("Success with ID:");
Serial.println(i);
mcp.pinMode(LED_PIN, OUTPUT);
Serial.println("Looping...");
}
void loop() {
Serial.print("High, millis: ");
Serial.println(millis());
mcp.digitalWrite(LED_PIN, HIGH);
delay(250);
Serial.print("Low, millis: ");
Serial.println(millis());
mcp.digitalWrite(LED_PIN, LOW);
delay(250);
}
```
## Thumb cluster prototype iterations
I've iterated on the thumb cluster design (based on the amazing work by the [Dygma Defy](https://dygma.com/pages/defy) team)
and I've reached a design that works for me.


### MCP23017 breadboard TRRS cable

I've now moved to using 2 separate breadboards to test if the I²C is stable over the cable (it seems to be).
Pulling the TRRS cable while powered, doesn't break it, but does require a power cycle to function again.
### MCP23017 button code
```c++
// https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-button-code
// Based on: https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/examples/mcp23xxx_combo/mcp23xxx_combo.ino
#include <Adafruit_MCP23X17.h>
#define BLINK_FREQUENCY 1000 // Milliseconds
#define LED_PIN 8 // LED pin on MCP23017
#define BUTTON_PIN 7 // Button pin on MCP23017
Adafruit_MCP23X17 mcp;
int blink_frequency; // Milliseconds
void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23017 Blink Test!");
int i = 0;
while (!mcp.begin_I2C(i)) {
Serial.print("Error with ID:");
Serial.println(i);
i++;
delay(10);
}
Serial.print("Success with ID:");
Serial.println(i);
mcp.pinMode(LED_PIN, OUTPUT);
mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.println("Looping...");
}
void loop() {
// What is an interupt?
if (!mcp.digitalRead(BUTTON_PIN)) {
// Button pushed, light LED
blink_frequency = BLINK_FREQUENCY / 20;
} else {
blink_frequency = BLINK_FREQUENCY; // Milliseconds
}
// Alternate state every blink_frequency milliseconds
bool state = (millis() % (blink_frequency * 2)) > blink_frequency;
Serial.print("State: ");
Serial.println(state);
mcp.digitalWrite(LED_PIN, state);
}
```
### Other QMK keyboards using MCP23017
MCP23017 working principle has been tested. Now it's time to make it work with QMK.
The following keyboards implement the MCP23017.
```bash
# List keyboards containing mcp23017 case insensitive
grep -I --color=always -rnie "mcp23017" | cut -d'/' -f2 | uniq
# List files containing mcp23017 case insensitive with the file extension .h or .c
grep -I --color=always -rnie "mcp23017" --include \*.h --include \*.c | cut -d':' -f1 | uniq
```
- [github.com - nek_type_a](https://github.com/qmk/qmk_firmware/tree/master/keyboards/nek_type_a)
- [github.com - hotdox](https://github.com/qmk/qmk_firmware/tree/master/keyboards/hotdox)
- [github.com - ergodox_stm32](https://github.com/qmk/qmk_firmware/tree/master/keyboards/ergodox_stm32)
- [github.com - ingrained](https://github.com/qmk/qmk_firmware/tree/master/keyboards/ingrained)
- [github.com - ferris](https://github.com/qmk/qmk_firmware/tree/master/keyboards/ferris)
## PCB Design
Based on this tutorial: [How to Design Mechanical Keyboard PCBs with Kicad, Joe Scotto - youtube.com](https://www.youtube.com/watch?v=8WXpGTIbxlQ)
### LED Indicator
I'm adding an indicator LED, it's an RGB LED, meaning I'll have to add a current limiting resistor per color,
with a unique value for each.
I then run into the issue that the forward voltage of the blue LED is higher than the supply voltage, which is about 3v.
[What will happen to an LED if the forward voltage (Vf) is greater than its supply voltage? - electronics.stackexchange.com](https://electronics.stackexchange.com/questions/573214/what-will-happen-to-an-led-if-the-forward-voltage-vf-is-greater-than-its-suppl)
|