Add a Touch of Magic to Your Desk 🪄⌨️

Enrique Gamboa
6 min readMay 26, 2023

--

Adafruit PyRuler as a Customizable Hotkey Keyboard!

Adafruit PyRuler — Hotkey Zoom keyboard map

Hello, fellow innovators! 👋💡

Ever wished for a magic wand to instantly control your PC’s volume or silence your microphone during a Zoom call? Well, your wish is granted! 🧞‍♂️✨

Today, I’m thrilled to share how I turned my Adafruit PyRuler into an uber-cool, handy-dandy hotkey keyboard! It’s my very own magic wand that makes my digital world a breeze to navigate. And guess what? You can weave this magic too! 🪄💫

PyRuler working as Hotkey keyboard for Zoom

Before we dive in, let’s talk about the star of our show today — the Adafruit PyRuler. It’s a compact, versatile device that combines the features of a trinket M0 with handy touch pads and an array of LEDs. Best of all, it’s programmable with CircuitPython 🐍, making it a fantastic platform for all sorts of creative projects. 🌟💡

If you are interested in doing your own:

So, without further ado, let’s get started! 🚀

PyRuler — Zoom hotkey demo

The Secret Sauce: The Code 🤫🍝

This code is the secret recipe that brings the PyRuler to life! Here’s a little sneak peek into what it does:

  1. Setting the Stage: The code first prepares the PyRuler, initializing the touchpads, LEDs, and the DotStar LED.
  2. Detecting Touch: In the read_caps() function, it checks if any of the touch pads have been tapped.
  3. Reacting to Touch: In the infinite loop, the code checks if a touch pad has been pressed. If so, it sends a particular command to the computer, like lowering the volume when the first pad is touched.
import os
import board
from digitalio import DigitalInOut, Direction
import time
import touchio
import busio
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode

# Set this to True to turn the touchpads into a keyboard
ENABLE_KEYBOARD = True

WINDOWS = "W"
MAC = "M"
LINUX = "L" # and Chrome OS

# Set your computer type to one of the above
OS = WINDOWS

# Used if we do HID output, see below
if ENABLE_KEYBOARD:
kbd = Keyboard()
layout = KeyboardLayoutUS(kbd)

led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT

touches = [DigitalInOut(board.CAP0)]
for p in (board.CAP1, board.CAP2, board.CAP3):
touches.append(touchio.TouchIn(p))

leds = []
for p in (board.LED4, board.LED5, board.LED6, board.LED7):
led = DigitalInOut(p)
led.direction = Direction.OUTPUT
led.value = True
time.sleep(0.25)
leds.append(led)
for led in leds:
led.value = False

cap_touches = [False, False, False, False]

# Setup SPI for DotStar
spi = busio.SPI(board.APA102_SCK, MOSI=board.APA102_MOSI)
while not spi.try_lock():
pass
spi.configure(baudrate=4000000)

# Create a bytearray to store the frame
frame = bytearray(12)
# Start frame is all zeros
frame[0:4] = bytes([0, 0, 0, 0])
# LED frame starts with 111 (brightness control) and ends with the RGB values
frame[4:8] = bytes([0xFF, 0, 0, 0])
# End frame is all ones
frame[8:12] = bytes([0xFF, 0xFF, 0xFF, 0xFF])
# Send the frame to the DotStar LED
spi.write(frame)
# Unlock the SPI now that we're done
spi.unlock()

# ... Rest of your code ...
def read_caps():
t0_count = 0
t0 = touches[0]
t0.direction = Direction.OUTPUT
t0.value = True
t0.direction = Direction.INPUT
# funky idea but we can 'diy' the one non-hardware captouch device by hand
# by reading the drooping voltage on a tri-state pin.
t0_count = t0.value + t0.value + t0.value + t0.value + t0.value + \
t0.value + t0.value + t0.value + t0.value + t0.value + \
t0.value + t0.value + t0.value + t0.value + t0.value
cap_touches[0] = t0_count > 2
cap_touches[1] = touches[1].raw_value > 3000
cap_touches[2] = touches[2].raw_value > 3000
cap_touches[3] = touches[3].raw_value > 3000
return cap_touches

def type_alt_code(code):
kbd.press(Keycode.ALT)
for c in str(code):
if c == '0':
keycode = Keycode.KEYPAD_ZERO
elif '1' <= c <= '9':
keycode = Keycode.KEYPAD_ONE + ord(c) - ord('1')
else:
raise RuntimeError("Only number codes permitted!")
kbd.press(keycode)
kbd.release(keycode)
kbd.release_all()

cc = ConsumerControl()

while True:
caps = read_caps()
print(caps)
# light up the matching LED
for i,c in enumerate(caps):
leds[i].value = c
if caps[0]:
if ENABLE_KEYBOARD:
if OS == WINDOWS:
#type_alt_code(234)
#type_alt_code(129297)
cc.send(ConsumerControlCode.VOLUME_DECREMENT)
elif OS == MAC:
kbd.send(Keycode.ALT, Keycode.Z)
elif OS == LINUX:
kbd.press(Keycode.CONTROL, Keycode.SHIFT)
kbd.press(Keycode.U)
kbd.release_all()
kbd.send(Keycode.TWO)
kbd.send(Keycode.ONE)
kbd.send(Keycode.TWO)
kbd.send(Keycode.SIX)
kbd.send(Keycode.ENTER)
if caps[1]:
if ENABLE_KEYBOARD:
if OS == WINDOWS:
#type_alt_code(230)
cc.send(ConsumerControlCode.VOLUME_INCREMENT)
elif OS == MAC:
kbd.send(Keycode.ALT, Keycode.M)
elif OS == LINUX:
kbd.press(Keycode.CONTROL, Keycode.SHIFT)
kbd.press(Keycode.U)
kbd.release_all()
kbd.send(Keycode.ZERO)
kbd.send(Keycode.THREE)
kbd.send(Keycode.B)
kbd.send(Keycode.C)
kbd.send(Keycode.ENTER)
if caps[2]:
if ENABLE_KEYBOARD:
if OS == WINDOWS:
#type_alt_code(227)
cc.send(ConsumerControlCode.MUTE)
elif OS == MAC:
kbd.send(Keycode.ALT, Keycode.P)
elif OS == LINUX:
kbd.press(Keycode.CONTROL, Keycode.SHIFT)
kbd.press(Keycode.U)
kbd.release_all()
kbd.send(Keycode.ZERO)
kbd.send(Keycode.THREE)
kbd.send(Keycode.C)
kbd.send(Keycode.ZERO)
kbd.send(Keycode.ENTER)
if caps[3]:
if ENABLE_KEYBOARD:
kbd.send(Keycode.ALT, Keycode.A)
#layout.write('https://www.digikey.com/python\n')
#layout.write('metaverseprofessional.tech')
time.sleep(0.1)

Currently, the code is configured for Windows, but with a little tinkering, you can make it work for Mac or Linux as well.

Adafruit PyRuler board

Putting Your Stamp on It 🎨🔖

Customization is where the fun begins! 🎉You have the power to configure your Adafruit PyRuler to execute specific tasks that best suit your needs. Want a hotkey to pause your Spotify jam? Or how about a shortcut to open your favorite coding forum? All you need to do is tweak the code. Here’s how you can do that:

How to Add Your Own Hotkeys

Let’s look at the main section of the code where the magic happens:

while True:
caps = read_caps()
print(caps)
# light up the matching LED
for i,c in enumerate(caps):
leds[i].value = c
if caps[0]:
if ENABLE_KEYBOARD:
# ... Your code for the first pad ...
if caps[1]:
if ENABLE_KEYBOARD:
# ... Your code for the second pad ...
if caps[2]:
if ENABLE_KEYBOARD:
# ... Your code for the third pad ...
if caps[3]:
if ENABLE_KEYBOARD:
# ... Your code for the fourth pad ...
time.sleep(0.1)

This code is constantly checking whether any of the four touch pads (indexed from 0 to 3) on the PyRuler have been touched. If a pad is touched, it executes the corresponding block of code.

You can customize each touch pad’s functionality by modifying the respective code block. Let’s take a look at how you could do this with some examples.

Example 1: Open a Website

Suppose you want the fourth touch pad (indexed as 3) to open your favorite website when touched. You could do so by sending a sequence of keystrokes to open a new browser window and navigate to the URL. Here’s an example for Windows, where the combination Win + R opens the Run dialog, and typing a URL and hitting Enter opens that URL in the default browser:

if caps[3]:
if ENABLE_KEYBOARD:
kbd.send(Keycode.GUI, Keycode.R) # Win + R
time.sleep(0.1) # Give the Run dialog a moment to open
layout.write('http://metaverseprofessional.tech') # Type URL and hit Enter

Replace 'http://metaverseprofessional.tech' with your desired URL.

Example 2: Play/Pause Media

Say you want the first touch pad (indexed as 0) to play or pause media playback on your computer. On Windows, the media play/pause function can be triggered with the ConsumerControlCode.PLAY_PAUSE command:

if caps[0]:
if ENABLE_KEYBOARD:
cc.send(ConsumerControlCode.PLAY_PAUSE)

Remember that the Adafruit PyRuler has four capacitive touch pads, which means you can set up to four hotkeys. Choose wisely and make your PyRuler the ultimate productivity tool

Ready to Wave Your Magic Wand? 🎩🐇

The Adafruit PyRuler is not just a fun gadget; it’s a doorway to the thrilling world of Python and hardware. So why not step through?

I’d love to hear about your own magical transformations of the PyRuler in the comments below 🧙‍♀️.

Until next time 🌟👋

References:

  1. Adafruit Industries. (n.d.). Adafruit PyRuler: Video Panic. Learn Adafruit. Retrieved May 26, 2023, from https://learn.adafruit.com/PyRulerVideoPanic/overview
  2. Adafruit Industries. (2023). Adafruit_Learning_System_Guides. GitHub. Retrieved May 26, 2023, from https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/main
  3. Adafruit Industries. (n.d.). Adafruit PyRuler — Engineer Reference Ruler with CircuitPython. Adafruit. Retrieved May 26, 2023, from https://www.adafruit.com/product/4319
https://www.buymeacoffee.com/jegamboafuentes

--

--

Enrique Gamboa
Enrique Gamboa

Written by Enrique Gamboa

If art is a human abstraction, Artificial Intelligence is the abstraction of humanity 🦾

No responses yet