Hello,
I mentor an FRC robotics team (6762, The Oscats). One of our off-season projects is to make a custom controller. To be FRC legal, it needs to be wired to a Windows PC. We have some Cypress boards, which are a bit difficult for our programmers to get running. So, we are looking for something else that can be programmed with Python. Does anyone have any recommendations? At the moment, it would be nice if it were capable of at least two analog inputs, a few digital, and PWM outputs to run a rumble motor or two.
Thank you for all you bring to the robotics community.
~Mr. R^2
A Board Capable of Python and USB Joystick HID?
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- MrRSquared
- Posts: 14
- Joined: Fri Sep 20, 2019 9:48 am
- mikeysklar
- Posts: 14194
- Joined: Mon Aug 01, 2016 8:10 pm
Re: A Board Capable of Python and USB Joystick HID?
All the popular chips such as the M4, ESP32, RP2040 and nRF52 that Adafruit offers can run CircuitPython with USB GAMEPAD HID (which contains a joystick parameter). Maybe start with a Feather RP2040 since you didn't mention a need for WiFi or BLE. There are two guides to checkout:
https://learn.adafruit.com/customizing- ... id-devices
https://learn.adafruit.com/custom-hid-d ... cuitpython
https://learn.adafruit.com/customizing- ... id-devices
https://learn.adafruit.com/custom-hid-d ... cuitpython
- MrRSquared
- Posts: 14
- Joined: Fri Sep 20, 2019 9:48 am
Re: A Board Capable of Python and USB Joystick HID?
Hello,
Sorry for the delay. The end of the school year is always quite crazy.
Thank you for this recommendation. We have some esp32s, so I think we will begin with that. This is incredibly helpful.
Sorry for the delay. The end of the school year is always quite crazy.
Thank you for this recommendation. We have some esp32s, so I think we will begin with that. This is incredibly helpful.
- Lekofraggle
- Posts: 23
- Joined: Thu Jun 21, 2018 2:50 pm
Re: A Board Capable of Python and USB Joystick HID?
Hello,
Thank you again for your help.
Our school year is over, and I have a bit of time to play with this. We decided to take your recommendation and begin with a Pi Pico (the feather version is out of stock, so we did the normal one). As you surmised, we do not need wifi because wireless comms are not allowed at our events (thought we may switch to wireless for outreach events).
I looked at the tutorials, and the samples. I can get the normal HID examples to work (mouse and keyboard), but I am lost at the gamepad.
It seems the tutorials posted above need three software components (I assume all live on the pico).
1) main.py (code.py would work, but linting complains about overriding base modules, which is understandable) This is the interpreter of the analog stick(s) and button IO.
2) boot.py sends the messages from the device to the OS
3) a driver (hid_gamepad).
I am stuck with 3. int he tutorial is just this line.
I assume the driver is an interpreter between the boot and the main, but I am not certain. I found some old example code, but none mention a driver.
Am I reading things correctly, or is there another piece I am missing?
If I am reading things correctly, are there any tutorials for writing a CircuitPython driver?
The sample I would like to start with is here. There is a more complex example in the same folder, but I cannot get it to work either.
Here is the sample boot.py I am using.
Thank you again for your help.
Our school year is over, and I have a bit of time to play with this. We decided to take your recommendation and begin with a Pi Pico (the feather version is out of stock, so we did the normal one). As you surmised, we do not need wifi because wireless comms are not allowed at our events (thought we may switch to wireless for outreach events).
I looked at the tutorials, and the samples. I can get the normal HID examples to work (mouse and keyboard), but I am lost at the gamepad.
It seems the tutorials posted above need three software components (I assume all live on the pico).
1) main.py (code.py would work, but linting complains about overriding base modules, which is understandable) This is the interpreter of the analog stick(s) and button IO.
2) boot.py sends the messages from the device to the OS
3) a driver (hid_gamepad).
I am stuck with 3. int he tutorial is just this line.
If I click the link to the examples page, it sends me here. It is confusing because the only drivers for devices that do not need a boot.pyYou will also need to write a CircuitPython driver to handle your new device. There are examples in the adafruit_hid library.
I assume the driver is an interpreter between the boot and the main, but I am not certain. I found some old example code, but none mention a driver.
Am I reading things correctly, or is there another piece I am missing?
If I am reading things correctly, are there any tutorials for writing a CircuitPython driver?
The sample I would like to start with is here. There is a more complex example in the same folder, but I cannot get it to work either.
Code: Select all
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# You must add a gamepad HID device inside your boot.py file
# in order to use this example.
# See this Learn Guide for details:
# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/hid-devices#custom-hid-devices-3096614-9
import board
import digitalio
import analogio
import usb_hid
from hid_gamepad import Gamepad #I cannot find this import.
gp = Gamepad(usb_hid.devices)
# Create some buttons. The physical buttons are connected
# to ground on one side and these and these pins on the other.
button_pins = (board.D2, board.D3, board.D4, board.D5)
# Map the buttons to button numbers on the Gamepad.
# gamepad_buttons[i] will send that button number when buttons[i]
# is pushed.
gamepad_buttons = (1, 2, 8, 15)
buttons = [digitalio.DigitalInOut(pin) for pin in button_pins]
for button in buttons:
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP
# Connect an analog two-axis joystick to A4 and A5.
ax = analogio.AnalogIn(board.A4)
ay = analogio.AnalogIn(board.A5)
# Equivalent of Arduino's map() function.
def range_map(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
while True:
# Buttons are grounded when pressed (.value = False).
for i, button in enumerate(buttons):
gamepad_button_num = gamepad_buttons[i]
if button.value:
gp.release_buttons(gamepad_button_num)
print(" release", gamepad_button_num, end="")
else:
gp.press_buttons(gamepad_button_num)
print(" press", gamepad_button_num, end="")
# Convert range[0, 65535] to -127 to 127
gp.move_joysticks(
x=range_map(ax.value, 0, 65535, -127, 127),
y=range_map(ay.value, 0, 65535, -127, 127),
)
print(" x", ax.value, "y", ay.value)
Code: Select all
import usb_hid
# This is only one example of a gamepad descriptor, and may not suit your needs.
GAMEPAD_REPORT_DESCRIPTOR = bytes((
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
0x09, 0x05, # Usage (Game Pad)
0xA1, 0x01, # Collection (Application)
0x85, 0x04, # Report ID (4)
0x05, 0x09, # Usage Page (Button)
0x19, 0x01, # Usage Minimum (Button 1)
0x29, 0x10, # Usage Maximum (Button 16)
0x15, 0x00, # Logical Minimum (0)
0x25, 0x01, # Logical Maximum (1)
0x75, 0x01, # Report Size (1)
0x95, 0x10, # Report Count (16)
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
0x15, 0x81, # Logical Minimum (-127)
0x25, 0x7F, # Logical Maximum (127)
0x09, 0x30, # Usage (X)
0x09, 0x31, # Usage (Y)
0x09, 0x32, # Usage (Z)
0x09, 0x35, # Usage (Rz)
0x75, 0x08, # Report Size (8)
0x95, 0x04, # Report Count (4)
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, # End Collection
))
gamepad = usb_hid.Device(
report_descriptor=GAMEPAD_REPORT_DESCRIPTOR,
usage_page=0x01, # Generic Desktop Control
usage=0x05, # Gamepad
report_ids=(4,), # Descriptor uses report ID 4.
in_report_lengths=(6,), # This gamepad sends 6 bytes in its report.
out_report_lengths=(0,), # It does not receive any reports.
)
usb_hid.enable(
(usb_hid.Device.KEYBOARD,
usb_hid.Device.MOUSE,
usb_hid.Device.CONSUMER_CONTROL,
gamepad)
)
- Franklin97355
- Posts: 23940
- Joined: Mon Apr 21, 2008 2:33 pm
- MrRSquared
- Posts: 14
- Joined: Fri Sep 20, 2019 9:48 am
Re: A Board Capable of Python and USB Joystick HID?
Thank you. That seems to be working.
My confusion was not realizing that hid_gamepad.py was the driver.
My confusion was not realizing that hid_gamepad.py was the driver.
Please be positive and constructive with your questions and comments.