• Products
    • Isadora
    • Get It
    • ADD-ONS
    • IzzyCast
    • Get It
  • Forum
  • Help
  • Werkstatt
  • Newsletter
  • Impressum
  • Dsgvo
  • Press
  • Isadora
  • Get It
  • ADD-ONS
  • IzzyCast
  • Get It
  • Press
  • Dsgvo
  • Impressum

Navigation

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Tags

    USB Keyboard with Raspberry Pi Pico for Isadora 4 - Complete Tutorial

    Interfacing
    2
    2
    75
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • K
      Konrad last edited by

      DIY USB Keyboard with Raspberry Pi Pico for Isadora 4 - Complete Tutorial

      Build a custom 20-key USB keyboard using a Raspberry Pi Pico and CircuitPython - perfect for triggering scenes, cues, and effects in Isadora!

      šŸŽÆ What This Project Does

      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.

      Key Features:

      • āœ… 20 programmable keys (easily expandable)
      • āœ… Plug-and-play USB HID device (no drivers needed)
      • āœ… Visual feedback with onboard LED
      • āœ… Robust error handling and debugging
      • āœ… Works with any computer (Windows, Mac, Linux)
      • āœ… Perfect for live performance setups

      šŸ›  Hardware Requirements

      • Raspberry Pi Pico (any variant: Pico, Pico W, Pico 2) - ~$4
      • 20x Push buttons/momentary switches - any normally-open type
      • Breadboard or perfboard for connections
      • Jumper wires
      • USB cable (data-capable, not charge-only!)

      Total cost: Under $15!

      šŸ”Œ Wiring Diagram

      The wiring is incredibly simple - no resistors needed!

      GP0  ←→ Button ←→ GND    (sends 'a')
      GP1  ←→ Button ←→ GND    (sends 'b')
      GP2  ←→ Button ←→ GND    (sends 'c')
      ...
      GP19 ←→ Button ←→ GND    (sends 't')
      

      Important: Each button connects between a GPIO pin and any GND pin. The Pico's internal pull-up resistors handle the rest!

      šŸ“„ Software Installation

      Step 1: Install CircuitPython

      1. Download CircuitPython firmware:

        • For Pico: https://circuitpython.org/boar...
        • For Pico W: https://circuitpython.org/boar...
        • For Pico 2: https://circuitpython.org/boar...
      2. Install firmware:

        • Hold BOOTSEL button on Pico
        • Connect USB cable (keep BOOTSEL pressed)
        • Release BOOTSEL → "RPI-RP2" drive appears
        • Drag the downloaded .UF2 file to RPI-RP2
        • Drive disappears and "CIRCUITPY" appears

      Step 2: Install Required Library

      1. Download the library bundle:

        • Go to: https://circuitpython.org/libr...
        • Download the bundle matching your CircuitPython version
      2. Install adafruit_hid:

        • Extract the downloaded ZIP file
        • Copy the adafruit_hid folder from the bundle's lib directory
        • Paste it into the lib folder on your CIRCUITPY drive

      Your CIRCUITPY drive should look like:

      CIRCUITPY/
      ā”œā”€ā”€ code.py
      └── lib/    └── adafruit_hid/        ā”œā”€ā”€ __init__.py        ā”œā”€ā”€ keyboard.py        ā”œā”€ā”€ keycode.py        └── ...
      

      šŸ’» The Complete Code

      Save this as code.py on your CIRCUITPY drive:

      """
      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  <-> Button <-> GND   (sends 'a')
      GP1  <-> Button <-> GND   (sends 'b')
      GP2  <-> Button <-> GND   (sends 'c')
      ...
      GP19 <-> Button <-> 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 < len(failed_pins) and pin_numbers[i] in failed_pins:        print(f"  GP{i:2d} -> '{char}' (ERROR)")    else:        print(f"  GP{i:2d} -> '{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 >= 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")
      

      šŸŽ­ Using with Isadora 4

      Once connected, your Pico keyboard works like any standard keyboard:

      1. Scene Triggers: Assign keys a-t to trigger different scenes
      2. Parameter Control: Use keyboard shortcuts to control actor parameters
      3. Cue Sequences: Create complex cue sequences triggered by your custom keys
      4. Live Performance: Perfect for hands-on control during performances

      Tip: You can easily modify the keycodes array in the code to send different keys, function keys, or even key combinations!

      Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz, 3192 MHz, 6 Kern(e), 12 logische(r) Prozessor(en)
      16GB RAM
      Samsung SSD 870 QVO 2TB
      Win11Home
      NVIDIA Geforce GTX 1060 6GB
      www.dieleuchten.info

      Woland 1 Reply Last reply Reply Quote 3
      • Woland
        Woland Tech Staff @Konrad last edited by

        @konrad

        It'd be awesome if you could upload this to our Add-Ons Page.

        Cool stuff like this eventually gets buried in the forum.

        TroikaTronix Technical Support
        New Support Ticket: https://support.troikatronix.com/support/tickets/new
        Support Policy: https://support.troikatronix.com/support/solutions/articles/13000064762
        Add-Ons: https://troikatronix.com/add-ons/ & https://troikatronix.com/add-ons/?u=woland
        Professional Services: https://support.troikatronix.com/support/solutions/articles/13000109444

        | Isadora Version: all of them | Mac Pro (Late 2013), macOS 10.14.6, 3.5GHz 6-core, 1TB SSD, 64GB RAM, Dual AMD FirePro D700s |

        1 Reply Last reply Reply Quote 0
        • First post
          Last post