Introduction: Add USB Game Controller to Arduino Leonardo/Micro
IMPORTANT NOTE: This article is for Arduino IDE version 1.6.5 (or below). To add a USB Game Controller to an Arduino Leonardo or Micro using Arduino IDE version 1.6.6 (or above) see the following Instructable: Arduino Leonardo/Micro as Game Controller/Joystick.
Out of the box the Arduino Leonardo and the Arduino Micro appear to the host computer as a generic keyboard and mouse. This article discusses how the Arduino Leonardo and the Arduino Micro can also appear as a generic Game Controller. This project will only work with Arduino products based on the ATmega32u4 microcontroller (i.e. the Arduino Leonardo and the Arduino Micro). It will not work with the Arduino Uno, because it is based on the ATmega328 microcontroller.
The Arduino generic Game Controller provides the following:
- X, Y, and Z axis
- 32 buttons
- X, Y, and Z axis rotation
- Rudder
- Throttle
- 2 Point of View Hat Switches
Step 1: Updating the Arduino Code
First make a backup copy of the following two files in the “%PROGRAMFILES%\Arduino\hardware\arduino\avr\cores\arduino” folder:
- USBAPI.h
- HID.cpp
Replace these two files with the ones attached to add a generic Game Controller to the Arduino Leonardo and the Arduino Micro.
Step 2: Running the Test Sketch
Compile and upload the attached UsbJoystickTest.ino sketch file onto the Arduino Leonardo or the Arduino Micro using the Arduino Software (IDE). I have tested this using version 1.6.1 through 1.6.5 of the software. For Arduino IDE version 1.6.6 and above, see the following Instructable: Arduino Leonardo/Micro as Game Controller/Joystick.
The following steps are for Windows 7. If you have a different version of Windows or a different operating system, these steps may differ.
Attachments
Step 3: Windows Control Panel - Hardware and Sound
Go to the Windows Control Panel and select “Hardware and Sound”.
Step 4: Devices and Printers
Then select “Devices and Printers”.
Step 5: Arduino Should Appear
The Arduino Micro or Arduino Leonardo should appear in the list of devices.
Step 6: Arduino Settings
- Next right mouse click on the Arduino Leonardo or Arduino Micro to display the settings menu.
- Then select “Game controller settings” to get to the “Game Controllers” dialog.
Step 7: Game Controller Settings
The Arduino Micro or Arduino Leonardo should appear in the list of installed game controllers. Select the Arduino Micro or Arduino Leonardo and click the Properties button to display the game controller test dialog.
Step 8:
While this dialog has focus, ground pin A0 on the Arduino to activate the test script. The test script will test the game controller functionality in the following order:
- 32 buttons
- throttle and rudder
- X and Y Axis
- Z Axis
- 2 Hat Switches
- X and Y Axis Rotation
Step 9: Joystick Library
Now that the Arduino Leonardo or Arduino Micro has the Joystick library, the Arduino can be used for custom game controller projects. The following describes the Joystick library that is included in the updated USBAPI.h and HID.cpp files.
Joystick.begin(bool initAutoSendState)
Starts emulating a game controller connected to a computer. By default all methods update the game controller state immediately. If initAutoSendState is set to false, the Joystick.sendState method must be called to update the game controller state.
Joystick.end()
Stops the game controller emulation to a connected computer.
Joystick.setXAxis(byte value)
Sets the X axis value. Range -127 to 127 (0 is center).
Joystick.setYAxis(byte value)
Sets the Y axis value. Range -127 to 127 (0 is center).
Joystick.setZAxis(byte value)
Sets the Z axis value. Range -127 to 127 (0 is center).
Joystick.setXAxisRotation(int value)
Sets the X axis rotation value. Range 0° to 360°.
Joystick.setyAxisRotation(int value)
Sets the Y axis rotation value. Range 0° to 360°.
Joystick.setZAxisRotation(int value)
Sets the Z axis rotation value. Range 0° to 360°.
Joystick.setButton(byte button, byte value)
Sets the state of the specified button. The button is the 0-based button number (i.e. button #1 is 0, button #2 is 1, etc.). The value is 1 if the button is pressed and 0 if the button is released.
Joystick.pressButton(byte button)
Press the indicated button. The button is the 0-based button number (i.e. button #1 is 0, button #2 is 1, etc.).
Joystick.releaseButton(byte button)
Release the indicated button. The button is the 0-based button number (i.e. button #1 is 0, button #2 is 1, etc.).
Joystick.setThrottle(byte value)
Sets the throttle value. Range 0 to 255.
Joystick.setRudder(byte value)
Sets the rudder value. Range 0 to 255.
Joystick.setHatSwitch(byte hatSwitch, int value)
Sets the value of the specified hat switch. The hatSwitch is 0-based (i.e. hat switch #1 is 0 and hat switch #2 is 1). The value is from 0° to 360°, but in 45° increments. Any value less than 45° will be rounded down (i.e. 44° is rounded down to 0°, 89° is rounded down to 45°, etc.).
Joystick.sendState()
Sends the updated joystick state to the host computer. Only needs to be called if AutoSendState is false (see Joystick.begin for more details).

Participated in the
Coded Creations
88 Comments
4 years ago
Where does one find the wiring diagram(s)?
Thanks :)
5 years ago
I'm a newbie as well. I have my board set up as a Leonardo, yet I get the message
'Joystick was not declared in this scope'.
I put the files you mentioned in the
PROGRAM FILES(x86)\Arduino\hardware\arduino\avr\cores\arduino
folder (I had to rename them so they matched the names you gave them - since during the download, the names were changed).
One thing that could be an issue: My Arduino files are in several locations on my hard drive. I can find no guide as to where everything should be in order to insure that all the various sketches and libraries are found by the IDE.
I need 8 ANALOG channels and no buttons.
I also cannot find any documentation on where to connect the potentiometers for the various channels. Is that somewhere?
Reply 5 years ago
You'll need 2 things to make this work:
1: The Arduino Joystick library: https://github.com/MHeironimus/ArduinoJoystickLibr...
2: add [ #include <Joystick.h> ] (without brackets) to the beginning of the sketch before the first const bool string.
Reply 5 years ago
I no longer support this method of doing this. I have a much easier way to do this using the Arduino Library (https://github.com/MHeironimus/ArduinoJoystickLibrary). There are examples on how to install and use this library on GitHub and at https://www.instructables.com/id/Create-a-Joystick-Using-the-Arduino-Joystick-Libra/.
Reply 5 years ago
Matthew,
I apologize for my lack of knowledge. I'm an experienced PIC Basic Pro (PBP) programmer. But Arduinos work a LOT different.
My goal is to use an ordinary hand-held R/C controller with 8 pots (pitch, roll, yaw ,throttle, mode, camera pitch, camera yaw, spare) to control a quadcopter using my laptop and the Mavlink Protocol. A program called MISSION PLANNER running on my laptop does the conversion between the joystick and Mavlink. This will allow me to use my laptop's 4G LTE connection to send commands to my quadcopter (which also has a 4G connection). This gives me virtually unlimited control range.
I need at least 8 ANALOG channels where an input voltage of 1-4V sets the output. I don't need any toggle or "hat" switches at all.
I can use ANALOG READ() to get a value. But how many bits are returned - 8? 10? 12? 16?. And what is the reference? 3.3V, Vcc, something else? I looked through the joystick library and I can't figure out how to make all channels analog, and what is the syntax to get an A/D reading into a 8-bit joystick "position".
Reply 5 years ago
> I can use ANALOG READ() to get a value. But how many bits are returned - 8? 10? 12? 16?
This is documented on the Arduino website: https://www.arduino.cc/en/Reference/AnalogRead
The Arduino uses a 10-bit A-to-D converter.
> And what is the reference? 3.3V, Vcc, something else?
Some links to help you with your question:
https://www.arduino.cc/en/Tutorial/AnalogInputPins
https://www.arduino.cc/en/Reference/AnalogReferenc...
For the Leonardo and the Micro the default reference is 5V.
Reply 5 years ago
Mattew,
I downloaded and installed the latest version of the joystick library.
I figured out how to read analog channels on an Arduino, and I can read them and send values to the terminal.
But I have some more questions:
In the Multiple Joystick Test program example -
There is a line
JOYSTICK_TYPE_MULTI_AXIS 32,1,true,true, false, true, true, false, false, false...
What are the numbers "32" and "1" for?
What does "true,true, false, true, true....." mean?
What is gcCycleDelta?
What is gcAnalogDelta?
If I want 8 analog joysticks and no digital buttons, how would set up that?
I look at each individual analog joystick as a "channel" . Is it correct that I can write a value to a channel by
Joystick[channel].setXAxis(analog value); ?
But I'm confused by the 'setXAxis' part. I was thinking if 'channel' is a variable that lets you write to any channel, but 'setXAxis' refers to a particular channel.
And if you have 8 joysticks, how do you refer to them? "X", "Y", "Z" .... then what?
I also assume that the value range expected by the library is -127 to +127. Is that correct?
If the above is true, then wouldn't
JoyStick_Value = (analogRead(1) >> 2) - 127
do the right thing?
Reply 5 years ago
I think most of your answers can be found on the ReadMe file at https://github.com/MHeironimus/ArduinoJoystickLibrary.
> What are the numbers "32" and "1" for?
The 32 is for buttonCount
The 1 is for hatSwitchCount
These are explained in the constructor portion of the Joystick Library API located in the ReadMe file.
> If I want 8 analog joysticks and no digital buttons, how would set up that?
Question: Do you want a single joystick with 8 axes or do you want 8 joysticks with an X and Y axis each?
Having 8 axes on a single joystick is tricky. The USB specification defines X, Y, Z, RX, RY, and RZ axes (which gets you to 6), but does not give you the ability to create more. You can also turn on some of the other analog inputs, like Accelerator and Throttle, but your game would need to support reading those values. A lot of games max out at 6.You can learn more about this at http://www.usb.org/developers/hidpage/Hut1_12v2.pd...
Having 8 joysticks with an X and Y each is just a matter of creating 8 instances of the Joystick class and giving them each a unique hidReportId. I have only tested up to 4, however.
> Is it correct that I can write a value to a channel by Joystick[channel].setXAxis(analog value); ?
Yes
> And if you have 8 joysticks, how do you refer to them? "X", "Y", "Z" .... then what?
You refer to them as 0, 1, 2, 3, 4, 5, 6, 7. For example, to set the Y axis for Joystick #4 (the index would be 3) to 100:
Joystick[3].setYAxis(100);
> I also assume that the value range expected by the library is -127 to +127. Is that correct?
That was the range for Version 1.0. Version 2.0 aligns with the Arduino defaults (which is 0 to 1023). You can set the range to anything you want, however, using the setXAxisRange, setYAxisRange, etc. methods.
Hope this helps,
Matt
Reply 5 years ago
I have successfully compiled the code and installed it into a Leonardo.
Then, when I go into Windows 10 "Devices and Printers". It identifies the device as "Arduino Leonardo", but the category is "Unspecified" and when I right-click on that icon, I get only
Create Shortcut
Remove Device
Troubleshoot
Properties
When I click on PROPERTIES, I get
"Report ID declaration outside of top level collection"
Apparently the joystick driver isn't loading properly.
5 years ago
I believe I'm getting it. I have 5 channels working, and now I'll try to add the other 3. It helps that the program that this controls allows me to "map" the "channels" to whatever I want, so I don't have to concern myself with what each channel is called - or is usually used for.
I may yet need more help, but I'm making solid progress. Knowing programming (in general) has helped a lot, and I'm slowly learning the way Arduino does things.
Thanks for everything so far....
5 years ago
I'll read some more, but note this is NOT for a game.
This is for robot/drone control.
I have -
Two - two-axis joysticks = 4 analog inputs
MODE control = 1 analog
Camera tilt (pitch) = 1 analog
Camera yaw = 1 analog
Camera MODE = 1 analog
SPARE = 1 analog.
All inputs will be either from a potentiometer wiper or from a variable voltage source. The potentiometers produce an approx 1.2V - 3.8V signal, while the voltage source produce 0V - 5V. As mentioned before, there will be no buttons or switches. And just as in a game controller, the response times should be very short.
5 years ago
Can anybody give me some tips on how to code for 14 digital buttons? Im very new to programming and im trying to make my first raspberry pi gameboy case. I would really apreciate a little help.
Looking forward to hear from you.
Reply 5 years ago
The latest version of this Arduino Library (https://github.com/MHeironimus/ArduinoJoystickLibrary) has a simple Gamepad example. The following Instructable shows how to use that example: https://www.instructables.com/id/Create-a-Joystick-Using-the-Arduino-Joystick-Libra/. It get to 14 buttons, you just need to follow the patterns established by that example. Hope this helps.
6 years ago
hi all,
just figure out the code i need for the joystick i need finally.
with 1 analog and 9 button mini joystick for my retropie.
i'm new in arduino, and not good in coding, just curious if any better way to do this.
btw, it's interest for try and error in coding arduino ;)
here is the code just modify by web research:
#include <Joystick.h>
Joystick_ Joystick(0x03, 0x04, 9, 0, true, true, false, false, false, false, false, false, false, false, false);
void setup() {
pinMode(2, INPUT_PULLUP); //A
pinMode(3, INPUT_PULLUP); //B
pinMode(4, INPUT_PULLUP); //X
pinMode(5, INPUT_PULLUP); //Y
pinMode(6, INPUT_PULLUP); //L
pinMode(7, INPUT_PULLUP); //R
pinMode(8, INPUT_PULLUP); //SELET
pinMode(9, INPUT_PULLUP); //START
pinMode(10, INPUT_PULLUP); //EXIT
Joystick.setXAxisRange(-32767,32767);
Joystick.setYAxisRange(-32767,32767);
Joystick.begin();
}
const int pinToButtonMap = 2;
int lastButtonState[9] = {0,0,0,0,0,0,0,0,0};
void loop(){
int xAxis = analogRead(A0);
int yAxis = analogRead(A1);
xAxis = map(xAxis, 1023, 0, 0, 255);
yAxis = map(yAxis, 0, 1023, 0, 255);
Joystick.setXAxis(xAxis);
Joystick.setYAxis(yAxis);
for (int index = 0; index < 9; index++)
{
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index])
{
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
}
}
}
7 years ago
Hi, is possible with this create a force feedback Sterring Wheel??? And witch board i can use??
Reply 7 years ago
I think this library could be used as a starting point, but I have not researched this. This library currently only supports sending Joystick data to the host machine. Force feedback devices get data back from the host computer and act on it (e.g. making the steering wheel harder to turn).
The library I wrote should work with any ATmega32u4 - based Arduino (or clone). I have tested it with the Arduino Leonardo and Arduino Micro. I know of others who have used it with the Arduino Due and SparkFun Pro Micro. I know it will not work with the Arduino Uno (since it used the ATmega328P).
Reply 7 years ago
Thank for your response..
I will try to go on this direction, if you have other info about it let us know them! I know that a lot of people have the same problem!
7 years ago
Great library and very useful. However I have been experiencing the issue where I cannot use both the Joystick.h and either/both Mouse.h and Keyboard.h. It seems the arduino can't be recognized as both a game controller and an HID device. Is there any workaround that you know of?
Reply 7 years ago
Can you include an example sketch file (*.ino) that demonstrates your issue? I have successfully used Joystick.h and Keyboard.h together without issue (see https://www.instructables.com/id/Ultimate-Classic-Game-Console-Joystick-to-USB-Adap/ for an example of this).
Reply 7 years ago
Thanks for the response! I actually got them to work together by installing the Joystick Libraries in the Program Files folder, not in the Documents/Arduino folder. The past day has been very productive thanks to your code. Thanks!