<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[USB Keyboard with Raspberry Pi Pico for Isadora 4 - Complete Tutorial]]></title><description><![CDATA[<p></p><h1>DIY USB Keyboard with Raspberry Pi Pico for Isadora 4 - Complete Tutorial</h1>
<p><strong>Build a custom 20-key USB keyboard using a Raspberry Pi Pico and CircuitPython - perfect for triggering scenes, cues, and effects in Isadora!</strong></p>
<h2>🎯 <strong>What This Project Does</strong></h2>
<p>This tutorial shows you how to transform a $4 Raspberry Pi Pico into a fully functional USB keyboard with 20 customizable keys. The keyboard sends the first 20 letters of the alphabet (a-t) and works seamlessly with Isadora 4 for triggering scenes, controlling parameters, or any other keyboard shortcuts you need.</p>
<p><strong>Key Features:</strong></p>
<ul>
<li>✅ 20 programmable keys (easily expandable)</li>
<li>✅ Plug-and-play USB HID device (no drivers needed)</li>
<li>✅ Visual feedback with onboard LED</li>
<li>✅ Robust error handling and debugging</li>
<li>✅ Works with any computer (Windows, Mac, Linux)</li>
<li>✅ Perfect for live performance setups</li>
</ul>
<h2>🛠 <strong>Hardware Requirements</strong></h2>
<ul>
<li><strong>Raspberry Pi Pico</strong> (any variant: Pico, Pico W, Pico 2) - ~$4</li>
<li><strong>20x Push buttons/momentary switches</strong> - any normally-open type</li>
<li><strong>Breadboard or perfboard</strong> for connections</li>
<li><strong>Jumper wires</strong></li>
<li><strong>USB cable</strong> (data-capable, not charge-only!)</li>
</ul>
<p><strong>Total cost: Under $15!</strong></p>
<h2>🔌 <strong>Wiring Diagram</strong></h2>
<p>The wiring is incredibly simple - no resistors needed!</p>
<pre>
GP0  ←→ Button ←→ GND    (sends 'a')
GP1  ←→ Button ←→ GND    (sends 'b')
GP2  ←→ Button ←→ GND    (sends 'c')
...
GP19 ←→ Button ←→ GND    (sends 't')
</pre>
<p><strong>Important:</strong> Each button connects between a GPIO pin and any GND pin. The Pico's internal pull-up resistors handle the rest!</p>
<h2>📥 <strong>Software Installation</strong></h2>
<h3>Step 1: Install CircuitPython</h3>
<ol>
<li>
<p><strong>Download CircuitPython firmware:</strong></p>
<ul>
<li>For <strong>Pico</strong>: <a href="https://circuitpython.org/board/raspberry_pi_pico/">https://circuitpython.org/boar...</a></li>
<li>For <strong>Pico W</strong>: <a href="https://circuitpython.org/board/raspberry_pi_pico_w/">https://circuitpython.org/boar...</a></li>
<li>For <strong>Pico 2</strong>: <a href="https://circuitpython.org/board/raspberry_pi_pico2/">https://circuitpython.org/boar...</a></li>
</ul>
</li>
<li>
<p><strong>Install firmware:</strong></p>
<ul>
<li>Hold BOOTSEL button on Pico</li>
<li>Connect USB cable (keep BOOTSEL pressed)</li>
<li>Release BOOTSEL → "RPI-RP2" drive appears</li>
<li>Drag the downloaded .UF2 file to RPI-RP2</li>
<li>Drive disappears and "CIRCUITPY" appears</li>
</ul>
</li>
</ol>
<h3>Step 2: Install Required Library</h3>
<ol>
<li>
<p><strong>Download the library bundle:</strong></p>
<ul>
<li>Go to: <a href="https://circuitpython.org/libraries">https://circuitpython.org/libr...</a></li>
<li>Download the bundle matching your CircuitPython version</li>
</ul>
</li>
<li>
<p><strong>Install adafruit_hid:</strong></p>
<ul>
<li>Extract the downloaded ZIP file</li>
<li>Copy the <code>adafruit_hid</code> folder from the bundle's <code>lib</code> directory</li>
<li>Paste it into the <code>lib</code> folder on your CIRCUITPY drive</li>
</ul>
</li>
</ol>
<p>Your CIRCUITPY drive should look like:</p>
<pre>
CIRCUITPY/
├── code.py
└── lib/    └── adafruit_hid/        ├── __init__.py        ├── keyboard.py        ├── keycode.py        └── ...
</pre>
<h2>💻 <strong>The Complete Code</strong></h2>
<p>Save this as <code>code.py</code> on your CIRCUITPY drive:</p>
<pre>
"""
Raspberry Pi Pico USB Keyboard Emulator for Isadora 4
======================================================
FUNCTION:
---------
This program transforms the Raspberry Pi Pico into a USB keyboard with 20 keys.
The keys correspond to the first 20 lowercase letters of the alphabet (a-t).
The onboard LED lights up briefly with each key press for visual feedback.
HARDWARE WIRING:
---------------
Each button is connected between a GPIO pin and GND (Ground):
GP0  &lt;-&gt; Button &lt;-&gt; GND   (sends 'a')
GP1  &lt;-&gt; Button &lt;-&gt; GND   (sends 'b')
GP2  &lt;-&gt; Button &lt;-&gt; GND   (sends 'c')
...
GP19 &lt;-&gt; Button &lt;-&gt; GND   (sends 't')
IMPORTANT NOTES:
---------------
- No external pull-up resistors needed (internal pull-ups are enabled)
- Use simple momentary switches/buttons between pin and GND
- Onboard LED shows every key press
- Debouncing is already implemented
- Only works with CircuitPython (not standard MicroPython)
INSTALLATION:
------------
1. Install CircuitPython on Pi Pico
2. Copy adafruit_hid library to lib/ folder
3. Save this code as code.py
AUTHOR: Pi Pico Keyboard Project for Isadora
VERSION: 1.1 (with LED feedback and robust error handling)
"""
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import time
# Error handling for USB HID initialization
try:    kbd = Keyboard(usb_hid.devices)    print("✓ USB HID Keyboard successfully initialized")
except Exception as e:    print(f"✗ ERROR initializing USB keyboard: {e}")    print("Make sure CircuitPython is properly installed!")    raise
# Initialize onboard LED
try:    led = digitalio.DigitalInOut(board.LED)    led.direction = digitalio.Direction.OUTPUT    led.value = False  # LED off    print("✓ Onboard LED initialized")
except Exception as e:    print(f"✗ ERROR initializing LED: {e}")    led = None  # Disable LED if error occurs
# GPIO pins for the 20 buttons and their states
button_pins = []
button_states = []
button_last_states = []
# First 20 lowercase letters of the alphabet (a-t)
keycodes = [    Keycode.A, Keycode.B, Keycode.C, Keycode.D, Keycode.E,    Keycode.F, Keycode.G, Keycode.H, Keycode.I, Keycode.J,    Keycode.K, Keycode.L, Keycode.M, Keycode.N, Keycode.O,    Keycode.P, Keycode.Q, Keycode.R, Keycode.S, Keycode.T
]
# Configure GPIO pins (GP0-GP19)
print("Initializing GPIO pins...")
pin_numbers = list(range(20))
failed_pins = []
for i, pin_num in enumerate(pin_numbers):    try:        # Configure pin as input with pull-up resistor        pin = digitalio.DigitalInOut(getattr(board, f'GP{pin_num}'))        pin.direction = digitalio.Direction.INPUT        pin.pull = digitalio.Pull.UP                button_pins.append(pin)        button_states.append(False)        button_last_states.append(True)  # Pull-up: not pressed = True            except Exception as e:        print(f"✗ ERROR with pin GP{pin_num}: {e}")        failed_pins.append(pin_num)        # Placeholder for failed pins        button_pins.append(None)        button_states.append(False)        button_last_states.append(True)
if failed_pins:    print(f"⚠ Warning: Pins {failed_pins} could not be initialized")
else:    print("✓ All 20 GPIO pins successfully configured")
# LED feedback configuration
LED_ON_TIME = 0.1  # LED lights up for 100ms on key press
led_off_time = 0
print("\n" + "="*50)
print("🎹 USB KEYBOARD READY!")
print("="*50)
print("Key mapping:")
for i in range(20):    char = chr(ord('a') + i)    if i &lt; len(failed_pins) and pin_numbers[i] in failed_pins:        print(f"  GP{i:2d} -&gt; '{char}' (ERROR)")    else:        print(f"  GP{i:2d} -&gt; '{char}'")
print("\nConnect buttons between GPx and GND")
print("Onboard LED shows each key press")
print("="*50)
# Main loop with robust error handling
try:    while True:        current_time = time.monotonic()                # Automatically turn off LED after defined time        if led and led.value and current_time &gt;= led_off_time:            led.value = False                # Scan all available buttons        for i in range(20):            # Skip pin if initialization failed            if button_pins[i] is None:                continue                            try:                # Read current pin state (Pull-up: LOW = pressed)                current_state = not button_pins[i].value                last_state = button_states[i]                                # Button was pressed (edge from LOW to HIGH)                if current_state and not last_state:                    char = chr(ord('a') + i)                                        # Send key press                    kbd.send(keycodes[i])                    print(f"🔤 Key '{char}' pressed (GP{i})")                                        # Turn on LED with timer                    if led:                        led.value = True                        led_off_time = current_time + LED_ON_TIME                                        button_states[i] = True                                    # Button was released (edge from HIGH to LOW)                elif not current_state and last_state:                    char = chr(ord('a') + i)                    print(f"   Key '{char}' released")                    button_states[i] = False                                except Exception as e:                print(f"✗ ERROR reading GP{i}: {e}")                # Mark pin as faulty                button_pins[i] = None                # Short pause for debouncing and CPU relief        time.sleep(0.005)  # 5ms - good balance between responsiveness and debouncing
except KeyboardInterrupt:    print("\n🛑 Program terminated by user")    if led:        led.value = False        except Exception as e:    print(f"\n💥 UNEXPECTED ERROR: {e}")    print("Restart required...")    if led:        led.value = False    raise    finally:    # Cleanup: turn off LED    if led:        led.value = False    print("🔧 Cleanup completed")
</pre>
<h2>🎭 <strong>Using with Isadora 4</strong></h2>
<p>Once connected, your Pico keyboard works like any standard keyboard:</p>
<ol>
<li><strong>Scene Triggers:</strong> Assign keys a-t to trigger different scenes</li>
<li><strong>Parameter Control:</strong> Use keyboard shortcuts to control actor parameters</li>
<li><strong>Cue Sequences:</strong> Create complex cue sequences triggered by your custom keys</li>
<li><strong>Live Performance:</strong> Perfect for hands-on control during performances</li>
</ol>
<p><strong>Tip:</strong> You can easily modify the <code>keycodes</code> array in the code to send different keys, function keys, or even key combinations!</p>
<h2><span></span></h2>]]></description><link>https://community.troikatronix.com/topic/9237/usb-keyboard-with-raspberry-pi-pico-for-isadora-4-complete-tutorial</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 05:09:15 GMT</lastBuildDate><atom:link href="https://community.troikatronix.com/topic/9237.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 01 Jun 2025 08:39:22 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to USB Keyboard with Raspberry Pi Pico for Isadora 4 - Complete Tutorial on Sun, 01 Jun 2025 23:58:34 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://community.troikatronix.com/uid/7621">@konrad</a></p><p>It'd be awesome if you could upload this to our <a href="https://troikatronix.com/add-ons/" target="_blank">Add-Ons Page</a>.</p><p>Cool stuff like this eventually gets buried in the forum.</p>]]></description><link>https://community.troikatronix.com/post/56402</link><guid isPermaLink="true">https://community.troikatronix.com/post/56402</guid><dc:creator><![CDATA[Woland]]></dc:creator><pubDate>Sun, 01 Jun 2025 23:58:34 GMT</pubDate></item></channel></rss>