Using Keybow to build custom keyboard functions
Published on under the Keyboards category.

A few weeks ago I came across the Keybow, a small mechanical keyboard developed by Pimoroni that is powered by the Raspberry Pi Zero. After doing some digging, I realised that the Keybow was designed to be coded, meaning I could create my own custom keyboard functions using this device. I let the keyboard sit in the back of my mind for a few weeks until earlier this week when I decided that I was going to take the leap and give the Keybow a try.
Assembling the Keybow
When the Keybow arrived earlier today, I was surprised by the fact I had to assemble the keyboard before being able to program it. I only checked that the keyboard required no soldering—as many electronics products doo—before use, not whether any assembly was necessary. However, the amount of assembly was minimal and after about half an hour I was able to put the Keybow together.
The biggest challenge was getting the key switches on correctly. I accidentally positioned them the wrong way, as I realised when I went to push the board with all the switches attached onto the Keybow PCB board connected to the Pi Zero. To solve the issue, I had to take all of the switches out of the board in which they were rested and rotate them. This did not take too much time but it was a bit of a pain to do as the switches have metal pieces that were to connect to the board below. I had to be careful not to push onto the metal with my fingers when removing the switches from the case. After a few minutes, I was able to rotate the switches and continue with the build.
My advice to anyone building the Keybow is this: make sure that the switches align before you put all twelve into the board. If you put the switches in the wrong way like I did, you will have to spend at least a few minutes taking them all out again and putting them back in the right way.
After the switches and the keycaps were on, I was ready to continue with this project.
Here is a photo of the Keybow keyboard, fully assembled (showcasing the lights that I programmed later):
The software
The Keybow is powered by a special operating system that can fit on a small SD card. This was convenient because I only had an 8 GB SD card to spare for this project. The operating system is minimal and runs Lua code. As a result, to use the Keybow beyond the default configuration, you must write some Lua code. I have never written a line of Lua code before working on this project but there was plenty of helpful code already bundled with the operating system that I could use. And if I didn't know something—which was the case on many occasions—I just went to Google and looked for a solution.
To customise the Keybow, you must connect your SD card with the Keybow operating system to your computer and then modify the appropriate files. Pimoroni has a great series of tutorials that outline how to work with the Keybow. One of their tutorials goes into detail on how to write your own custom macros which I found useful as I wanted to write a few.
For this project, I decided that I wanted one key that muted my Zoom and another key that took me out of a Zoom meeting. The latter was to replace a red button which is attached to my Raspberry Pi that I have been using to leave my Zoom meetings for the last few weeks. While this button is practical and within easy reach on my desk, I sometimes forget to enable the script that powers it so I need to manually leave my meetings on Zoom.
To support these functions, I wrote some Lua code:
require "keybow"
muted = false
—this code lets me press multiple keys at once (use a keyboard shortcut)
—the modifier function is copied from one of the keyboard snippets included with the Keybow OS
function modifier(key, ...)
for i = 1, select('#', ...) do
local j = select(i, ...)
keybow.set_modifier(j, keybow.KEY_DOWN)
end
keybow.tap_key(key)
for i = 1, select('#', ...) do
local j = select(i, ...)
keybow.set_modifier(j, keybow.KEY_UP)
end
end
—end zoom meeting
function handle_key_00(pressed)
if pressed then
modifier("q", keybow.LEFT_ALT)
reset_keys()
keybow.tap_enter()
end
end
—mute zoom meeting
function handle_key_01(pressed)
if pressed then
modifier("a", keybow.LEFT_ALT)
if muted == false then
for i=0,11 do
keybow.set_pixel(i, 255, 0, 0)
end
muted = true
else
for i=0,11 do
keybow.set_pixel(i, 0, 255, 0)
end
muted = false
end
end
end
You can view this code on GitHub Gists too.
The functions are all named after the "index" position assigned to each key on the keypad. These index positions let you identify each button. Button 0, the one that is in the bottom left of the keypad, lets me quit Zoom. This code presses Alt+Q on my keyboard and then enter, the key sequences necessary to leave Zoom. Button 01, the middle button on the bottom row of the keypad, lets me mute and unmute my microphone. If I press this key, I mute my microphone and all keys turn red to indicate I am muted. If I press the key again, all keys turn green to indicate I am not muted.
This code took quite a bit of time to write because I am not familiar with the Lua syntax. I had to use Google a lot and I don't have my head around quite a bit of the syntax. However, I have definitely learned a bit about Lua from this project and I know how the code I have written works.
Every time you want to update the keyboard, you need to turn the Keybow off, plug in your SD Card into your computer, modify the Lua code, and then put the SD card back into the Keybow. I do not mind this process because I do not expect I will need to update the Keybow often.
Expanding the keyboard functionality
My ambitions for this project grew after I got the two functions above working. I then decided to write functions to:
- Print my daily update on my thermal printer.
- Take a screenshot (using the drag screenshot rather than the whole print screen so I can select parts of the page in my screenshot).
- Turn the volume off or on (this one is still in progress).
- Copy highlighted text.
- Paste text on my clipboard.
- Open my blog in a web browser.
I now have eight keys used up in total, with another four still left to program. I don't have any other ideas in mind for now. I still have to tetst some of the code for the six functions in the bullet point list above. However, most of my code works. I might look through some of the examples that come with the Keybow for inspiration.
If you are wondering how I can open my blog in a web browser or print a daily update on my thermal printer from the Keybow, that's a great question. To do this, I have written code that lets me open a terminal and insert a command. I have a command that prints a daily update and I can use the "open" command (not included by default on Ubuntu, but you can download "xdg-open" to get this functionality) to open a web page from the terminal.
Here is the code that lets me open my blog by pressing a key on the Keybow:
function handle_key_04(pressed)
if pressed then
modifier("t", keybow.LEFT_ALT, keybow.LEFT_CTRL)
keybow.sleep(1000)
keybow.text("open https://jamesg.blog && exit")
keybow.tap_enter()
reset_keys()
keybow.sleep(3000)
setup()
end
end
Alt+Control+T let me open a terminal. I then wait 1 second (1000 milliseconds) so that the computer has enough time to process the terminal opening. I then use the open command to open my blog and the "&& exit" syntax to quit the terminal as soon as the code has executed.
Wrapping up
Building and then writing macros code for the Keybow was an excellent challenge. While I have not done many hardware projects, I did not think the Keybow was too difficult to assemble. Writing code for the Keybow took a bit of time because I am not familiar with Lua but I was able to achieve what I wanted to do. I am looking forward to trying out these commands in my day-to-day life. I expect almost if not all of the keyboard commands that are part of my Keybow to be used regularly. If you're looking for a mechanical keyboard you can code—and don't mind doing a bit of assembly and Lua coding—I'd recommend checking out the Keybow by Pimoroni.
Tagged in python.
Responses
Comment on this post
Respond to this post by sending a Webmention.
Have a comment? Email me at readers@jamesg.blog.