adafruit / Adafruit_CircuitPython_HID

USB Human Interface Device drivers.
MIT License
364 stars 106 forks source link

Examples using the keypad module for a keyboard and macros #108

Open Neradoc opened 1 year ago

Neradoc commented 1 year ago

We could use [an] example[s] that uses the keypad module for a keyboard, and shortcuts or macros. Mention to @kattni as promised.

Possibly showing concepts like:

Maybe more advanced:

xgpt commented 1 year ago

Today I was trying to write a class based around keypad.

Things I specifically needed to implement (that I'm still working on), that I think would be more accurate/easy with keypad vs. digitalio:

utilizing .timestamp and .key_pressed to track when a button is pressed

so creating a variable/object/attribute that tracks when a button is pressed, and when a button is pressed, it marks it as pressed.

I need a way to basically re-implement the following code without getting caught in the while loop, I'd very much so like to do it inside keypad instead of with digitalio.

import time,board,digitalio, usb_hid
from adafruit_hid.mouse import Mouse

button0=digitalio.DigitalInOut(board.D4)
button1=digitalio.DigitalInOut(board.D5)
button0.switch_to_input(pull=digitalio.Pull.DOWN)
button1.switch_to_input(pull=digitalio.Pull.DOWN)

m = Mouse(usb_hid.devices)

while True:
    if button0.value:
        timestamp=time.monotonic()+0.75
        while button0.value:
            if timestamp>=time.monotonic():
                m.move(0,1,0)
                print('slow')
            else:
                if button0.value:
                    timestamp=time.monotonic()+.75
                    while button0.value:
                        if timestamp>=time.monotonic():
                            m.move(0,3,0)
                            print('medium')
                        else:
                            m.move(0,7,0)
                            print('fast!')

The above is real code (I think , or at the very least test code) that is used by someone who uses a buttons-to-mouse-movement HID device I made with a headpointer. They need to move the mouse slowly at first, but if they need to get all the way across the screen it helps if it moves faster if the button has been held a while. Then they can let up off it, and press it again to regain slow and careful control to zero in on the UI target.

todbot commented 1 year ago

Hi @xgpt, Not sure if this is what you're asking for, but here's how I might do the above code using keypad. It frees you up from being stuck in while loops waiting for key holding or release. Is this sort of what you were after? (Using the key.timestamp property isn't that helpful here since you need to save the time anyway)

import time, board, keypad, usb_hid
from adafruit_hid.mouse import Mouse

m = Mouse(usb_hid.devices)

key_pins = (board.D4, board.D5)

keys = keypad.Keys(key_pins, value_when_pressed=True, pull=False)

print("waiting for keypresses...")

but0_press_time = 0  # when button0 was pressed. 0 means not currently pressed

while True:
    # get key events, if any, set butN_press_time as appropriate
    key = keys.events.get()
    if key:
        print(key.timestamp, key)  # see what key was pressed
        if key.key_number == 0:  # button0 
            if key.pressed:
                but0_press_time = time.monotonic()
            if key.released:
                but0_press_time = 0 # unpressed

    # handle sending mouse commands if buttons were pressed
    if but0_press_time:
        held_time = time.monotonic() - but0_press_time
        if held_time < 0.75:
            print("slow", held_time)
            m.move(0,1,0)
        elif held_time > 0.75 and held_time < 0.75*2:
            print("medium")
            m.move(0,3,0)
        elif held_time > 0.75*2:
            print("fast!")
            m.move(0,7,0)
xgpt commented 1 year ago

@todbot That's absolutely an excellent solution that solves my problem nearly entirely. I wonder if these commonly asked questions might better be incorporated into keypad itself, specifically things like "long hold" or "double click" questions.

@Neradoc mentioned that he even created a debouncer library in the Discord yesterday. https://github.com/Neradoc/keypad_debouncer

If such features aren't incorporated into the standard library, perhaps it would be worth mentioning how to implement them in the to-be-written guide?

I hope I'm not coming off as a demanding user here, just genuinely trying to make recommendations as a beginner on what would be helpful to be able to search up on the learning platform.

partyexpress commented 1 year ago

Hi There,

I am trying to make a mouse and keyboard HID. I'm using a Raspberry Pi 4, with the USB C port as the connection. I've used the code below, and it says, "Could not find matching HID device. I can't seem to get around that. Can you please explain my issue. Thanks in advance.

Steve C.

import usb_hid
from adafruit_hid.mouse import Mouse

m = Mouse(usb_hid.devices)

# Click the left mouse button.
m.click(Mouse.LEFT_BUTTON)

# Move the mouse diagonally to the upper left.
m.move(-100, -100, 0)

# Roll the mouse wheel away from the user one unit.
# Amount scrolled depends on the host.
m.move(0, 0, -1)

# Keyword arguments may also be used. Omitted arguments default to 0.
m.move(x=-100, y=-100)
m.move(wheel=-1)

# Move the mouse while holding down the left button. (click-drag).
m.press(Mouse.LEFT_BUTTON)
m.move(x=50, y=20)
m.release_all()       # or m.release(Mouse.LEFT_BUTTON)
todbot commented 1 year ago

@partyexpress, this library is for CircuitPython on microcontrollers. If you want to use Python to access USB HID on Raspberry Pis (or other unixes), check out https://pypi.org/project/hidapi/

dhalbert commented 1 year ago

I made a keypad example a while ago in https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/keys-one-key-per-pin#macropad-example-3099041. I am wondering if it is out of scope for simple library examples, or whether I should just add it to examples/.