#hid
1 messages ยท Page 1 of 1 (latest)
# SPDX-FileCopyrightText: 2018 Dan Halbert for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`Gamepad`
====================================================
* Author(s): Dan Halbert
"""
import time
from adafruit_hid import find_device
class Gamepad:
def __init__(self, devices):
"""Create a Gamepad object that will send USB gamepad HID reports."""
self._gamepad_device = find_device(devices, usage_page=0x1, usage=0x05)
# Reuse this bytearray to send gamepad reports.
# Report structure:
# Byte 0: RX
# Byte 1: RY
# Byte 2: RZ
self._report = bytearray(3)
# Remember the last report as well, so we can avoid sending duplicate reports.
self._last_report = bytearray(3)
# Store axis states separately for easier manipulation.
self._rx = 0
self._ry = 0
self._rz = 0
# Send an initial report to test if HID device is ready.
# If not, wait a bit and try once more.
try:
self.reset_all()
except OSError:
time.sleep(1)
self.reset_all()
def set_axes(self, rx, ry, rz):
"""Set the RX, RY, and RZ axis values (0-255)."""
self._rx = self._validate_axis_value(rx)
self._ry = self._validate_axis_value(ry)
self._rz = self._validate_axis_value(rz)
self._send()
def reset_all(self):
self._rx = 0
self._ry = 0
self._rz = 0
time.sleep(0.05) # Short delay to prevent USB busy state
self._send(always=True)
# Pack RX, RY, RZ axes into the HID report
self._report[0] = self._rx
self._report[1] = self._ry
self._report[2] = self._rz
# Debug print to verify the report content
print(f"Sending HID report: {self._report.hex()}")
# Retry logic for USB busy state
retry_count = 3
for attempt in range(retry_count):
try:
# Only send the report if it has changed, unless `always` is True
if always or self._last_report != self._report:
self._gamepad_device.send_report(self._report)
self._last_report[:] = self._report
break
except OSError as e:
if attempt < retry_count - 1:
print(f"USB busy, retrying... (attempt {attempt + 1})")
time.sleep(0.05) # Short delay before retrying
else:
print("USB busy error, retries exhausted.")
raise e
@staticmethod
def _validate_axis_value(value):
if not 0 <= value <= 255:
raise ValueError("Axis value must be in range 0 to 255")
return value```
i got this as boot
# It may not suit your needs, or be supported on your host computer.
import usb_hid
GAMEPAD_REPORT_DESCRIPTOR = bytes([
0x05, 0x01, # Usage Page (Generic Desktop Controls)
0x09, 0x05, # Usage (Gamepad)
0xA1, 0x01, # Collection (Application)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x00, # Logical Maximum (255)
0x75, 0x08, # Report Size (8 bits)
0x95, 0x03, # Report Count (3 fields: RX, RY, RZ)
0x09, 0x33, # Usage (RX - Rotation about X-axis)
0x09, 0x34, # Usage (RY - Rotation about Y-axis)
0x09, 0x35, # Usage (RZ - Rotation about Z-axis)
0x81, 0x02, # Input (Data, Variable, Absolute)
0xC0 # End Collection
])
gamepad_descriptor = usb_hid.Device(
report_descriptor=GAMEPAD_REPORT_DESCRIPTOR,
usage_page=0x01, # Generic Desktop Controls
usage=0x05, # Gamepad
report_ids=(1,), # Report ID is 1
in_report_lengths=(3,), # 3 bytes: RX, RY, RZ
out_report_lengths=(0,) # No output reports
)
this is the hid part
upload the whole files. Use the + instead of pasting. It takes less space
i have to go pick up a pizza; will be back alter
๐ oke
im trying to port my
https://github.com/vospascal/pedal-gui
https://github.com/vospascal/pedal-arduino
bon appetit
i wish i could just unit test it or something to get easier bug errors out of it
the first argument to usb_hid.enable() needs to be a sequence of devices, not a single device:
you have
usb_hid.enable(gamepad_descriptor, boot_device=1)
do
usb_hid.enable((gamepad_descriptor,), boot_device=1)
to pass a 1-element tuple
errors in boot.py are reported in boot_out.txt. Look in that file and see if there's an error reported
oke will try that in a sec
Auto-reload is off.
Running in safe mode! Not running saved code.
You are in safe mode because:
Boot device must be first (interface #0).
Press reset to exit safe mode.
Press any key to enter the REPL. Use CTRL-D to reload.```
in need to reflash the whole pico when it gets in this state
you can just edit boot.py to fix
you should not need to reflash everything. you need to do a hard reset to get out of safe mode
Set interface name for the gamepad
usb_hid.enable((gamepad_descriptor,), boot_device=1)
usb_hid.set_interface_name("PedalBox")
usb_cdc.enable(console=True, data=True)
i got this and it stuck
in save mode
i cant copy files to it
boot device is a special thing so you can use a keyboard to talk to the bios
or similar
but it should not be read-only, that's weird
is this 9.2.1?
There's a typo (missing comma) in the documentation, sorry :/
9.0.5 i think im on
update to 9.2.1, and also make sure adafruit_hid is up to date
oke
it did work for other projects ๐
just combination kinda freaks it out i think
but just hid or just serial on 9.0.5
there may well be some bug, but take away boot_device=1, you don't need that for the gamepad
yes i did ๐
what is the host computer?
that is right, console and data. Two COM ports
ah oke ๐
do you need two? The data is for transferring binary data without getting in the way of the REPL. But if you don't need it, you can take that away
ah now i get nice errors again ๐
File "code.py", line 53, in <module>
File "code.py", line 14, in __init__
File "Pedals.py", line 26, in __init__
File "Pedal.py", line 24, in __init__
File "adafruit_ads1x15/ads1x15.py", line 153, in __init__
AttributeError: 'NoneType' object has no attribute 'try_lock'```
i can work with this
ok, you are on your way. looks like you i2c device is None
i try to connect to this now
i have this on ardiuno now want it to pico bit more modern ๐
it uses serial to set settings to the device
and hid for game input
fun stuff
yes i dont have any i2c connected just analog for now need to get a loadcell other one the strain gauge broke ๐
@pastel creek thank you for your help and your awesome work on CircuitPython ๐
you're welcome!
it is so easy to make a mistake; too many times I have changed the comment but not the actual value