- Iris Rev 2 PCBs (Only Rev 4 is available now)
- 2 Arduino Pro Micros (1 regular and 1 elite-c)
- 3D-printed case
- M3 nuts & bolts (for attaching the tenting legs)
- 53 "Trash Panda" key switches (purchased from someone on Reddit's mechmarket)
- Canvas Ortho Keycap set (purchased from someone on Reddit's mechmarket)
- TRRS Cable
- Magnetic USB Cables - these are super nice so you don't accidentally break off the usb connector on your pro-micro!
Here are the parts that came in the kit from Keebio:
The case was 3D printed using these Iris case files by wizarddata (thanks for making these available!). I've copied the same files into the iris_case_files folder in this repo. The parts were printed at at the GWU Innovation Center (shout out to Konstantin Mitic for all the help with this!).
After printing the parts, I tried to create a "wood"-like look for the top pieces by attempting to stain them (staining plastic is tricky, but do-able). I started by coating the parts in a black stain to try and build some variation in the main color. After that dried (about 24 hours later), I coated the parts again in a stain-polyurethane blend by Midwax (I used [Olde Maple(https://www.minwax.com/wood-products/one-step-stain-and-finishes/minwax-polyshades)]). The polyurethane in the blend helped keep the color in place as it all dried.
| Black stain layer | Stain-polyurethane coating |
|---|---|
![]() |
![]() |
Since the back pieces were black plastic and therefore the stain color wouldn't work, I attempted to give them a metallic look by spray painting them with a silver colored "Hammered Spray Paint" by Rust-Oleum.
Finally, I sealed all the parts using a water-based Polycrylic by Minwax. This gave everything a smooth feel.
The final product came out okay, though the stained parts look more like a leather than wood IMO. Despite the backs looking like Altoid cans, the overall aesthetic is somewhat steampunk-esqe.
| Final pieces | Final case assembled |
|---|---|
![]() |
![]() |
For the most part, I followed the Iris build guide, which is pretty straight forward. However, I made one major error, and one minor error (I'll get to those in a bit).
I started by flashing the pro-micros to make sure they work, following the guide here. Once I was confident the pro-micros were good, I moved on to soldering the diodes, TRRS jacks, and reset switches.
Here's where I made the major error - I went straight to soldering the switches...big mistake. Instead, I should have soldered on the pro-micro header pins before the switches. Realizing my error too late, I de-soldered the two switches that sit just over the pro-micro and had to solder the pro-micro header pins from the top side of the switch plate, which was ridiculously tedious. Once I got that error fixed, I moved on to soldering on the pro-micros.
| Major error | Switches soldered in place |
|---|---|
![]() |
![]() |
Both sides with soldering all done:
The minor error was adding the rotary encoder at the end. This was mostly because I decided to add it on a few weeks after finishing the build. In retrospect I should have installed it prior to soldering in the switches as adding it at the end left me little wiggle room when trying to get the pins all aligned and wired up.
I was able to get it in place by first straightening out the three pins on the encoder and soldering on three wires to them. I then fed those wires down through the switch plate and around the bottom of the PCB (see the close up photo below).
| Rotary encoder | Close up of mounted encoder |
|---|---|
![]() |
![]() |
I then clipped off the two mounting feet on the encoder and soldered the two other encoder leads to the PCB where you would otherwise solder a key switch. This enables me to program a key press when pressing down on the encoder (I use it to toggle between layers, which changes the rotary encoder's functionality). I added a dab of Gorilla Glue to keep the whole thing nice and set in place. Finally, I soldered the other ends of the wires to the F4, F5, and Ground holes at the top of the PCB.
| Gorilla Glue | Soldered wires at top of PCB |
|---|---|
![]() |
![]() |
After getting everything set, I realized the case wouldn't quite close over the wires coming off the rotary encoder, so I used a dremel to make some extra space. It looked better once I painted over it again.
| Final wiring | Dremeled-out spacing for wires |
|---|---|
![]() |
![]() |
I started by following the QMK "getting started" documentation to build the Iris firmware. It's all pretty straightforward and well-documented.
Where I made the biggest gains was to use the QMK Configurator for the Keebio Iris Rev 2 to setup most of my keymap. On each layout iteration (I experimented for a while), I downloaded the json file from the configurator, then used that file to create my keymap.c file that goes in my "jhelvy" keymap inside the qmk_firmware folder (qmk_firmware/keyboards/keebio/iris/keymaps/jhelvy/keymap.c). Since the json file is a different format from that in the keymap.c file, I used a simple R script in my qmkJsonConverter repo to convert the json file to a plain .txt file that had the code needed for the keymap.c file. Then I just copy-pasted the code in the .txt file over to the keymap.c file. This allowed me to quickly go back-and-forth between changing my settings on the QMK Configurator and generating the necessary keymap.c file. On each iteration, I then followed the QMK instructions to build the .hex firmware and then flashed it to the Iris using the QMK Toolbox.
This gave me some trouble until I found this documentation on configuring the rotary encoder on a Lily58. Turns out it's pretty straightforward - I'll repeat the instructions here.
First, in rules.mk, I added ENCODER_ENABLE = yes, as well as setting EXTRAKEY_ENABLE = yes. The EXTRAKEY_ENABLE is necessary if you want to control media keys (e.g. control volume).
Then in the config.h add :
#define ENCODERS_PAD_A { F4 }
#define ENCODERS_PAD_B { F5 }
#define ENCODER_RESOLUTION 4
This creates one encoder, and assigns the rotation pins to F4 and F5 (which is what the wires from encoder are connected to). 4 is a pretty good resolution.
To configure the encoder to control the volume, put the following code below the function matrix_init_user in keymap.c:
void encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
if (clockwise) {
tap_code(KC_VOLU);
} else {
tap_code(KC_VOLD);
}
}
}
This tells the encoder to send "volume up" when turned clockwise and "volume down" when turned counter-clockwise.
In my case, I used if-else conditionals to change what the encoder does based on what layer I'm on. Here's my full settings. Note: my settings are reversed (e.g. "clockwise" is volume DOWN not UP) because I think I connected the wires the wrong way...much easier to change the settings than re-wire things :)
void encoder_update_user(uint8_t index, bool clockwise) {
if (IS_LAYER_ON(_LAYER1)) {
if (clockwise) {
tap_code(KC_MS_WH_LEFT);
} else {
tap_code(KC_MS_WH_RIGHT);
}
} else if (IS_LAYER_ON(_LAYER2)) {
if (clockwise) {
tap_code(KC_VOLD);
} else {
tap_code(KC_VOLU);
}
} else if (IS_LAYER_ON(_LAYER3)) {
if (clockwise) {
register_code(KC_LGUI);
tap_code(KC_MINS);
unregister_code(KC_LGUI);
} else {
register_code(KC_LGUI);
tap_code(KC_EQL);
unregister_code(KC_LGUI);
}
} else {
if (clockwise) {
tap_code(KC_MS_WH_UP);
} else {
tap_code(KC_MS_WH_DOWN);
}
}
}
Here's what that code does. The default layer (0) is mouse scroll "up" (CW) and "down" (CCW). When on layer 1 (which I trigger with my main left thumb key), it is mouse scroll "right" (CW) and "left" (CCW). When on layer 3 (which I trigger with my farthest-left left-hand thumb key), it sends "Command + Equal" to zoom in (CW) and "Command + Minus" to zoom out (CCW). I use the zooming and scrolling left / right mostly when working with images, like in photoshop. Finally, when I press down on the encoder, it toggles to layer 2 and becomes "volume up" (CW) and "volume down" (CCW). The only thing not in the code above is the control to get the keypress on the rotary encoder to toggle between layers, which is set in the keymap.c file.
Since I didn't use the RGB lighting (my casing is completely enclosed anyway), I turned that feature off to save space in my rules.mk:
RGBLIGHT_ENABLE = no
BACKLIGHT_ENABLE = no
I also really like the Autoshift feature, so I turned that on in rules.mk:
AUTO_SHIFT_ENABLE = yes # Autoshift by holding down a key
I also modified the specific settings for the autoshift in the config.h file:
#define TAPPING_FORCE_HOLD
#undef TAPPING_TERM
#define TAPPING_TERM 200
#define AUTO_SHIFT_TIMEOUT 150
Finally, as noted above, to get the rotary encoder working I had to enable that feature (with the EXTRAKEY_ENABLE to control volume):
ENCODER_ENABLE = yes
EXTRAKEY_ENABLE = yes
Important: One slightly annoying feature with this setup is that the rotary encoder is only supported on the master side, and since I put the encoder on my right hand, I had to make that side the master by changing the setting in the config.h file:
// Had to swap the master to get the right-side rotary encoder supported
#define MASTER_RIGHT
Unfortunately, I only learned this later after soldering my pro-micros in place. I had intended up use the elite c pro micro for the master side, which I put on the left side. So now I've got a really nice elite c on the slave side...whatever, it works.















