โ† Back to list

Add a Touch of Magic to Your Desk ๐Ÿช„โŒจ๏ธ

Adafruit PyRuler as a Customizable Hotkey Keyboard!

Enrique Gamboa ยท 2023-05-26 18:17 ยท 0 claps ยท 5.6 min read
#adafruit #pyruler #circuitpython #iot #hotkeys
Open on Medium โ†—
Wiki topics: ๐Ÿ“Ÿ ยท Gadgets & IoT

Add a Touch of Magic to Your Desk ๐Ÿช„โŒจ๏ธ

Adafruit PyRuler as a Customizable Hotkey Keyboard!

Adafruit PyRuler โ€” Hotkey Zoom keyboard map

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

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:

  • Adafruit PyRuler: Link
  • Github repo: Link

So, without further ado, letโ€™s get started! ๐Ÿš€

[embed]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

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

https://www.buymeacoffee.com/jegamboafuentes


๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
post_id
9b7bb30a25a0
slug
add-a-touch-of-magic-to-your-desk-๏ธ-9b7bb30a25a0
url
https://medium.com/@jegamboafuentes/add-a-touch-of-magic-to-your-desk-%EF%B8%8F-9b7bb30a25a0
canonical_url
https://medium.com/@jegamboafuentes/add-a-touch-of-magic-to-your-desk-%EF%B8%8F-9b7bb30a25a0
author_url
https://medium.com/@jegamboafuentes
status
ok
fetched_at
2026-08-09 08:35:07