I've built a basic two button analog joystick driver for the UNO that turns the UNO into a USB joystick. This is based on the joystick demo from the LUFA project which defines X and Y analog input ranging from -100 to +100 and two buttons.
I've defined a serial protocol for sending joystick commands with the following format:
||X value, -100 to 100
||Y value, -100 to 100
||Buttons. Bit 0 = button 1, Bit 1 = button 2
||reserved. Set to 0 for now.
Here is the firmware, source, and sample sketch. The firmware works on both the UNO and the Mega2560.
Upload the sketch, then load the hex file using DFU mode as described in my earlier posts (dfu-programmer for Linux/OSX or flip for Windows). Unplug the board and plug it back in and your PC should now recognise an Arduino joystick and start receiving input from the sketch.
Note you'll need to reload the USB Serial firmware via DFU mode whenever you want to change your sketch.
Here's a summary of how I created the firmware.
- I started with a copy of the arduino-mouse source code, and renamed Arduino-mouse.c to Arduino-joystick.c and Arduino-mouse.h to Arduino-joystick.h. I could have started with the USB Serial driver but the mouse HID driver was already close to what was needed for the joystick code.
- I copied in Descriptors.c and Descriptors.h from the LUFA joystick demo (Demos/Device/ClassDriver/Joystick available from the LUFA100807 source from the LUFA Project).
- I modified Descriptors.c to change the ManufacturerString to "Arduino" and the ProductString to "Arduino Joystick".
- I added a USB_JoystickReport_Data_t data structure typedef to Arduino-joystick.h (based on the definition from the LUFA demo's joystick.h header).
- I replaced all references to "MouseReport" in Arduino-joystick.c with "JoystickReport".
- I changed the CALLBACK_HID_Device_CreateHIDReport so that it checks the amount of serial data received and whenever there is a full report available (i.e. 4 bytes) it copies it into a global joystick report variable. The function always sends the global joystick report to the PC host, so the effect is that it always sends the most recent report to the host. If there is no new report then the last one received is sent again.
- I changed the main loop to only call the HID and USB handlers (since the report handling is now taken care of in the CALLBACK_HID_Device_CreateHIDReport function).
- I also bumped the serial baud rate from 9600 up to 115200 to let the UNO send joystick updates as quickly as possible.
- And finally I added code to turn on the TX led when a report is received from the serial port (i.e. from the UNO) and to turn it off again after a small amount of time. This means the TX led will flash whenever the UNO sends a joystick command.