adafruit / Adafruit_Blinka

Add CircuitPython hardware API and libraries to MicroPython & CPython devices
https://learn.adafruit.com/circuitpython-on-raspberrypi-linux
MIT License
439 stars 328 forks source link

Add requirements and example for usb_hid #628

Open makermelissa opened 1 year ago

makermelissa commented 1 year ago

Hi,

what are prerequirements for this module on raspberry pi zero? Is there any example code?

_Originally posted by @Med-JH in https://github.com/adafruit/Adafruit_Blinka/issues/560#issuecomment-1234122867_

makermelissa commented 9 months ago

For the documentation and an example, I think the best place would be for me to write up a page to this learn guide: https://learn.adafruit.com/circuitpython-on-raspberrypi-linux

eightycc commented 9 months ago

The API documentation also needs to be here: https://docs.circuitpython.org/projects/blinka/en/latest/index.html

eightycc commented 9 months ago

@makermelissa If you like, I can summarize the steps needed to get usb_hid to work and give you a simple example.

makermelissa commented 9 months ago

That would be awesome.

eightycc commented 9 months ago

@makermelissa Here are my steps and demo program. The demo is cribbed from another Adafruit demo.

Note: This set of steps is specific to the Raspberry Pi Zero (W) running the latest 32-bit Raspberry Pi OS.

  1. Install Blinka. This can be the usual user level install, I'll show how to use it in superuser (uid 0) mode in a later step.
  2. usb_hid is the package in Blinka that implements USB HID support. It depends on the overlay dwc2.dtbo. This overlay is the driver that implements low-level USB gadget support necessary for emulating HID devices on the USB interface. Install it by adding this line at the end of your /boot/config.txt and reboot:
    sudo bash -c "echo 'dtoverlay=dwc2' >> /boot/config.txt"
    sudo reboot
  3. usb_hid also depends on the Linux kernel module libcomposite. This provides the upper-level part of USB gadget that implements an fs-like interface for configuring and communicating with HID devices. Load it by running:
    sudo modprobe libcomposite

    Note: You will have to repeat this step after each reboot. To make it permanent, add libcomposite to /etc/modules:

    sudo bash -c "echo 'libcomposite' >> /etc/modules"
  4. adafruit-circuitpython-hid is the CircuitPython package that implements the python interface to HID devices. Install it by running:
    pip3 install adafruit-circuitpython-hid
  5. Wire a button to the Zero GP20 and GND pins.
  6. Wire another button to the Zero GP21 and GND pins.
  7. Wire an LED to the Zero GP16 and to GND pins through a 1k resistor (I like my LEDs dim!).
  8. Connect the Zero to your host computer with a USB cable. The Zero will appear as a USB HID keyboard device when you run the demo.
  9. Create a file hid_kbd_demo.py:

    # SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
    #
    # SPDX-License-Identifier: MIT
    
    """Blinka HID Keyboard example"""
    
    import time
    import board
    import digitalio
    import usb_hid
    from adafruit_hid.keyboard import Keyboard
    from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
    from adafruit_hid.keycode import Keycode
    from usb_hid import Device
    
    # A simple neat keyboard demo for Blinka
    
    # The pins we'll use for buttons, each will have an internal pullup
    keypress_pins = [board.D20, board.D21]
    #    Our array of key objects
    key_pin_array = []
    # The Keycode sent for each button, will be paired with a control key
    keys_pressed = [Keycode.A, "Hello World!\n"]
    control_key = Keycode.SHIFT
    
    # Make all pin objects inputs with pullups
    for pin in keypress_pins:
        key_pin = digitalio.DigitalInOut(pin)
        key_pin.direction = digitalio.Direction.INPUT
        key_pin.pull = digitalio.Pull.UP
        key_pin_array.append(key_pin)
    
    # Setup LED
    led = digitalio.DigitalInOut(board.D16)
    led.direction = digitalio.Direction.OUTPUT
    
    # Create the keyboard object
    usb_hid.enable([Device.KEYBOARD], boot_device=0)
    keyboard = Keyboard(usb_hid.devices)
    keyboard_layout = KeyboardLayoutUS(keyboard)
    
    print("Waiting for key pin...")
    
    while True:
        # Check each pin
        for key_pin in key_pin_array:
            if not key_pin.value:  # Is it grounded?
                i = key_pin_array.index(key_pin)
                print("Pin #%d is grounded." % i)
    
                # Turn on the red LED
                led.value = True
    
                while not key_pin.value:
                    pass  # Wait for it to be ungrounded!
                # "Type" the Keycode or string
                key = keys_pressed[i]  # Get the corresponding Keycode or string
                if isinstance(key, str):  # If it's a string...
                    keyboard_layout.write(key)  # ...Print the string
                else:  # If it's not a string...
                    keyboard.press(control_key, key)  # "Press"...
                    keyboard.release_all()  # ..."Release"!
    
                # Turn off the red LED
                led.value = False
    
        time.sleep(0.01)
    
  10. Run the demo in superuser mode. The -E option preserves the users environment variables, which causes the user installed Blinka and CircuitPython packages to be found:
    sudo -E python3 hid_kbd_demo.py
makermelissa commented 9 months ago

Thank you. I'm currently updating Blinka Displayio, but will test out and write up a page afterwards.