QMKeybox - Anything Can Be a One Button Keyboard

by Nachimir in Circuits > Microcontrollers

97 Views, 1 Favorites, 0 Comments

QMKeybox - Anything Can Be a One Button Keyboard

2025-11-13 19.21.18.jpg
2025-11-13 19.18.27.jpg
2025-11-13 19.27.02.jpg

QMKeybox is a small USB-C interface based on the Pro Micro, that can make almost any conductive object act as USB keyboard. It's also VIA compatible, so while it behaves as a space bar by default, it can easily be remapped to act as any other keyboard key you want.

Depending on what you connect the other side of it to, as well as switches and buttons, you could also find many other ways of triggering it. I've included source files for everything from the firmware to the 3D prints, so you can modify it to meet your specific needs.

I designed this to be a very compact one button interface, partly because I've built a lot of things in the past using other things like IPACs or full size Ardiunos, which can be awkward to fit in smaller controllers or enclosures.

Another reason I designed this was to go with my friend Alex Johansson's videogame MORSE, which is controlled by Morse Code and can be played with actual Morse keys. Connecting one of those to a PC isn't always straightforward though. There are DIY solutions involving stuff like relays, or Alex' own example of hacking a broken mouse; or there are neat off-the-shelf solutions like Brett Hollifield's excellent VAIL Adapter (perfect for people serious about telegraphy; which is still very much a thing in HAM Radio communities!).

For many of the applications me and Alex have in videogames, DIY events, workshops, and community outreach though; a simple, cheap USB interface fills a gap. Hence QMKeybox.

Supplies

2025-11-13 19.34.06-1.jpg
2025-11-13 19.37.56.jpg

You will need:

  1. 3D printed parts (.stl and .step files included below).
  2. A USB-C Sparkfun Pro Micro, or one of the many clones out there.
  3. A computer, to flash the Pro Micro firmware (files included below).
  4. Metal tweezers.
  5. Wire, and wire strippers.
  6. Soldering iron, and solder.
  7. 3.5mm mono minijack lead.
  8. Glue gun.

Optional:

  1. Scalpel.
  2. Third hand.
  3. Zip tie.
  4. Trailing monojack sockets.
  5. 3.5mm jack socket to crocodile clips.

This may work with older Micro-USB Pro Micros too, though I've not tried any.

3D Printed Case

2025-11-13 19.40.46.jpg
2025-11-13 19.43.36.jpg
2025-11-13 19.42.58.jpg
2025-11-13 19.43.13.jpg
2025-11-13 19.42.19.jpg
2025-11-13 19.41.44.jpg

If you're printing these parts yourself, the lid doesn't need supports, and the lower case will print without but can benefit from them if your printer struggles with horizontal holes and bridges. For getting rid of supports, I find a scalpel and curved-point tweezers are best. The tweezers double up for pulling and poking, being very good for pushing support material out of holes.

The box and lid are designed to be a tight push fit. In PLA, if you push and pull them apart more than a few times, that'll quickly become a loose slip fit. This might vary depending on your filament, nozzle, printer calibration and how much maintenance you do. I printed in PLA, with a 0.4mm nozzle, 0.2mm layer height, and 20% adaptive cubic infill.

I've designed two types of lid, because I found there are two types of USB-C Pro Micro, and one is slightly longer than the other (shown in photos). The case accommodates either, but each lid has a different length of backstop. That backstop fills the space between the end of the PCB and the case, stopping the Pro Micro from sliding backwards and forwards when you plug or unplug a USB cable.

Both 3D printed parts have some features included to limit warping (circular cutouts hidden inside the structure of the lid, and the wavy vertical cutouts on the inside box walls). I find slight warping can still occur though, depending on where the part is located on my printers heat-bed. Warping will make slight gaps between the lid and box on the longer sides. The inside bevel helps locate the lid correctly and, if the lid does have any warping, at least means light won't shine through.

It's possible that there are other, slightly differently sized Pro Micro boards out there. For that eventuality, I've included .step files so you can modify as you need. Alternatively, you could file down the backstop teeth, or cut them short with a scalpel so they don't touch the Pro Micro at all, then use double-stick tape to secure it instead. Don't stick it in the box just yet though! It's much easier to flash and solder up the microcontroller before it's imprisoned.

I've attached .step files as well as .stls, just in case you want to make your own edits to the box.

Flash Firmware

2025-11-13 20.18.20.jpg
Screenshot 2025-11-13 201702.png
Screenshot 2025-11-13 201719.png
Screenshot 2025-11-13 201723.png
Screenshot 2025-11-13 201727.png
2025-11-13 20.18.48.jpg
Screenshot 2025-11-13 201857.png

We'll be flashing new firmware to the Pro Micro. I prefer to flash and test it before assembling anything. One of six Pro Micro clones I bought was broken on arrival, with a resistor missing from the board. It would have been very annoying to find that out after assembly.

You'll need the file QMKeybox.hex, which I've included at this step. There are a few different ways to flash QMK firmware to things, and I opted for QMK Toolbox: https://qmk.fm/toolbox

QMK is a variety of open source keyboard firmware that can be used for all sorts of DIY mechanical keyboards, macropads, or any other device with buttons that you want to send key-presses to a computer. Instructables doesn't support the required filetypes, but if you're interested in the source files for QMKeybox, you can find them on github: https://github.com/nachimir/QMKeybox/ . If you don't want to recompile the firmware yourself, you only need the .hex file.

This firmware defaults to making your Pro Micro act as a space bar, and as I'll cover later, VIA is a much easier way to reprogram it than modifying firmware. This is based off of the onekey-promicro firmware example, which is among the numerous source file examples QMK.MSYS ships with, located in: qmk_firmware/keyboards/handwired/onekey/promicro/

I'm not a programmer, nor a keyboard expert, nor really that great at electronics. After following then undoing some red herrings with pull-up resistors, the main change I've made is to enable VIA compatibility. I've tested QMKeybox.hex with two different varieties of Pro Micro though, and both work as they should.

To flash the .hex file to the Pro Micro, I learned from the excellent guide here: https://kriscables.com/flash-controller-qmk/


That covers three different methods. In brief, this is the one I followed:

  1. Open QMK Toolbox.
  2. At the top right, make sure MCU is set to ATMega32U4.
  3. Click "open" and find QMKeybox.hex.
  4. Check the "auto flash" box.
  5. Plug in your Pro Micro.
  6. Use your tweezers to bridge pins GROUND (GND) and RESET (RST).
  7. Wait a few seconds to see if QMK Toolbox starts flashing the microcontroller.
  8. If not, bridge A3 and RST a second time. Some Pro Micro clones apparently need the pins bridged twice before they go into the correct mode.
  9. QMK Toolbox should then tell you it's flashing the thing, then that it's successfully flashed. It might also add a final line about the device being disconnected.
  10. Uncheck auto flash, close QMK Toolbox, unplug the Pro Micro, and plug it back in.

If the flash was successful, the Pro Micro is now running QMK firmware. Computers should recognise it as a valid HID device (Human Interface Device (…device?)). A Windows machine will make those little "do-duh!" "duh-dum!" noises when you plug and unplug it. MacOS might ask you to grant permission for the USB accessory to connect before it'll do anything. Linux will either just work, or (joke!) nuke your oddball GUI from orbit then send you down a two-day rabbit hole of broken dependencies and terminal commands.

At this point, you can also try testing it by bridging pins A2 and A3 with tweezers, but it might behave inconsistently without a ground wire on A3, which we're going to solder during the next step.

Downloads

Wiring

2025-11-13 20.28.09.jpg
2025-11-13 20.29.52.jpg
2025-11-09 18.02.32.jpg

The firmware for this works very simply: bridging pins A2 and A3 causes the Pro Micro to send keypresses over USB. It uses an internal pull-up resistor on one of the pins, and needs pin A3 connected to ground. Briefly bridging the pins will send one keypress, continuously bridging them will continuously send keypresses.

I didn't get many photos of these steps, because it was fiddly, I was holding a very hot object, and I was trying not to inhale fumes.

Cut a small length of black wire. Before stripping the ends, work the middle with your wire strippers to expose a small section of the conductor. Then strip the ends. Cut a small length of red wire, and strip both ends of that. Tin all the exposed ends, plus the middle section of your black wire.

Solder the ends of the black wire to GND and A3. Solder the red wire to pin A2. Place your Pro Micro into the box, and push it all the way home so the USB-C socket is more-or-less flush with the outside surface.

You can solder up your own 3.5mm lead for this part, but instead of making those from scratch, I just buy short mono patch leads and cut them in half. They're inexpensive and tend to have nicely molded connectors, so are a very quick, low-hassle way to get a more polished result. Strip the wire ends, then feed the cable through the hole in the back of the box. Solder one end to the red wire, and the other to the middle section of the black wire.

That's it for wiring. With the ground wire now in place, bridging pins A2 and A3 should consistently work like pressing a space bar.

Strain Relief, Close Box

2025-11-09 18.02.32.jpg
2025-11-09 18.16.03.jpg

For strain relief and electrical insulation, I fill the centre of the box with hot glue, which pots the wiring and fixes it all in place. This is technically optional, but I doubt one of these things would last long in use without it. If you want the hot glue to grip the cable more firmly, you can also add a zip tie before splodging the glue in. Just make sure to set it back from the end of the box so it won't foul the the lid.

It's also worth making sure to leave the GND and RST pins clear of glue, because that means you could bridge them to reflash in future should you need to. The main thing I care about here is those wire-to-wire solder joints being insulated from each other.

If you want to be certain you'll be able to remove the lid later on, wait a little bit for the hot glue to form a skin before smooshing the lid down, but do make sure to do it before the glue is too firm to let the lid push all the way down. If you don't care about ever opening it again, you smoosh it immediately, maybe even modify the underside of the lid first to give it a more solid mechanical connection.

The big blob of hot glue also makes the whole thing feel more solid and brick-like. I don't super-like the non-serviceability of filling things with glue, but events beat the snot out of DIY hardware. Every other method of strain relief I considered had more likely failure modes, or would have needed a bigger box. Nearly anything I need to do with this in future, I can do over USB-C with QMK or VIA. If not, Pro Micro clones are very cheap and small, so I can make more.

Test

2025-11-13 19.50.14.jpg
2025-11-13 19.52.48.jpg

Plug it into any computer with a USB lead, then close the circuit to test. You can do it by just bridging the poles on the 3.5mm jack. I had a few ways of testing it, including a mono socket to crocodile clips, and a telegraph key I designed.

However you test or use this, bridging the two poles of the connector briefly should type one space character. Bridging it continuously should spam them. That's it! You can plug the QMKeybox into any monojack socket, and whatever that socket is connected to can act as a space bar.

Options

2025-11-13 19.56.07.jpg
2025-11-13 20.42.36.jpg
2025-10-13 21.37.26.jpg
2025-10-13 21.41.42.jpg
2025-10-13 21.42.58.jpg
2025-10-13 21.43.04.jpg
2025-10-13 21.43.39.jpg

This could all be modded to accommodate more inputs, different connectors and so on, which is why I've included source files for the firmware, and .step files for the 3D printed parts. A Pro Micro can be wired to a much bigger keyboard matrix that will handle more than a hundred keys.

There are also many other microcontrollers that are compatible with QMK keyboard firmware. I settled on the Pro Micro because it's smaller than an RP2040 Nano, a bit cheaper than a Tiny 2040, and seemed optimally sized for a very compact box… but just big enough it's hard to miss or lose.

Me and Alex often build weird installations and game controllers. We've wanted to figure out a bunch of things with USB-C for a while, and while the Pro Micro doesn't solve everything that's on our minds, QMK solves a lot of game-controller problems. VIA compatibility is a step toward solving more.

For the past few years, Alex and I have been trying to include mono jack connectors on most things we make. When you're close to a deadline, adding proper connectors feels like an easy corner to cut, but that's a false economy. We've spent far too many events and workshops nursing installations with janky breadboard wiring. Giving your work simple connectors makes it so much more robust, and also makes setup quicker. Moreover, as you build more things, using a consistent connector type will make your work modular in ways your breadboard prototypes just can't.

Alex and I will doubtless make other, more complex things based on this. We'll definitely find use cases that benefit from more complicated connectors. I designed QMKeybox to be a very simple missing link of "connect a single switch or button to a PC" though, and mono minijacks are a robust, widely available option. In many colours!

That's all you need to do, but you can optionally reprogram this in various ways if you want. The sections below cover some more detailed or advanced stuff, in order of complexity:

  1. Remapping with VIA
  2. Note on Pull-Ups, Matrices, & A Piano
  3. Compile Your Own Firmware

Remapping With VIA

Screenshot 2025-11-13 200329.png
2025-11-13 20.14.45.jpg
Screenshot 2025-11-13 200339.png
Screenshot 2025-11-13 200356.png
Screenshot 2025-11-13 200605.png
Screenshot 2025-11-13 200619.png
Screenshot 2025-11-13 200650.png
Screenshot 2025-11-13 200707.png

If you want this box to act as a different key, there's no need to mess around with firmware or flashing. You can use VIA to very quickly remap the Pro Micro. Download here: https://github.com/the-via/releases/releases/

At first, getting VIA to work does involve some non-obvious steps. VIA uses .json files to load keymaps, and once it has a valid one for the device you've plugged in, you can click any key on the keymap it shows, then click on another in the selection area to change it. That's all, as soon as you click the new key you want, the microcontroller is reprogrammed to give that output instead.


Step by step, also shown in screenshots:

  1. First, make sure your QMKeybox is plugged in (and maybe unplug any other VIA compatible devices you have to be safe).
  2. Next, you'll need to tell VIA what device it's looking for; it won't find this one automatically. You tell it that with a special .json file (QMKeybox.json, uploaded here) that lays out the keymap in a way VIA can read.
  3. Open VIA, and it will say "looking for devices". Go into the settings tab (one of the icons near the top of the window), and make sure "Show Design Tab" is enabled. If it wasn't already, you should now see a fourth icon at the top of the window, that looks like a paintbrush. That's the design tab.
  4. If the design tab already shows a line at the bottom with something like "0x12345000" next to an X, it already has a keymap loaded. Click the X to clear that, then drag and drop QMKeybox.json to load the right one.
  5. Now click the keyboard icon ("CONFIGURE"), and you'll see a single key, labelled "space". Click it, then click any other key in the window below, and your little box is instantly reprogrammed to give that key output instead. That's it! No need to manually upload, reflash, or save anything.

If you choose to compile your own firmware based on QMKeybox, you might also need to write a new .json file for VIA compatibility. I'm sorry to say that might cause you some hair-pulling. The present docs for VIA are mainly reference for people who already know what they're doing, rather than guides or tutorials. They provide no simple examples or templates. I had to piece it all together from various forum and reddit posts.


The .json standard for VIA is also quite poorly documented, and exasperatingly, the docs and many posters also point people to .json validators which will validate .json with features that VIA rejects. On top of invalid and valid .json, this creates a wonderful third category: invalid-valid .json. It's validity is a superposition until you try feeding it to VIA. There seems to be nothing documenting or listing the invalid features, and the only examples I could find were enormous keymaps rather than simple, smaller ones. VIA does give error messages when you try to load an invalid .json file, but they can't be copy-pasted, and don't have line numbers. Grrr!

In my opinion, many docs for software (open source or related DIY projects) fall short in similar ways: loads of microscopic detail, but almost nothing in the way of overviews or entry points for newbies. Hopefully what I've written here helps others like me. To be fair, the typical shortcomings of open source documentation are still a lot better than the tech industry special move: "startup where the marketing team also writes the docs".

Downloads

Note on Pull-Ups, Matrices, & a Piano

2025-11-06 15.40.55.jpg
DOOM_PIANO_IMG_1742_EDIT.jpg
2013-09-25 20.08.17-1280.jpg
IMG_1753.jpg
IMG_1748.jpg

If you're not familiar with terms like pull-up and pull-down, I'm not the person to explain them in detail but can give you an abstract. Basically, in any given moment the little microcontroller chip reads its input pins as HIGH (receiving electricity) or LOW (not receiving electricity). That's how it knows things like "a button is being pressed" (philosophers, don't @ me).

Depending on what things you connect to those pins and how they're connected though, you might end up with excess electrons floating around, making the microcontroller read a pin as high when it's supposed to be low, or vice versa.

During prototyping, I found a very basic breadboard setup and just touching jumper wires to each other worked fine without a ground wire to A3. As soon as it got more cabling though, such as extra inline sockets or terminal blocks, it would develop problems. Instead of sending "space" on each button push, whenever it was connected it was continuously screaming "SPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACE" (linguists and Unicode Consortium don't @ me).

At first, after asking my friend Angus' advice, I added an external pull-up resistor (a 10K resistor between VCC and pin A2) as well as connecting A3 to ground, which fixed it. I subsequently realised the resistor was unnecessary though, because on digging deeper I found the ATMega32U4 has internal pull-up resistors. As far as I can tell, recent versions of QMK enable those by default, though the docs and forum posts on this are murky. Whatever the case there, for QMKeybox connecting A3 and GND seems to reliably eliminate any floating voltage that could accidentally set a pin high.

If you've done any of the basic introductory microcontroller stuff like making an LED blink, it should be obvious that one button or switch per input pin is an easy thing to do. One switch contact goes to the input pin, the other to ground. Pressing the button completes the circuit, letting electricity through, making that input pin high. IPAC boards, typically used for DIY arcade machines, are a really good option for this sort of wiring. They come with software already installed, have many separate inputs with screw terminals, and are clearly labelled to correspond to the keyboard output they'll send. As you add more buttons though, the wiring can get incredibly messy.

The screw terminals make IPAC setups quite robust, which is why they're so good for arcade machines. They're also convenient for a lot of game controller projects, but expensive too and a bit overkill when they only have a handful of buttons. For some rare controller projects, one IPAC isn't enough. For instance, at the time we built the DOOM Piano we needed two IPAC2s to wire up all 88 keys: https://www.youtube.com/watch?v=sJu997jwBcA

Keyboards can have more than a hundred keys, which far outnumbers the available pins on most microcontrollers. For various reasons, including the fact they have much less internal space than an upright piano, computer keyboards tend to do clever things with a smaller number of pins. The pins are arranged into matrices, and the controller then polls them in sequence to see which are low and which are high. The values of all those outputs combined tells the controller exactly which keys are being pressed.

What I read in mechanical keyboard communities seemed to indicate that pull-up and pull-down resistors might not be necessary for most keyboard matrices if the microcontroller can just take care of it, but they do often seem to be a problem for people making split keyboards. One half has the main microcontroller with internal pull-ups, but the other doesn't and might need physical resistors added. I read some heartbreaking posts of people having to rip handwired prototypes apart then redesign CAD models and PCBs to accommodate pull-ups. Bear that in mind if you plan to modify QMKeybox into anything more complex or modular.

Compile Your Own Firmware

Screenshot 2025-11-13 201954.png
Screenshot 2025-11-13 202029.png
Screenshot 2025-11-13 202059.png
Screenshot 2025-11-13 202242.png
Screenshot 2025-11-13 202309.png

You can find all of the source files for this project at: https://github.com/nachimir/QMKeybox/

You'll need an application called QMK.MSYS to compile your own firmware (download at https://msys.qmk.fm/). There are other methods too, but QMK.MSYS on a Windows box looked best to me.

Setting it up will require you get comfortable with the command line. There are also a few stumbling blocks in terms of the home directory it works from. In my case, it did not configure itself nicely by default, and I spent a while bouncing off that. It kept saying that certain files or paths didn't exist whenever I tried to compile anything. I then found some out of date forum posts that gave a wrong method for setting the home directory, before finally getting it to work. Your development environment will be different to mine though, so: godspeed. Hopefully you just don't have those problems.

There are some docs here: https://msys.qmk.fm/guide

Here though is the very brief introductory overview of QMK firmware I could have done with:

QMK compiles firmware, in the form of a .hex file, from a selection of files, which must be laid out in a specific folder structure. Those files tell QMK things like what platform it's being compiled for, what size keyboard matrix the hardware has, how that's set up, what default key mappings it should have, what the keyboard is named, who made it, and dictates various other things you might want the firmware to do. That's all done via .json, C code and text, spread through various different files. The files are all plaintext, just with different extensions, and can be edited with anything like TextMate or Notepad++.

The command qmk new-keyboard should create the files and folder structure you need, but just in case, as of November 2025, the things you'll need in those folders are:

ROOT FOLDER: name this after your keyboard, so in the case of this project I went with "qmkeybox". Note that uppercase letters are not allowed. Lowercase and underscores are. In that folder, you need these files:

  1. config.h
  2. keyboard.json
  3. rules.mk
  4. FOLDER: keymaps

In the keymaps folder, add another folder titled "default", and if you want to support VIA, a second named "via". In those:

default:

  1. keymap.c

via:

  1. keymap.c
  2. rules.mk

The rules.mk file in the via folder only needs one line:

VIA_ENABLE = yes

You might be able to find a similar one in the hundreds of firmware source folders that QMK.MSYS ships with, then make a copy of that to work from.

It took me a day to go from knowing almost nothing about QMK to installing all the tools, reading up on things, then successfully compiling the QMKeybox firmware. In terms of prior experience, I'm not a programmer and don't use terminals/command lines much, though nowadays I am comfortable installing software using a terminal. I'd never edited or compiled firmware for anything before this though.

Annoyingly, I found there have been different standards for the files QMK compiles from, and the docs don't seem to be up to date. The current standard uses a file named "keyboard.json". The older standard, which seems to be the only one mentioned in QMK docs, was to name that file "info.json". I found that confusing until I dug up a reddit post where someone mentioned it.

In future, I'm likely to make variants of QMKeybox for other projects, probably with a few more inputs. When I do, if they don't deserve their own write-up I'll at least make sure to add relevant files and show them here.