Bridge USB gamepads over IP to enable FTC remote operation
Download the client page (right click -> Save As) and open in a browser. The client webpage uses the Javascript Gamepad API, which is sufficiently supported by most modern browsers.
- Enter the address and port of the server you wish to connect to.
- Then connect a gamepad to your computer and press some buttons so the browser can detect it. If you are using the Logitech F310 controller, make sure the switch on the back is set to "D" before plugging it into your computer.
- Press the Connect button to establish connection to the server
This project uses pipenv to manage dependencies. Run pipenv install
on first clone to download and install Python dependencies.
Run server script with pipenv run python3 server/gamepad_bridge_server.py /dev/serial0
, replacing /dev/serial0
with the appropriate serial UART for your system. For testing, you can add the --dummy-serial
option to skip connecting to a physical serial port.
The firmware is written to run on both Teensy boards via the Teensyduino Joystick API and Arduino boards via the Arduino XInput library. Note that the XInput library requires additional installation procedures, but can run on either Arduino or Teensy boards. Also, XInput is a Microsoft API, so boards running with the XInput library will not be detected as joysticks on Mac or Linux computers without additional software. On an Android phone running the driver station app, XInput devices will appear as Xbox 360 controllers.
The Teensys listen for incoming command on a common serial bus. To simplify connecting all the RX lines together to the Raspberry Pi's serial TX, we designed a simple carrier board. The first design is a single-sided prototype suitable for milling on a desktop CNC machine. Each board holds four Teensy LCs, with headers for ground and serial RX. Note that the Teensys receive power via USB, but share a common ground with the Raspberry Pi. A second set of headers allows these boards to be daisy chained to easily add additional Teensys. The address or device index for each Teensy is programmed using a set of jumpers selective pulling down GPIO pins 2-5. Each Teensy reads its ID as a binary coded number on boot based on the jumper configuration.
The same binary message format will be used over the Websocket and serial connection. We shall use little-endian byte order to match the Arduino/ARM processor convention. All messages start with the following header:
Field | Size (bytes) | Description |
---|---|---|
Index | 1 | ID of destination controller |
Command ID | 1 | Numeric identifier signfying message type |
Length | 2 | Length of the message body in bytes. Note this does not include this header, only the contents following. |
Signify that a client has connected to the given controller index. No message body (length = 0).
Signify that a client has disconnected from the given controller index. No message body (length = 0).
Report the controller state from client to server/device. Message body:
Field | Size (bytes) | Description |
---|---|---|
Joystick1_X | 2 | Joystick 1 X Axis value. Format as 16 bit signed integer. |
Joystick1_Y | 2 | Joystick 1 Y Axis value |
Joystick2_X | 2 | Joystick 2 X Axis value |
Joystick2_Y | 2 | Joystick 2 Y Axis value |
Button_state | 2 | Bitfield indicating status of controller buttons. Bit(x) = 1 if pressed, 0 if unpressed. Bits counted from LSB. |
RESERVED | 2 | Unused, space reserved for padding to 4b alignment. |
Report a Windows XInput controller state from client to server/device. Message body:
Field | Size (bytes) | Description |
---|---|---|
Joystick1_X | 2 | Joystick 1 X Axis value. Format as 16 bit signed integer. |
Joystick1_Y | 2 | Joystick 1 Y Axis value |
Joystick2_X | 2 | Joystick 2 X Axis value |
Joystick2_Y | 2 | Joystick 2 Y Axis value |
Button_state | 2 | Bitfield indicating status of controller buttons. Bit(x) = 1 if pressed, 0 if unpressed. Bits counted from LSB. |
Trigger_L | 1 | Trigger value, format as 8 bit unsigned integer |
Trigger_R | 1 | Trigger value, format as 8 bit unsigned integer |