In my opinion, one of the more novel things you can do with an Arduino is put it to use as a custom game controller for your favorite games. Whether you’re retrofitting a Nerf gun, converting a rhythm controller to play an FPS game, or playing PUBG with a frying pan – using an Arduino makes it quick and easy to build your own custom controller.

In this tutorial, I’m going to show you how to program your own Arduino to emulate an Xbox controller using the ArduinoXInput library.

Getting Started


The first thing you’ll need is an Arduino-compatible microcontroller that has native USB support. Supported boards include:

Using a Leonardo or 5V Pro Micro is my usual suggestion, although if you need a little more ‘oomph’ you can pick up a Teensy LC or Teensy 3.2. This is not a complete list however! Check the supported boards list in the library repository to see if your board is compatible.

Note that the Arduino Uno, Nano, and Mega are missing from this list. Those three boards do not have native USB support and will not work for this. You will need to buy another microcontroller. Sorry Charlie 🙁


The next thing you’ll need is the software to make this work. There are two separate but related pieces: the boards package that contains the USB descriptors for the XInput controller, and the library that makes it easy to interact with.

Boards Package

First, you’ll need a copy of the XInput boards package for your specific microcontroller. Because of the way this XInput emulation works it’s not possible to include the USB descriptors with the library – it requires modifying the Arduino core files which means installing some purpose-built boards files.

As of this writing, there are three boards packages available:

You need to download the one(s) required for your microcontroller and install them by copying the relevant files to your Arduino installation’s ‘hardware’ folder. Make sure you have the latest version of the Arduino IDE to avoid any issues.

After you have installed the new boards packages, restart your IDE and you should see the new boards available in the ‘Tools’ menu. The AVR boards will have “w / XInput” in their name.

XInput AVR boards, properly installed and available in the IDE

XInput Library

Next, you’ll need a copy of the ArduinoXInput library. You can install this like any other Arduino library – download the latest release as a .zip file and use the IDE’s library manager to install it ( Sketch -> Include Library -> Add .ZIP Library ).

Upload Instructions

A word of warning: as a consequence of using the USB layout of an XInput device, the programmer auto-reset will no longer work. Don’t worry, you can still use the bootloader to program the board! You will just have to reset it by hand when uploading. (This section does not apply if you’re using a Teensy 3 board or a dedicated programmer.)

To do this you need to know where the ‘reset’ button is on your Arduino. If your board does not have a ‘reset’ button, you can wire your own by momentarily connecting the ‘reset’ pin to ground.

To upload a new sketch, connect the board to your computer using a USB cable, and make sure you have the proper board selected in the IDE’s ‘boards’ menu (with or without XInput). If the board already has an XInput sketch on it, you do not need to select a serial port. You should also turn on ‘verbose output’ for uploading in the Arduino IDE’s preferences (File -> Preferences). This makes it easier to time the manual reset and see if the upload succeeded.

To upload to the board:

  • Press the ‘Upload’ button in the IDE
  • Wait until the status bar says “Uploading…”
  • Press the reset button twice, quickly

If you did these steps properly, the board should reset to the bootloader and the upload should begin. AVRDUDE will do its thing and you should see avrdude done. Thank you. near the bottom of the output window. Note that the IDE may say that it “Couldn’t find a Board on the selected port” even if the upload succeeded. This is why it’s important to turn on the verbose uploading output – look for the avrdude message.

Do not upload XInput sketches to your Arduino unless you know how to reset it! Otherwise you will not be able to program it anymore and you’ll have to reflash the bootloader with an external programmer. You’ve been warned…

Hello World

Now it’s time to put this baby to the test. In the IDE’s menu, go to File -> Examples -> XInput and load the “Blink” example. Here’s what it looks like:

The example will press and then release the controller’s “A” button every two seconds. It’s a good way to test that the XInput emulation is working properly.

Double check that you have the correct board selected in the “Tools” menu and that you’re using the “w/ XInput” version. Upload the sketch to the board, making sure you follow the uploading instructions above.

On Windows you can test the output by using either the joystick control panel (Run: joy.cpl) or, preferably, a more detailed interface like HTML5 Gamepad Tester. You should see the “A” button (#1) steadily blinking on and off. Success!

Using the Library

“Blinking” buttons is fun, but we’re just scratching the surface with what’s possible. The library gives you access to the following controls available on the Xbox 360 controller:

  • 10 + 1 Digital Buttons
  • 2 Analog Joysticks (16 bit)
  • 2 Analog Triggers (8 bit)
  • 1 Four-Way Directional Pad (D-Pad)

In addition to these, you can also read the state of the virtual rumble motors (big and small), and even get the pattern that is running on the LED ring. Let’s jump in!


To set up the library, you need to include the library header and then call XInput.begin() once in the setup function:

The USB data is automatically handled by the library, although you can choose to handle the output yourself if you want to update a bunch of controls at once:

Digital Inputs


There are three functions for dealing with the buttons: press(), release(), and setButton():

There are ten buttons on the controller, plus the center ‘Xbox’ button. Here is the list:

Pass these values into the button functions above to ‘press’ or ‘release’ the respective buttons.

Directional Pad (D-Pad)

The directional pad inputs function the same as buttons, and you can use the button functions (above) to manipulate them with the following names:

You can also use the setDpad() function to set all four of these at once. The function takes four boolean values, one for each direction: up, down, left, and right:

For use with fighting games, this function also includes a simultaneous opposite cardinal directions (SOCD) cleaner to avoid erroneous states (up and down is up, left and right is neutral).

Analog Inputs


There are two joysticks: JOY_LEFT and JOY_RIGHT. Both of these have two axes (XY) and use 16-bit signed values (-32768 is min, 32767 is max, and 0 is centered). The north-east corner of the joystick is positive for both axes.

To set the joystick value, call the setJoystick() function. The first argument is the joystick ID, the second is the ‘x’ position, and the third is the ‘y’ position:

As of version 1.1.0 there is also a function to set the joystick using four digital inputs (like a direction pad), for use with arcade joysticks that use micro switches instead of potentiometers:

Version 1.2.0 also adds functions to manipulate the joystick axes separately, in case you’re mapping independent potentiometers (e.g. for a racing wheel) or other types of inputs. Prior to this, you would have to pass the ‘center’ value for the pre-scaled joystick range for the other axis:


There are two triggers: TRIGGER_LEFT and TRIGGER_RIGHT. These use 8-bit unsigned values (0 is min, 255 is max) where the trigger is normally ‘off’ at 0. You can set the values for these by calling the setTrigger() function:

You can also use button functions (press(), release(), etc.)  to manipulate the analog triggers as if they were digital buttons. This will ignore the range and just set them to their min / max values.

Range Rescaling

The library provides built-in range rescaling options for both the joysticks and the triggers! This means you can set an input range for the functions and pass the raw values to the library without having to rescale them beforehand. For example, you could set an input range of 0 – 1023 to use a value from analogRead(), or set a range of 48 – 57 to use an ASCII number value from ‘0’ through ‘9’.

This rescaling is entirely optional. If you don’t set a custom range, the functions will use their output ranges by default (16-bit signed for the joysticks, 8-bit unsigned for the triggers). Values outside of the output range will be clipped to the min/max values, so you don’t have to worry about overflow.

Debug Mode

I know this can get confusing and it can be difficult to keep track of what’s going on without being able to print over serial, so the library comes with a ‘debug mode’! Just set your USB-capable board to the non-XInput version and the library will print a nicely formatted output of all of the control states for you, instead of acting like an Xbox controller:

Rumble Motors and LED Patterns

The library also gives you access to the XInput data the Arduino receives. Namely, the state of the gamepad’s two rumble motors and the pattern playing on the LED ring.

There are two rumble motors: a ‘big’ one in the left grip and a ‘small’ one in the right grip. These are stored as 8-bit unsigned integers (0 – 255), where the normal state is ‘0’ for off. There are functions for getting these values separately, or combined into a single packed 16-bit value:

The LED patterns work similarly. The pattern IDs can be retrieved by calling the getLEDPattern() function:

You can find an enumeration of the available LED patterns in the library’s header file. This library does not handle the LED animations themselves. For that you can use the Xbox 360 Controller LEDs library. For more information on the LED animations, see this blog post.

If you want to deal with these values as they come in, check out the ReceiveCallback example.

Example: Rocket League Controller

Now that you know the basics of using the library, let’s build a simple example to put it into practice! In this case, a barebones controller for Rocket League.


I’m going to be using some basic components that you should have on hand. You’ll need a breadboard, two tactile push-buttons switches, a 10K potentiometer or joystick, and an XInput-capable Arduino (I’m using an Arduino Leonardo). You’ll also need a few wires to connect everything together.

Both switches are going to be wired using the Arduino’s internal pull-ups. One pin of the button should connect to a digital IO pin and the other pin of the button should connect to ground. I’m using pins 2 and 3, but you can use whatever pins you like. The potentiometer should have pin 1 connect to 5V, pin 2 connect to an analog pin (I’m using A0), and pin 3 connect to ground. Here’s a Fritzing diagram of the completed circuit:



Now it’s time to connect these hardware inputs to the XInput outputs! There are a myriad of controls in Rocket League, but for now we’ll just focus on three:

  • Turning – Left Joystick X Axis
  • Moving Forward – Right Trigger
  • Jumping – Button ‘A’

At the top of the sketch, we’ll start by including the library and then defining some constants for our pins:

Next up is the setup() function. Here we’ll initialize the pins we’re using, set the input range for the joystick (potentiometer), and ‘begin’ the library:

Then in the loop() function we’ll add the bits we want to run continuously. First we’ll read the pin states using the built-in digitalRead and analogRead functions and then assign those values to the XInput controls, which are automatically sent to the PC:

Note that the digital read functions have a not operator (‘!’) to invert the output because we’re using the pull-up resistors, so ‘LOW’ is ‘pressed’. You can also see that I’m treating the trigger like a digital output by using the setButton function instead of the typical setTrigger function that takes an analog value. The potentiometer value is written to the joystick ‘x’ axis, and the ‘y’ axis is centered based on the constant we set at the top of the code.

Lastly, we’ll check whether the Arduino has received any commands to turn on the rumble motors. If the motors are supposed to be rumbling, we’ll turn on the built-in LED. Otherwise, we’ll turn off the LED:

And that’s it! Just 50 lines of code and we’re up and running. Here’s the sketch in full:


Time to take this baby for a spin! Upload the sketch, boot up the game, and head into Free Play (Training) to try it out!


It’s time to practice what you’ve learned! Try to make some changes to the Rocket League controller sketch. Here are some ideas to get you started:

  • Change the ‘jump’ button (A) to ‘boost’ (B)
  • Make the turning more responsive (narrow the range)
  • Turn off the ball-cam (Y) whenever the controller rumbles

If you have the extra hardware, try replacing the potentiometer with a two-axis thumbstick or add a few extra buttons for the missing controls.

Further Reading

That should give you a good overview of how to use the ArduinoXInput library to emulate an Xbox controller. For further reading, check out some of the library’s built-in examples. You can find them either through the IDE by going to File -> Examples -> XInput, or in the library’s repository on GitHub.

This library opens up so many possibilities. Let me know what you create!


Eric F · April 13, 2019 at 9:18 pm

Thank you so much for this! I just spent about six hours researching HID/PID report descriptors in order to get force feedback to work. Then I thought Xinput might work and wow does it seem so much easier with your code. I’ll let you know how it works out for me.

Nishar Ahamed · May 8, 2019 at 6:40 am


I have installed & copied the files from “ArduinoXInput-master” to Arduino/hardware folder. But I could not find any new X/ input boards from the Tools list..

Please help

    Dave · May 8, 2019 at 9:09 am

    “ArduinoXInput-master” is the library, which goes in your libraries folder. You need the boards files, which are specific to the board you’re using.

    The installation instructions are slightly different depending on which board you’re using. Please read the documentation on GitHub closely.

Ertugrul · May 11, 2019 at 4:55 pm


Is there anybody who is tested it with xbox 360 console? Is this works with 360 console?

I have a plan about convert ps2 mouse and keyboard data for 360 console. If this library and hardware work with 360 console, i think i can make it.

    Dave · May 11, 2019 at 5:35 pm

    This does not work with the 360 console. Licensed controllers use a hardware security method that has not been openly broken and this library does not replicate.

Kenny · May 31, 2019 at 1:27 am

Is it possible to emulate multiple controllers at once with the same arduino?

    Dave · May 31, 2019 at 10:10 am

    No. This emulates the Xbox 360 wired controller and the hardware doesn’t support displaying itself as multiple USB devices simultaneously. You would need multiple Arduinos to emulate multiple controllers.

Justin · July 8, 2019 at 2:25 am

I got the PC to see my Teensy LC as an Xbox controller with the Triggers being buttons but when i hook mine up to a Raspberry Pi running Retropi… triggers are not recognized. Everything else is.

    Dave · July 8, 2019 at 11:37 am

    Yep, I just tested that as well and it looks like RetroPie refuses to see the trigger axis unless it moves progressively and not all at once. If I were you I’d report a bug to the RetroPie GitHub repository with steps to reproduce.

    For a workaround you could write a function to ‘step’ the trigger from pressed/released over a series of updates, but that will introduce some delay.

Piotr · July 8, 2019 at 4:37 pm

Hi, is it possible to use 4 pots (two for x axis and two for y axis) instead of just 2 (one for x axis and one for y axis)? I was messing around with another xinput library (MSF-XINPUT) and I have exhausted all possibilities without a positive result so I thought that maybe your library will be more flexible. I need every direction (left, right, up, down) to hove its own potentiometer.

    Dave · July 8, 2019 at 4:55 pm

    Yes and no.

    You can use two potentiometers for each direction but there’s no way for them to be wholly separate because they feed into a single axis. The controller doesn’t have values for each direction, just a sliding scale for each axis. Let me put it this way: if you have 25% left and 25% right it’s no different than having 0% left and 0% right because they get summed together before they’re sent to the PC. The PC won’t see any change so long as both axes are perfectly opposed. That has nothing to do with the library, that’s just the way joysticks work.

    That being said, you can absolutely do that. I don’t know why you’d want to, but it’s easy enough to do. Read from two potentiometers, invert one value and sum the result, then pass it into the joystick function.

    Remember that the library is just a tool not the complete solution. You’ll almost always have to write a little bit of code to supplement it.

      Piotr · July 8, 2019 at 5:12 pm

      Many thanks for the prompt reply. I was able to use 4 separate pots to control one analog stick by modifying the MSF-XINPUT so I am not a complete newbie but I was not able to make both analog sticks (left and right) work simultaneously on my Teensy LC. Mostly because I’ve used “while” functions and it is impossible to have two “while” functions running at the same time. With that being said I will try now your solution by read from two potentiometers, inverting one value and summing the result.

      Piotr · July 8, 2019 at 5:31 pm

      Sorry for bothering you but your library is much more complicated (although I think meticulous would be a better word) and I am struggling a bit with it. I guess this is the first part I need to modifie?

      const int Pin_LeftJoyX = A0;
      const int Pin_LeftJoyY = A1;
      const int Pin_RightJoyX = A2;
      const int Pin_RightJoyY = A3;

      and this is the second part:

      if (UseLeftJoystick == true) {
      int leftJoyX = analogRead(Pin_LeftJoyX);
      int leftJoyY = analogRead(Pin_LeftJoyY);

      if (InvertLeftYAxis == false) {
      leftJoyY = ADC_Max – leftJoyY;

      XInput.setJoystick(JOY_LEFT, leftJoyX, leftJoyY);

      Can you help me by adding the necessary lines of code in the second part? Normally I would not ask for such a thing but it would take a minute to type these few lines of code for you and hours of trial and error for me.

        Dave · July 8, 2019 at 6:31 pm

        That’s part of an example, not the library itself. You shouldn’t need to modify the library at all to get this done.

        Just read from whatever potentiometers you want, add them together, and call the joystick ‘set’ function. Something like:

        int x = analogRead(Pin_JoyLeft) + -analogRead(Pin_JoyRight);
        int y = analogRead(Pin_JoyUp) + -analogRead(Pin_JoyDown);
        XInput.setJoystick(JOY_LEFT, x, y);

        Then you just need to set the library’s joystick input range to 0 – 2046 (i.e. 1023 * 2). If you get stuck look at some of the other examples.

          Piotr · July 8, 2019 at 6:46 pm

          Thank you very much for your help. I will try everything that I’ve learned today and post the results.

          Piotr · July 8, 2019 at 6:52 pm

          One last thing just be sure. Where exactly can/should I set the library’s joystick input range to 0 – 2046 ? Remember I am not that familiar with your code as you are.

          Piotr · July 8, 2019 at 7:18 pm

          nvm! I’ve tried your solution and it works perfectly! Thank you very much and good luck with all your future endeavours.

          Dave · July 8, 2019 at 10:28 pm

          Good, I’m glad you were able to figure it out!

Piotr · July 8, 2019 at 6:57 pm

just to be sure* sorry my english is not that good

Marek · July 9, 2019 at 8:59 am

Going from here, would it be possible to connect the Arduino via Bluetooth?

    Dave · July 9, 2019 at 12:49 pm

    Not with this method, no. To get this to work I reverse engineered the Xbox controller’s USB descriptors – the Bluetooth functionality is a different animal altogether.

Ryan · December 5, 2019 at 9:30 pm

Hi Dave,

How difficult would it be to modify this to work with Adafruit Feather Bluefruit LE 32u4? I actually got most of the inputs to work by loading my board with your Circuit Playground with Xinput firmware. But I need to access my Feather BT,

Would this involve more than copying and modifying the Playground’s variant file?

Thanks for creating this awesome setup!

    Dave · December 7, 2019 at 10:58 am

    It shouldn’t be hard at all. Take a look at my commits to the SparkFun boards repo, the changes needed are going to be very similar.

    In a nutshell, you need to:

    * Duplicate the Adafruit boards folder
    * Modify the platform name, so it’s unique in the list
    * Modify the board name so it’s unique in the list
    * Modify the USB PID / VID descriptors
    * Change the core to use the XInput AVR core

    It sounds more complicated than it is since the core modifications do most of the heavy lifting. Let me know how it goes!

Wes · December 15, 2019 at 1:13 pm

Is it possible to configure my Teensy 3.2 to send XInput along with Keyboard and Mouse inputs? (Similar to the built in “Keyboard + Mouse + Joystick” USB Type)

I followed the instructions in \hardware\teensy\avr\cores\teensy3\usb_desc.h to add the relevant interfaces to the USB_XINPUT define but no dice. It manages to compile and upload, but with many “excess elements in array initializer” warnings. Then Windows gives me an “Invalid Device Descriptor” error and does not work whatsoever. You won’t be able to upload to the Teensy in this state. But if you press the reset button on the Teensy, there is a three second window where you can upload a sketch. I’ve just been using the default Blink sketch (on USB Type Serial) then pressing the reset button and upload button simultaneously. Then it uploads and functions again.

Here is my modified the USB_XINPUT define in usb_desc.h:

The only changes are: Adding the Keyboard, Keyboard Media Keys, and Mouse interfaces; Adding an ENDPOINT7 as transmit, and setting those three interfaces to it; Changing NUM_ENDPOINTS to 7.

I didn’t change anything above those, which I think is part of the problem, since that includes all the descriptor stuff. I am completely lost on those fronts however.

Interestingly NUM_INTERFACE was already set to 4. I don’t know if XInput counts as 4 interfaces and it needs to be set to 7 now but it hasn’t made a difference either way.

Here is the compiling log: (line 547 is kind of hilarious given the circumstances)

And my test sketch is simply your Hello World example but with an added keyboard press:

Any insight would be appreciated!

    Dave · December 15, 2019 at 1:38 pm

    Hi Wes. Unfortunately no, you cannot use XInput along with Keyboard and Mouse (or any other USB descriptor, for that matter).

    Keyboard + Mouse + Joystick works because those are all class-compliant descriptors, and USB is designed to be extensible like that. So you can just throw compatible descriptor types onto the end of the configuration and it will work. Look at the AVR Arduino “PluggableUSB” API for reference.

    XInput is a closed standard, which is why I had to reverse engineer the descriptors myself and why the project is strictly for hobbyists and non-commercial projects. The way this works is by telling the PC that the Arduino/Teensy is a genuine Microsoft-branded Xbox 360 controller. The PC then loads the official Microsoft driver for Xbox controllers and everything works smoothly. When you add additional descriptors onto the end, the PC no longer recognizes the controller as the official Xbox controller and everything stops.

    Until Microsoft opens their standard, the only way to get XInput working for hobbyist projects is to imitate an existing product that is supported by the official driver.

      Wes · December 15, 2019 at 2:01 pm

      Thank you for the quick response! I guess my only option is to use Keyboard + Mouse + Joystick USB type then use a software emulator like x360ce, which I was trying to avoid due to input lag concerns. But if it is too bad, I suppose I’ll still use this library and work with the available 360 controller buttons.


Alex · December 26, 2019 at 12:02 pm

As seen in all examples, there is never a use of attachInterrupts, instead always a use of digitalRead funktions. I wanted to make a steeringwheel with FFB and this looked like the best library. To get the steeringwheel angle I wanted to use a rotary encoder but here I need to use Interrupts. On a classic way I cant get the Interruptfunktions to be called, like it would be on a normal Joystick library. I#m using a Arduino Leonardo. Do you have any ideas for me?

    Dave · December 26, 2019 at 3:37 pm

    There is nothing in the XInput library that limits you from using interrupts. All of the examples use digitalRead() just because it’s simpler for users to understand, and because the AVR microcontrollers don’t have enough interrupt-capable pins to handle all of the inputs.

    Still, you shouldn’t need to call the XInput functions directly from the ISR. You should only need to update your tally of the encoder in order to keep the ISR as short as possible.

      Alex · December 27, 2019 at 9:09 am

      First of all thenk you very much for your quick response.
      I found my error in the code. I forgot to set the pinmode to input_pullup. Now I get the steering angle perfectly right thank you!

Josh M · December 27, 2019 at 2:09 pm

Hello, is it possible to use this to turn the xbox on and off? I’m hoping to do some home automation which would include toggling power to things in my “media center”. I see there is an input for the xbox home button which is used in powering up/off the xbox typically. I don’t have any of the parts for another month or two (just ordered for an unrelated project that I’ll probably rob from to do this if it works out) or I’d try it for myself!

    Dave · December 27, 2019 at 3:48 pm

    No, this does not work with any of the Xbox consoles.

Vincent · January 24, 2020 at 7:44 pm

I uploaded this to my arduino leonardo and I want to restore my arduino back to its original state. Any idea how to do this? I tried running the firmwareupdater example but it doesn’t work.

    Dave · January 25, 2020 at 12:19 am

    This doesn’t change anything low-level in the hardware, so all you need to do is upload a sketch that isn’t compiled using the “XInput” board version.

      Vincent · January 25, 2020 at 9:52 am

      None of my other scripts are working anymore. Thats why I want to remove it.

Vincent · January 25, 2020 at 10:20 am

The example scripts from the regular libraries work but it can’t find my other custom libraries here is the error produced when trying to use the hid-master library:

Arduino: 1.8.10 (Windows 10), Board: “Arduino Yún w/ XInput”

In file included from C:\Users\vinmr\Documents\Arduino\libraries\HID-master\src/HID-Project.h:39:0,

Multiple libraries were found for “HID-Project.h”
from C:\Users\vinmr\Desktop\AU3\sketch_jan15a\sketch_jan15a.ino:1:

Used: C:\Users\vinmr\Documents\Arduino\libraries\HID-master
C:\Users\vinmr\Documents\Arduino\libraries\HID-master\src/SingleReport/SingleAbsoluteMouse.h:28:10: fatal error: HID.h: No such file or directory

#include “HID.h”

Not used: C:\Program

Not used: C:\Program
compilation terminated.

exit status 1
Error compiling for board Arduino Yún w/ XInput.

This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.

    Dave · January 25, 2020 at 10:27 am

    As I said, to set the board back to default settings, all you have to do is upload a sketch that isn’t compiled using the “w/ XInput” board in the IDE. To set the IDE back to default, just delete any of the “xinput” boards files you added.

    No HID libraries will compile under the XInput board type because XInput overrides all other USB modes. Again, you need to use the non XInput board type if you want your board to behave “normally”.

    The error message there shows that the IDE has found multiple libraries that match what you’re trying to use. It’s likely that you’re having issues unrelated to the XInput library, and I’d recommend seeking help elsewhere.

Vincent · January 25, 2020 at 10:38 am

Is it possible to remove the avr dude completely, when i upload regular sketches the avrdude compiler messages still show up.

    Adam · January 26, 2020 at 11:50 am

    With this can you still communicate over the serial ports?

      Dave · January 26, 2020 at 6:22 pm

      You cannot use the USB (CDC) serial, no. You can still use the hardware serial pins on the board itself.

ROSANGELA SANTOS DIAS · February 20, 2020 at 6:20 pm

ola amigo, olha como faço pra colocar os motores nos pinos digitais? ja nao estou conseguindo intender direito.
obs: sou muito leigo e iniciante no assunto.

    Dave · February 20, 2020 at 11:25 pm

    I don’t speak Portuguese, so I’m just going by Google Translate here – you want to use the rumble data to drive motors?

    You need to find the motors you want to use, then pass the XInput data using the XInput.getRumbleLeft(); or XInput.getRumbleRight(); functions. How to drive a motor with an Arduino is well beyond the scope of this tutorial, though.

Chris · March 11, 2020 at 5:10 pm


Should it be possible to combine this with the Keypad library to map the digital buttons into a matrix reduce the number of pins required? I tried doing this to allow me to add the “Home” button onto Arduino Micro but am having issues.

    Dave · March 12, 2020 at 9:00 am

    There should be no issues using the XInput library with a keypad matrix, no. I’d recommend testing the matrix separately to eliminate any wiring issues before introducing the XInput code.

Dmytro Grechko · May 3, 2020 at 8:11 pm


Thank you for your tutorials and sharing your knowledge about the subject! It is very detailed and helpful.

Based on your experience, is it possible to create DIY Xbox One controller using the same methodology? If so, how would you approach it?

    Dave · May 4, 2020 at 7:44 am

    I have no experience with either the Xbox One console or Xbox One controllers, so I’m afraid I’m not much help there.

Francou · May 6, 2020 at 9:36 pm

The work you did is awesome! thank you, I’m on my way to realise my project nicely with your help 😃
Just a quick note to help the guys like me that spends 10 minutes on a simple error 😅… The sample code in the section “Joysticks” comport a mistake, there is an extra dot, at the line XInput.setJoystick.(JOY_LEFT, 0, 0); that becomes XInput.setJoystick(JOY_LEFT, 0, 0);. And If like me at the first time the code uploads without the quick double press on reset button trick, and then the code no more upload and shows a java exception, It seems that rebooting the computer computer rules the problem. Hope that can help someone.
Thanks a lot again you made an awesome tutorial, without It, I never would have been able to do my project that quick! 😃
Have a good day.

    Dave · May 7, 2020 at 5:24 am

    Thanks for the heads-up! It should be fixed now.

Jackson F. Silva · May 6, 2020 at 10:14 pm

Is it possible to edit the buttons available in the joystick?
For example, let’s say I want to make an arcade joystick with 4 DPADS and 6 buttons but I don’t want that the joy.cpl shows the other buttons of the controller that I won’t use, especially the XY axis.

    Dave · May 7, 2020 at 5:28 am

    Nope. The library emulates an Xbox 360 controller, so you get exactly what’s on the controller – no more, no less.

riccardo · June 10, 2020 at 4:11 am

Hi, i’ve succesfully configured my accelerometer as joy1 axis using your guide, but i have a problem, i’ve tried to assign some buttons following your rocket league example, but it looks they doesn’t works, i’ve tried many pins, 2, 4, 8 and 12.
May be because of MPU6050 library interfering with xinput ? as far as i know there are only 2 pins used by MPU6050 library, 7 for DMP interrupt and 13 for the led, and the two i2c connectors obviously.
Do you have any idea ? what can i check ? i’m quite noob with arduino, just received 2 days ago,
I have an Arduino Leonardo, thanks

    Dave · June 10, 2020 at 4:25 am

    Hi Riccardo. If I were you I would try testing without the accelerometer connected and using one of the examples in the library. For most the examples (including the one in this post) the buttons use the Arduino’s internal pull-ups and should connect from the signal pin to ground. Once you have the buttons working without the accelerometer, add the accelerometer back in and try to figure out if and how it’s affecting the button behavior.

      riccardo · June 10, 2020 at 9:28 am

      sorry i was missing the last command for buttons XInput.setButton(BUTTON_A, buttonA); everything is working now, except pins 2 and 3 tht are used by i2c (hardwired to the bottom, fortunately i’ve not fried anything as i’ve used them yesterday :), thanks

George Ulerio II · June 17, 2020 at 2:58 pm

So would it be possible to utilize parts of this control just one of the buttons on the controller itself rather than it be a complete emulator? I am trying to reconfigure one of my controllers where the controller feeds to the xbox the user input that is actually coming from a code being run on the arduino.

    Dave · June 17, 2020 at 3:24 pm

    I’m not sure I’m following. You wouldn’t be able to use this to control the buttons on the controller itself.

John M · June 18, 2020 at 5:16 am

Hi Dave,

Great work! Can this project work on Android? I’m trying to make a wired controller for my phone to control a drone. I’ve got everything working on PC but can’t seem to get it to work on Android.

Thanks in advance!

    Dave · June 18, 2020 at 5:19 am

    I’ve heard mixed reports about it working on Android. It seems that it works on some devices but not others.

      John M · June 18, 2020 at 6:06 am

      Thanks for the quick reply. Do you happen to know any specific devices it does work on? I’ll dig through some of my old phones in the meantime…

        Dave · June 18, 2020 at 6:46 am

        I don’t. I didn’t do any testing on Android, and it’s probable that the driver is trying to initialize one of the unallocated endpoints that Windows does not bother with.

          John M · June 18, 2020 at 7:04 am

          OK thanks.

          In case it’s of any use to anyone I’ve tested it on the following devices:

          Works: Galaxy Tab S5e, Xperia XZ, LG G3

          Doesn’t Work: OnePlus 7 Pro

          Dave · June 18, 2020 at 9:13 am

          Thank you for doing that testing. Could you tell me which Arduino board you’re using?

          John M · June 20, 2020 at 6:22 am

          Sorry for late response – I tested these with an Arduino Micro.

Michael · June 18, 2020 at 2:04 pm

Given that iOS 13 now supports Bluetooth controllers (or at least, certain ones, namely the PS4 controller and newer Xbox One controllers), would the XInput library be useful in making a controller emulator that works over Bluetooth instead of USB? For example, would it be possible to swap out the USB layer for Bluetooth?

To be fair, I know that the Bluetooth portion isn’t trivial. Sprinkle iOS into that mix, and it’s nothing but dead ends. I can’t find any proper documentation about what iOS expects. I suspect it’s all behind Apple’s MFI program paywall, and that puts it immediately out of reach for hobbyist.

    Dave · June 18, 2020 at 2:26 pm

    There’s two separate layers here: the library itself which provides a nice interface for the data and the “boards” files that supply the USB descriptors and make everything functional. There’s an internal API for passing data between them. The boards files are USB-specific, though the library on its own could absolutely be used for a Bluetooth implementation.

    That being said I have no knowledge about Bluetooth development and reverse engineering a Bluetooth device is well out of my wheelhouse at the moment.

      Michael · June 18, 2020 at 4:08 pm

      Thanks. For what it’s worth, as best I can tell, the way you say “I am a Keyboard” or “I am a Game Controller” with Bluetooth is very similar, or even the same, as how you do it with USB devices.

      That could be (and is) pure naivety speaking. We’ll see how I feel once I’ve attempted swapping out USB for BLE.

Pobbit · August 13, 2020 at 8:32 am

This is great. I have used a $3 Pro Micro from China to replace the zero-delay USB controller in my self-built arcade stick.
This has brought several improvements.
Firstly it now works with games that only support XInput.
Secondly, I have coded one of the buttons to enable/disable rapid fire, selectable from 8 different speeds via the joystick. Any fire button/trigger, can have any of the 8 speeds configured independently.
Thirdly, I can switch the joystick to emulate the left analog stick if required.

It can also be used to connect an old 8-bit Atari compatible controller to USB, with added functionality.

    Dave · August 13, 2020 at 8:41 am

    That sounds awesome! I’m so glad you found this useful.

Xuan · August 18, 2020 at 10:43 am

Hi there David! Great work on this library, it worked flawlessly on my Windows 10 machine. I am trying to make a controller with your library that works on an Android phone. I have seen some comments that some Android phones are not supported, mine may unfortunately be one of them.

Do you have any plans on testing and making it so that xinput could be recognized by a bigger majority of Andoird phones?

It would be greatly appreciated as I have also seen others on this website talking about It!

    Dave · August 18, 2020 at 10:46 am

    Hi Xuan. I do not own a newer Android phone and do not have access to one, so there’s unfortunately nothing I can do. If you are able to hook up a logic analyzer to the USB data lines I’d be happy to look at the decoded output, otherwise I’m afraid someone else will have to engineer a fix.

Pobbit · August 18, 2020 at 12:18 pm

It might be best to try this project instead, if your phone doesn’t support xinput:

remy · September 15, 2020 at 12:52 am

hello i sucessfull installed the code in a pro micro works but i trying to figure out the response time if there are some input lag and if it can be be lowered in some form. im playing a fight game and i suspect that there are a little time between push the button and the action but there are no traces in code of that. (and dont know if its the arduino or something more in the pc)
thanks for the tutorial and the time to make it

    Dave · September 15, 2020 at 10:59 am

    Unless your code introduces delays or sends more control packets than are necessary, there is no more input lag than with a standard Xbox controller.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Would you like to know more?