diff options
Diffstat (limited to 'Keyboard V2 - Part 1 - Prototyping/index.md')
| -rwxr-xr-x | Keyboard V2 - Part 1 - Prototyping/index.md | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/Keyboard V2 - Part 1 - Prototyping/index.md b/Keyboard V2 - Part 1 - Prototyping/index.md new file mode 100755 index 0000000..a5bb859 --- /dev/null +++ b/Keyboard V2 - Part 1 - Prototyping/index.md @@ -0,0 +1,441 @@ +--- +description: "Prototyping new concepts: Adjustable column position, thumb clusters, GPIO expander" +created: 2024-01-24 +--- + + + +[TOC] + +## Intro + +### Design ideas + +- 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 + +### New Parts + +After finding out, [what worked, and what didn't with my first custom keyboard](https://blog.node5.net/Custom keyboard/#retrospective-ideas-for-a-version-2) +I've got some new ideas for components i want to try out. + +- Low profile switches +- Dedicated scroll / volume roller (scrolling on the roller ball is really nice!) +- GPIO expander, for split keyboard + +- [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) +- MCP23017 + +### Layout + +With the [my first keyboard design](https://blog.node5.net/Custom%20keyboard/) +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, i wonder if there's a reason for this? (this is forshadowing) + + + +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. + +#### Trackpoint + +I might switch from the tiny roller ball to a [ThinkPad TrackPoint™](https://xkcd.com/243/) pointing device. +Since it allows for precise inputs, or fast movement, depepending on force used. +Perhaps this could be implemented with the tiny roller ball aswell. +The rollerball is kinda choppy though. + + + +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 + + + +[V1 keyboard](https://blog.node5.net/Custom%20keyboard/) vs new keyboard (V2) height, almost half, nice + +#### 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) + +### Other keyboards with adjustable columns + +After i started on this, i found out that apparently I'm not the first to think of adjustable columns, bummer see: + +- [ReSummit/Seismos GitHub repo](https://github.com/ReSummit/Seismos) +- [nezumee/zebra GitHub repo](https://github.com/nezumee/zebra) + +## Switch holder module + + + +### Switch holder design ideas + + + + + + +[switch 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 + + + +### Column module prototype + + + + + + + + +### Printing Keycaps + + + +Again, printed on its side for greater dimensional accuracy + +### Prototype pile + + + +Here's the pile of prototypes it took to get a satisfying and functional mechanism and keycaps. + +## Preliminary layout design + + + +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. + +## Wiring + +### First 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 ^-^ + + + +## GPIO Expander + +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. + +### GPIO Expander test + +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); +} +``` + +## Thumbcluster + +### 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 + + +### 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) + +### LED Indicator + +I planned to add 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) + +## Full stop + +Got a bit burned out on the project, shelfing it for now. + +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. + + +## Next up: PCB + +This article is followed up in: [Custom keyboard V2 - part 2 - PCB](/Keyboard%20V2%20-%20Part%202%20-%20PCB/) + +Also checkout [my V1 keyboard](https://blog.node5.net/Custom%20keyboard/). |
