Introduction: Arduino Leonardo/Micro As Game Controller/Joystick

Picture of Arduino Leonardo/Micro As Game Controller/Joystick

IMPORTANT NOTE: This article is for Arduino IDE version 1.6.6 (or above). To add a USB Game Controller to an Arduino Leonardo or Micro using Arduino IDE version 1.6.5 (or below) see the following Instructable: Add USB Game Controller to Arduino Leonardo/Micro.

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 or Joystick. 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 Joystick Library (a.k.a. Game Controller library) used in the Instructable 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: Installing the Library

Picture of Installing the Library

The latest version of the Arduino library that allows the Arduino Leonardo and Micro to appear as a Game Controller can be downloaded from the following GitHub repository:

This GitHub repository actually contains three different versions of the Arduino Joystick Library:

  • Joystick - Causes the Arduino to appear as single Game Controller
  • Joystick2 - Causes the Arduino to appear as two, simple Game Controllers
  • Joystick3 - Causes the Arduino to appear as three, simple Game Controllers

Copy the Joystick (and/or Joystick2 and/or Joystick3) folder from GitHub to the Arduino Libraries folder (typically located at %userprofile%\Documents\Arduino\libraries). The library (or libraries) should now appear in the Arduino IDE list of libraries.

Step 2: Running the Test Sketch

Picture of Running the Test Sketch

Included in the library is a test sketch, called UsbJoystickTest.ino (or UsbJoystick2Test.ino or UsbJoystick3Test.ino). This sketch should be loaded, compiled, and uploaded to the Arduino Leonardo or Micro using the Arduino IDE (version 1.6.6 or above).

The following steps are for Windows 7. If you have a different version of Windows or a different operating system, these steps may differ.

Step 3: Windows Control Panel - Hardware and Sound

Picture of Windows Control Panel - Hardware and Sound

Go to the Windows Control Panel and select “Hardware and Sound”.

Step 4: Devices and Printers

Picture of Devices and Printers

Then select “Devices and Printers”.

Step 5: Arduino Settings

Picture of Arduino Settings

  1. The Arduino Micro or Arduino Leonardo should appear in the list of devices.
  2. Right mouse click on the Arduino Leonardo or Arduino Micro to display the settings menu.
  3. Select “Game controller settings” to get to the “Game Controllers” dialog.

Step 6: Game Controller Settings

Picture of Game Controller Settings

The Arduino Leonardo or Micro should appear in the list of installed game controllers. Select the Arduino Leonardo or Micro and click the Properties button to display the game controller test dialog.

Step 7: Test Using Game Controller Settings

Picture of Test Using Game Controller Settings

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 8: Another Simple Test

Once you have verified the Arduino Leonardo or Micro is working as a Game Controller, you can start creating your own Game Controller projects. The attached Arduino sketch file is a simple example that reads digital pins 9, 10, 11, and 12 and maps them to buttons 1, 2, 3, and 4 on the Game Controller.

Step 9: Joystick Library API

Now that the Joystick library is available to the Arduino IDE, an Arduino Leonardo or Arduino Micro can be used for custom game controller projects. The following describes the complete Arduino Joystick Library API.

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.


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 (0 or 1) of the specified button (0 - 31). 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 (0 - 31). 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 (0 - 31). 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.). Set the value to -1 to release the hat switch.


Sends the updated joystick state to the host computer. Only needs to be called if AutoSendState is false (see Joystick.begin for more details).

Step 10: Additional Information

Additional information about this Arduino Joystick Library can be found on the following websites:

Arduino Joystick Library -

GitHub [MHeironimus/ArduinoJoystickLibrary] -


charleslinquist (author)2017-10-18


I downloaded the "Multiple Joystick Test" from GitHub and installed the Joystick library. It shows up in my list of libraries. When I try to compile for Leonardo, I get the messages:

"MultipleJoystickTest:14: error: 'Joystick_' does not name a type

Joystick_ Joystick[JOYSTICK_COUNT] = {

C:\Users\Charles\Documents\ArduinoJoystick\MultipleJoystickTest\MultipleJoystickTest.ino: In function 'void testSingleButtonPush(int, unsigned int)':

MultipleJoystickTest:36: error: 'Joystick' was not declared in this scope

Joystick[joystickId].releaseButton(button - 1);

MultipleJoystickTest:40: error: 'Joystick' was not declared in this scope


C:\Users\Charles\Documents\ArduinoJoystick\MultipleJoystickTest\MultipleJoystickTest.ino: In function 'void testMultiButtonPush(int, unsigned int)':

MultipleJoystickTest:52: error: 'Joystick' was not declared in this scope

What could be wrong?

MatthewH (author)charleslinquist2017-10-19

It sounds like you may have a version mismatch between your Joystick library and the example you are trying to run. I suggest pulling down the latest version of the library from (which is 2.0.4 when I wrote this comment), install it using deploy.bat (or if you are on linux), and open the example using the Arduino's File -> Examples -> Joystick -> MultipleJoystickTest menu option.

If you are still having issues after that, let me know what version of he Arduino IDE you are using and what OS you are running on.

Swed X (author)2017-09-18

Hi Matthewh

all this is so awesome and great
and iam going to buy an micro arduino now

i only have one ? is it possible to maybe add Ethernet module to the arduino board and then make an joystick board over local Ethernet?

MatthewH (author)Swed X2017-09-18

I have never tried to connect a joystick over Ethernet, so I am not sure. I think you would need a special joystick driver on the host PC. Do you know of any off-the-shelf joysticks that support connecting to the PC via Ethernet? If so, I would be interested in seeing a link to one.

Swed X (author)MatthewH2017-09-19

I also found out that Uno Boards also can be HID Joystick
wich is not an Atmega32u4

Swed X (author)MatthewH2017-09-19

I got it to work with Littlebits Arduino
1 button
2 R Axis

This one does not work

Joystick.setXAxisRotation(int value)
so i found someone who used

that Works fine

about the ethernet solution i will try do some Research
but i think i need to send udp packets data directly into Flight simulator

Swed X (author)MatthewH2017-09-19

Hi again

I Think it Would requrie an atmega32u4 arduino board with Ethernet and an udp protocol

And then on the client pc
It Would need an software to translate udp to hid driver

One exsample here

But i know it Can be done
Maybe i first need to find that translate client software

Bonus info
Right now i Only have an at heart littlebits arduino
Just found out it has an atmega32u4

So now i Will try to Make that littlebits board work Locally

SarthakG10 (author)2017-08-22

Hi, Thanks for the awesome work. I have a couple of questions. I am using an arduino micro pro with a thumb joystick and the latest version of your library. I am doing analog read on the joystick axes and doing a "Joystick.setXAxis(value)" call. In this way, the joystick values are being mapped to -32678 to 32676 (int16_t). I checked the raw values in the Windows gamepad calibration applet. However, when I connect a commercial gamepad device (like an xbox controller), I see that the raw values range from 0-65536 (uint16_t). Could you tell me why we see this difference and how can I make the arduino behave like the commercial controller?

Secondly, I faced some difficulty to understand the examples given with the library. Specifically, I couldn't understand what some variables are meant to do, for example : gcurrentStep in JoyStickTest. If you could provide some explanations and documentation on the existing examples, that would be extremely helpful. Thank you!

MatthewH (author)SarthakG102017-08-24

The raw axis values are determined by they datatypes used in the Joystick class and some constants defined in the Joystick.cpp file in the library. To make your desired change you will need to change the JOYSTICK_AXIS_MINIMUM to 0 and the JOYSTICK_AXIS_MAXIMUM to 65536. You will also need to modify most of the class's field variables from int16_t to uint16_t (e.g. _xAxis, _yAxis, etc.) in the Joystick.h and Joystick.cpp files. You would also need to modify the HID Report Description defined in the class constructor.

I am curious to know why you would need to change the raw joystick values as the OS's joystick drivers typically translate raw, hardware values to whatever scale the OS wants to use.

The JoystickTest file is basically a regression test I use anytime I modify the library to verify I have not broken anything. The regression test is made up of many "steps". Every time the loop function is executed, the function checks to see if it is time to run the next "step" in the test. If it is time to run the next step, it is executed. For example, the first time loop runs, step 1 is run. Step 1 happens to be the first step in the testSingleButtonPush test, which releases all buttons and pushes the first button. The next time loop runs and determines it is time to run a step, step 2 is executed. Step 2 happens to be the second step in the testSingleButtonPush test, which releases all buttons and pushes the second button. When it has run all the steps of all of the tests, it goes back and runs step 1 again. I would not base any "real" implementation on the JoystickTest file (it is just a regression test). Gamepad example, JoystickButton example, etc. are more realistic examples.

SarthakG10 (author)MatthewH2017-08-25

Thank you Matthew! I was trying to use an arduino+joystick as an HID for a Unity game. However, for some reasons, Unity was not behaving properly with negative values (-32768-0). I found some suggestions like convert the analogRead values to half the scale, {map(val, 0,1023, 512, 1023)}. Then send the converted value to the Joystick.setXAxis(val) method. This method maps the 512-1023 values to 0-32767 and works fine with Unity. But this seemed more like a hack and I was looking for a better solution. I was able to make the changes you suggested using the HID Descriptor Tool. Thanks for your guidance.

BTW, I also tried to connect the same joystick to Unreal Engine. Apparently, Unreal Engine only accepts XInput devices by default. That being said, they do have an old, "RawInput Windows" plugin, which is supposed to work with legacy controller devices. I tried out the plugin, but could not make it work with my joystick. Any suggestions on how we can make the Arduino look like an XInput Device? I know about the X360CE emulator software, but it would be much better if we can do it directly on the arduino, instead of having a third party middleware.

Thanks again!


MatthewH (author)SarthakG102017-08-31

Unfortunately I have not used Unity or Unreal Engine, so I do not know. You could post your question on GitHub ( Someone else who uses the library might have an idea.

LIVEY3 (author)2017-08-09

32button hardware mappings Leonardo schematic?

MatthewH (author)LIVEY32017-08-20

There are various techniques one can use to support more than one button per digital input pin. I have listed a few for your reference:

Hope these help,


SondreL1 (author)2017-06-30

Hello, im trying to use a arduino pro micro as a game controller to put into a gameboy case for a raspberry pi. Im as good as new to programming so this is kind of a problem for my part. I need just a simpel button board with 14 buttons, id really apreciate if anybody had a toturial og a helping hand in the matter.
Looking forward to what you have to say, have a nive day :)

MatthewH (author)SondreL12017-07-06

The latest version of this Arduino Library ( has a simple Gamepad example. The following Instructable shows how to use that example: It get to 14 buttons, you just need to follow the patterns established by that example. Hope this helps.

Goustoulos (author)2017-04-23

hello Matthew! thanks for everything!

i am modding an old ps2 racing wheel to work on my pc, and you helped me so much! i have already made my X and Y axis, and they are working great! now i want to write the code for the 8 buttons. i am guessing that i have to use switch or if, right?

thanks once again! have a great day!

Goustoulos (author)Goustoulos2017-04-23

i have wrote the code, and everything works like a charm! thanks once again Matthew!

here is my code if anyone is interested in using it, or imporving it(bevause i know its not going to be good :P)

#include "Joystick.h"

Joystick_ Joystick;

void setup() {




pinMode(6, INPUT_PULLUP);

pinMode(7, INPUT_PULLUP);

pinMode(8, INPUT_PULLUP);

pinMode(9, INPUT_PULLUP);

pinMode(10, INPUT_PULLUP);

pinMode(11, INPUT_PULLUP);

pinMode(12, INPUT_PULLUP);

pinMode(13, INPUT_PULLUP);

int lastButtonState = 0;


void loop() {

int button0Val =digitalRead(6);

int button1Val =digitalRead(7);

int button2Val =digitalRead(8);

int button3Val =digitalRead(9);

int button4Val =digitalRead(10);

int button5Val =digitalRead(11);

int button6Val =digitalRead(12);

int button7Val =digitalRead(13);

int xAxis = analogRead(A0);

int yAxis = analogRead(A1);



Joystick.setButton(0, !button0Val);

Joystick.setButton(1, !button1Val);

Joystick.setButton(2, !button2Val);

Joystick.setButton(3, !button3Val);

Joystick.setButton(4, !button4Val);

Joystick.setButton(5, !button5Val);

Joystick.setButton(6, !button6Val);

Joystick.setButton(7, !button7Val);


Arduser_ (author)Goustoulos2017-05-27

Thank you! Thats exactly what I was looking for :)

cool stuff right! i just added 360 pedals to my flight setup no going back now. checkout my youtube if your interested it modding ;) ive got some idea coming for the future. im learning alot.

StarcitizenModder (author)2017-04-26

Great job with this mate. Days and days of fun you basically taught me coding, i wouldn't have learned it if i didnt want to modd my joysticks lol it kept me going.

i have a question if you can answer it. i was wondering if i could use this libraby on a teensy board? to easly manage 32 buttons. Thanks again

Any Arduino compatible board based on the ATmega32u4 should work. That being said, I personally have only tested using the Arduino Micro and Arduino Leonardo. I try to keep the list of "supported" board up to date on the GitHub repository ( Based on the Teensy website (, it seems like the Teensy 2.0 should work, but I am not sure about the others (Teensy++ 2.0, Teensy 3.0, Teensy 3.1, etc.) since they have different microprocessors. If you do try the library with a Teensy, let me know if it works or not. Thanks.

Yes Sir! i might try both.

for science. ;)

i have already ordered a 3.6 :/ i know that wont work with the same code. but thanks for the 2.0 advice. i will let you know what i learn.

JasonG255 (author)2017-03-21

Thank you so much for this Instructable. How ever. Is there a
tutorial that you know of that finishes it off with the coding and
button schematics to full fill the 32 buttons and axes?.

When I
saw this I was looking for a DIY button controller. When I saw this it
had enough buttons and axes for exactly what I wanted. I went and bought
the Leo and a kit and a bunch of buttons. Got the Leo to work on
Windows but now I am stuck and trying to find a way to wire 32 button
and all the axes.

Thanks for any replay you can provide. Thanks

MatthewH (author)JasonG2552017-03-25

JasonG255 - The easiest way to get more that 16 buttons on a Leonardo or Micro is to use a series of Shift Registers. The Arduino website has a tutorial on how to use these at Hope this helps. -Matt

is buying a teensy board easier? lol i would have to lean more on shift registers. i only know a little.

Any Arduino compatible board based on the ATmega32u4 should work. That being said, I personally have only tested using the Arduino Micro and Arduino Leonardo. I try to keep the list of "supported" board up to date on the GitHub repository ( Based on the Teensy website (, it seems like the Teensy 2.0 should work, but I am not sure about the others (Teensy++ 2.0, Teensy 3.0, Teensy 3.1, etc.) since they have different microprocessors. If you do try the library with a Teensy, let me know if it works or not. Thanks.

cracked it? its not beyond you trust me. if you haven't just take an hour out your day to look over the code that Matthew wrote and you'll be able to work out where to squeeze your buttons. ill be doing arduino tutorials on my channel soon sub

compactrhone (author)JasonG2552017-03-28

would making a switch matrix and using the keypad register work?

GiuseppeL19 (author)2017-04-17

Hi Matthew,

I'm trying this code to use a joystick but I have problems

Z axis works while X-axis and Y no.

#include "Joystick.h"

Joystick_ Joystick;

void setup() {



void loop() {

int xAxis = analogRead(A0);

xAxis = map(xAxis,0,1023,-127,127);


int yAxis = analogRead(A1);

yAxis = map(yAxis,0,1023,-127,127);


int zAxis = analogRead(A2);



Thanks in advance,

MatthewH (author)GiuseppeL192017-04-17

How are the X and Y axis behaving (e.g. not moving at all, they are erratic, they do not move the full range, etc.)? Have you tried debugging the values coming in from the analogRead function or the output of the map function?

You could also try the latest version of the library ( and see if that works better for you. You will not need the map function call with the latest version of the library.

GiuseppeL19 (author)MatthewH2017-04-20

Hi Matthew,

X and Y axises as well as Rx and Ry are moving irregularry and when I try to move the sticks, they go crazy!If I use Serial as axises reader the value goes from 0 in the middle 127 to left -127 to right. Axis Z and Rz are perfect. I'm using the Library last version.

this is the code:

#include "Joystick.h"

Joystick_ Joystick;

void setup()




void loop()


int xAxis = analogRead(A0);


int yAxis = analogRead(A1);


int zAxis = analogRead(A2);


int rzAxis = analogRead(A3);



tiopepe (author)2017-04-04

Hi Matthew,

I'm using your library to realize an joystick.

It is possible to change the name of the gamepad?

I mean, Can I to change the name that appear in "device and printers" list from "arduino Leonardo" to "topolino"?

Thanks in advance,


MatthewH (author)tiopepe2017-04-05

I have never done this, but there is a discussion about this on GitHub at

PeterH344 (author)2017-03-19

Hi Matthew,

I'm using your library to realize an analog handbrake.

Does it make sense to reduce the amount of traffic sent to the PC by reducing the frequency of calling the send command (directly or indirectly with autosend)? Currently I call the send operation only if the input value has changed. I'm wandering if the data is anyway sent with 100Hz to the PC so that this does not make sense at all!?

Thanks for any help and your great library,

MatthewH (author)PeterH3442017-03-20


I think you are OK either way. You can get by with only sending data when the values change, but sending at a rate of 100Hz should be OK as well. I do not think you would want to send any more frequently than that, however.


PeterH344 (author)MatthewH2017-03-28

Hi Matthew,

Thanks for your help! Finally I implemented it so, that data is only set if the change of the value is larger than a specific change tolerance which can be set by a constant:


MatthewH (author)PeterH3442017-03-29

Glad to hear you got it working the way you wanted. Thanks for sharing your link.

PeterH344 (author)PeterH3442017-03-20

If I understand correctly, it does not makes sense to reduce the frequency of send operations on the device side...

From []:

"The host periodically polls the device's interrupt IN endpoint during operation. When the device has data to send it forms a report and sends it as a reply to the poll token."

MatthewH (author)PeterH3442017-03-20

It does take some of the host CPU time to process the HID Reports coming in, so you do not want to overwhelm the host computer with non-stop messages, but 100Hz should be fine.

netbuddy (author)2017-03-25

Funnt really, I asked in the Arduino community for some help with making my own HID type interface for such a gizmo and I got nothing but demands for code that I didn't have and no help whatsoever.

*thumbs up* for a nice instructable.

*thumbs up* for a very nice instructable.

Arendv3 (author)2017-03-05

Hi Matthew,

Great job on the Joystick library.

I have a few questions. The game controller shows up as an Arduino Leonardo, is it possible to change its name?
Connection shows as a com port, dis you ever think about porting to LUFA and be able to assign a VID and PID?

I want to implement reading buttons from CD4021 shift registers. There is code for it that I could use, but was just wondering if you have ideas about this?



MatthewH (author)Arendv32017-03-15


There is a current thread out on GitHub that is discussing renaming the Arduino at I have been wanting to investigate this for some time, but have not had the time. :(

Using a shift register (like the CD4021) should be fine. I have used 74HC595 shift register on other Arduino projects without issue.


StarcitizenModder (author)2017-02-16

Greatjob!!! you have taught me soo much. thankyou ;)

Aracuan (author)2016-12-03

Hi Matthew,

thanks for this library!

I just found
out that MULTI_AXIS does not work on the Micro, GAMEPAD does. In my case
the Micro was recognized as a com port without the slightest chance to
enter the game controller properties... Took me only 5 hours to find out

(tested on Win 7/64(10.6.13) and MacOS Sierra (10.6.8))

is tempting just to read several analog inputs one after another, but
that is a trap: The analog inputs affect each other if you do not place
"delay" or "(void)analogRead" between them.

First part of my project was reanimating some gameport rudder pedals for DCS.

In the next part I will use an old MS Strategic Commander for absolute view control with programmable presets...

used to work with Digisparks but they are limited to two axes if you
connect them via USB. Maybe I will multiplex around that problem, but I
learned a lot tonight and I really like the power of 32 buttons and 8
axes. Thank you very much!



MattiV (author)2016-11-23

just i test this and found arduino micro controller and buttons, but how add and use all axis 12 pcs analog input pin to potentiometers ? i try add pot but no response no found. pot only do button 3, on/of game controller.

MatthewH (author)MattiV2016-11-23

I recommend going through the Analog Read Serial example on the Arduino website ( If you can get that working, you can use that value as an input into the Arduino Joystick Library.

MattiV (author)MatthewH2016-11-23

how add joystick code this, i no understand good ? i need only read all analog input and then send data to game (FSX) simulator need read data what joystick do,
i need add arduino micro to usb-hid read all 12 analog input and flight simulator X use this, yuoke,trim wheels,rudder,trottle,propel,mixture,brake toe, test and micro show my device manager ok, and game controller show too good.
have you example one potentiometer how add to micro and working ?
then i maybe can understand and add all more axis and sliders to micro.

MatthewH (author)MattiV2016-11-23

I am currently finalizing Version 2.0 of this library. Once that is finalized, I will try to do a Instructable on using a potentiometer with the new version of the library (it may take me a while to get around to it, though).

MattiV (author)2016-11-23

i no understand thats do 3 arduino micro joystick my device manager, and run something tes prcedure move joystic but i no have connect any potentiometer and button this ? how made own program and add pot this ? i know only pot left to 5volt, right to gnd and center to A0-5 or 12,11,10,9,8,6,,4 pin but how code read analog pins ?