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
Hardware
The first thing you’ll need is an Arduino-compatible microcontroller that has native USB support. Supported boards include:
- Arduino Leonardo
- Arduino Micro
- SparkFun MaKey MaKey
- SparkFun Pro Micro
- Teensy 4.0
- Teensy 3.2
- Teensy LC
Using a Leonardo or 5V Pro Micro is my usual suggestion, although if you need a little more ‘oomph’ you can pick up one of the Teensy boards. 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 🙁
Software
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:
- Arduino AVR Boards
- SparkFun AVR Boards (requires the Arduino AVR Boards package)
- Teensy 3 + 4 Boards
You need to download the one(s) required for your microcontroller and install them. Specific installation instructions are provided in each repo. 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 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 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:
#include <XInput.h> void setup() { XInput.begin(); } void loop() { XInput.press(BUTTON_A); delay(1000); XInput.release(BUTTON_A); delay(1000); }
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!
Setup
To set up the library, you need to include the library header and then call XInput.begin()
once in the setup function:
#include <XInput.h> void setup() { XInput.begin(); }
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:
#include <XInput.h> void setup() { XInput.setAutoSend(false); // disable automatic output XInput.begin(); } void loop() { ... // Update control surfaces here XInput.send(); // send data over USB }
Digital Inputs
Buttons
There are three functions for dealing with the buttons: press(), release(), and setButton():
XInput.press(BUTTON_A); // press 'A' XInput.release(BUTTON_B); // release 'B' boolean yState = digitalRead(ButtonPin); XInput.setButton(BUTTON_X, yState); // press X conditionally
There are ten buttons on the controller, plus the center ‘Xbox’ button. Here is the list:
BUTTON_LOGO BUTTON_A BUTTON_B BUTTON_X BUTTON_Y BUTTON_LB BUTTON_RB BUTTON_BACK BUTTON_START BUTTON_L3 BUTTON_R3
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:
DPAD_UP DPAD_DOWN DPAD_LEFT DPAD_RIGHT
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:
// Sample DPAD states boolean upPad = true; boolean downPad = false; boolean leftPad = false; boolean rightPad = true; XInput.setDpad(upPad, downPad, leftPad, rightPad);
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
Joysticks
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:
// Center the left joystick XInput.setJoystick(JOY_LEFT, 0, 0); // Push the right joystick all the way to the right // and slightly down XInput.setJoystick(JOY_RIGHT, 32767, -2000);
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:
// Sample arcade joystick inputs boolean stickUp = false; boolean stickDown = true; boolean stickLeft = false; boolean stickRight = true; XInput.setJoystick(JOY_LEFT, stickUp, stickDown, stickLeft, stickRight);
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:
// Move the left joystick's X axis to center XInput.setJoystickX(JOY_LEFT, 0); // Move the right joystick's Y axis to full 'up' XInput.setJoystickY(JOY_RIGHT, 32767);
Version 1.2.4 makes it possible to invert a joystick axis when setting its value. To do this, pass a third argument to invert the value (‘true’ to invert, ‘false’ otherwise). Bear in mind this only works with the single-axis (X/Y) function, not the function to set both at once:
// Set the Y axis 'up' (not inverted) XInput.setJoystickY(JOY_LEFT, 32767, false); // Set the Y axis 'down' (inverted) XInput.setJoystickY(JOY_LEFT, 32767, true);
Triggers
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:
// Set the left trigger to halfway pressed XInput.setTrigger(TRIGGER_LEFT, 127); // Set the right trigger to max XInput.setTrigger(TRIGGER_RIGHT, 255); // Release the right trigger XInput.setTrigger(TRIGGER_RIGHT, 0);
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’.
// Set left / right ranges together XInput.setTriggerRange(4, 26); // for Wii Classic Controller XInput.setJoystickRange(0, 1023); // using analogRead (10-bit ADC) // Set one range individually XInput.setRange(JOY_LEFT, -1, 1); // -1 min, 0 middle, 1 max
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:
uint8_t bigRumble = XInput.getRumbleLeft(); uint8_t smallRumble = XInput.getRumbleRight(); uint16_t bothRumble = XInput.getRumble();
The LED patterns work similarly. The pattern IDs can be retrieved by calling the getLEDPattern()
function:
XInputLEDPattern currentPattern = XInput.getLEDPattern(); // using enum uint8_t patternID = (uint8_t) XInput.getLEDPattern(); // using unsigned int
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.
Wiring
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:
Programming
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:
#include <XInput.h> // Input Pins const uint8_t Pin_Joystick = A0; // Turn left/right const uint8_t Pin_ButtonA = 2; // Jump const uint8_t Pin_TriggerR = 3; // Accelerate // Output Pins const uint8_t Pin_LED = LED_BUILTIN; // Analog Input Range const int AnalogRead_Max = 1023; // 10-bit ADC
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:
void setup() { // Set input pin modes pinMode(Pin_ButtonA, INPUT_PULLUP); pinMode(Pin_TriggerR, INPUT_PULLUP); // Set output pin mode pinMode(Pin_LED, OUTPUT); digitalWrite(Pin_LED, LOW); // Turn 'off' // Setup library XInput.setRange(JOY_LEFT, 0, AnalogRead_Max); XInput.begin(); }
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:
void loop() { // Read pin states boolean pressA = !digitalRead(Pin_ButtonA); boolean pressTrigger = !digitalRead(Pin_TriggerR); int joystickValue = analogRead(Pin_Joystick); // Set button and trigger states XInput.setButton(BUTTON_A, pressA); XInput.setButton(TRIGGER_RIGHT, pressTrigger); XInput.setJoystick(JOY_LEFT, joystickValue, AnalogRead_Max / 2); // move x, leave y centered ...
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:
... // Get rumble value uint16_t rumble = XInput.getRumble(); // If controller is rumbling, turn on LED if (rumble > 0) { digitalWrite(Pin_LED, HIGH); } else { digitalWrite(Pin_LED, LOW); } }
And that’s it! Just 50 lines of code and we’re up and running. Here’s the sketch in full:
/* * Project Rocket League XInput Demo * @author David Madison * @link partsnotincluded.com/tutorials/how-to-emulate-an-xbox-controller-with-arduino-xinput * @license MIT - Copyright (c) 2019 David Madison * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include <XInput.h> // Input Pins const uint8_t Pin_Joystick = A0; // Turn left/right const uint8_t Pin_ButtonA = 2; // Jump const uint8_t Pin_TriggerR = 3; // Accelerate // Output Pins const uint8_t Pin_LED = LED_BUILTIN; // Analog Input Range const int AnalogRead_Max = 1023; // 10-bit ADC void setup() { // Set input pin modes pinMode(Pin_ButtonA, INPUT_PULLUP); pinMode(Pin_TriggerR, INPUT_PULLUP); // Set output pin mode pinMode(Pin_LED, OUTPUT); digitalWrite(Pin_LED, LOW); // Turn 'off' // Setup library XInput.setRange(JOY_LEFT, 0, AnalogRead_Max); XInput.begin(); } void loop() { // Read pin states boolean pressA = !digitalRead(Pin_ButtonA); boolean pressTrigger = !digitalRead(Pin_TriggerR); int joystickValue = analogRead(Pin_Joystick); // Set button and trigger states XInput.setButton(BUTTON_A, pressA); XInput.setButton(TRIGGER_RIGHT, pressTrigger); XInput.setJoystick(JOY_LEFT, joystickValue, AnalogRead_Max / 2); // move x, leave y centered // Get rumble value uint16_t rumble = XInput.getRumble(); // If controller is rumbling, turn on LED if (rumble > 0) { digitalWrite(Pin_LED, HIGH); } else { digitalWrite(Pin_LED, LOW); } }
Soccar!
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!
Tweaking
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!
211 Comments
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
Hi,
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
Hi,
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.
Berghopper · August 29, 2024 at 3:58 pm
I made a project that is able to do this somewhat: https://github.com/Berghopper/360-w-raw-gadget
This kind of falls back on the other post describing the USB descriptors and whatnot.
Essentially if you send the same descriptors for the input endpoints (just incremented addresses), you’re able to have multiple xinput devices!
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: https://pastebin.com/hqb1MEFr
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: https://pastebin.com/kMdVHtJ2 (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: https://pastebin.com/z6zsZnDZ
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.
Cheers!
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();
orXInput.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
Hi,
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
Hi,
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
Hi,
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 becomesXInput.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
Hi,
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:
https://www.instructables.com/id/Create-a-Joystick-Using-the-Arduino-Joystick-Libra/
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.
James Potter · October 17, 2020 at 4:09 pm
Hi Dave!
First of all, I am impressed and thankful for your XInput library. I teach engineering at Washington University in St. Louis, and I have a new course where we are making custom computer input devices and video game controllers. We’re using Arduino Leonardos, keyboard/mouse functionality, and your library to emulate an Xbox controller. We’re trying to play Rocket League on Epic Games, and Pixel Cup Soccer 17 on Steam. I’m having the same problem with both (see below).
I am running into a strange problem. I have installed the boards package and library, and uploaded the GamepadPins example. For some reason A0-A3 are not being read at all. Here are details:
– All of the discrete buttons work fine.
– A4 and A5 work fine as discrete buttons AND AS ANALOG INPUTS when I set “UseTriggerButtons = false;” This is the strangest thing.
– I have used a multimeter to verify that potentiometers hooked up to A0-A5 all provide a continuous voltage between 0 and 5 V.
– I have tried this on two different Leonardos and had the same problem.
– I have used your debugger, and found that
– A potentiometer hooked up to A4 or A5 changes the value in the debugger between 0 and 255. Strangely, the debugger shows both Right Trigger and Left Trigger values changing at the same time, even when my potentiometer is only connected to one of them. Both LT and RT stay at close to the same (but not exactly the same) value.
– When I connect the SAME POTENTIOMETER up to A0, A1, A2, or A3, everything stays at 0. All the time. I have not gotten any value other than 0 for A0-A3.
Please let me know if you have any ideas about what might be causing this. I have a good amount of practice debugging electronics, but this is defeating me at the moment. All I really want is some way to get analog steering and gas pedal for Rocket League. If it has to be all discrete, then so be it.
Your coding and comments are well-organized and easy to follow. My hat is off to you.
Best Regards,
Jackson
James Potter · October 17, 2020 at 4:34 pm
One more detail: when I use Arduino’s built-in example “AnalogInOutSerial,” the A0-A3 do work. They give values between 0 and 1023. So it seems specific to the XInput programs… is there any difference at all between how A0-A3 are handled/processed compared to A4 and A5?
Jackson
Alex Sin · October 24, 2020 at 10:54 pm
This worked beautifully. I had already made a nRF24 wireless controller out of a RC Car remote for another project. I was able to repurpose the remote to play PC games now by purchasing a Leonardo + nRF24 radio. Getting the reset timing was a little tricky, but once that’s understood you’re good to go! Major thanks.
Marco Balletta · November 1, 2020 at 5:28 pm
Hi Dave! Would ypu please be able to add support to the teensy 4.0 ?
The teensy 4.0 has dual channel for i2c that must be used for my locomotion project.
Thanks!
Dave · November 1, 2020 at 8:16 pm
Hi Marco. Cool project! Unfortunately I have no plans to add Teensy 4 support at this time. Modifying the Teensy 4 core files for XInput would be a significant undertaking, and I currently have no controller projects that require the Teensy 4’s hardware.
Have you considered trying one of the Teensy 3 boards? I know that both the Teensy LC and the Teensy 3.2 have two I2C buses onboard.
Marco Balletta · November 2, 2020 at 1:58 pm
Hi Dave, thank you and thank you so much for the reply. I did not know about the Teensy LC and the Teensy 3.2 having two I2C. I hope the 3.2 will be powerful enough to run the code and sensors as smoothly as on the 4.0. I will try. Thank you!
Dave · November 2, 2020 at 4:00 pm
Good luck!
Marco balletta · November 2, 2020 at 7:01 pm
Thank you!
Marco balletta · November 2, 2020 at 9:51 pm
Forgot to ask you.
How would you be able to make a wireless gamepad with a teensy 3.2? Do you have any suggestion?
I have used this method based on using a mini router and virtualhere
https://streamable.com/t4599
Marco balletta · November 3, 2020 at 12:21 am
Sorry, I do not see an edit button.
Wanted to clarify that I have used this method based on a mini router and virtualhere, to make wireless your xinput gamepad based on the Arduino leonardo. The previous locomotion system I have used, was based on just one i2c channel on an arduino mega mounting a digipot shield. The digipot shield on the arduino mega was replacing the joystick of the arduino leonardo. The arduino leonardo was connected via usb to the minirouter and the minirouter was wireless connected to my pc internet home network
This is the schematic of the connections
https://ibb.co/LzQMykr
Dave · November 3, 2020 at 11:05 am
That’s more-or-less what you’d have to do. The XInput library is a USB implementation only, so if you wanted to make it wireless you would need to send the data wirelessly to another Arduino acting as the USB peripheral (or as you’ve done with VirtualHere). I’ve seen people use both RF (900 MHz) and Bluetooth serial with success.
Marco Balletta · November 14, 2020 at 10:52 am
Hi Dave, thank you for your reply about the wireless connectivity.
I have another question.
Can your library support/mount two left joystick at the same time? The 2 left joystick would need to work at the same time. Can they?
Pratically 1 of the method i am using to inplement my locomotion system to the xinput controller , is by hook/wire connect my locomotion system to the teensy 3.2, in place of the left joystick.
Thanks!
Dave · November 14, 2020 at 11:14 am
I’m not sure I follow. By definition there is only one ‘left’ joystick on the controller. You can write to the function as many times as you like and add together as many inputs as you like to control it, but there is still only one joystick and thus one joystick output.
Marco Balletta · January 9, 2021 at 6:26 pm
Do you know if it is possible to use in games , at the same time , the arduino based xinput controller and the original PC game controller?
Thanks
Dave · January 9, 2021 at 8:12 pm
That’s entirely dependent on the game itself. Most games will treat separate controllers as, well, separate controllers.
Marco Balletta · January 9, 2021 at 8:30 pm
Thanks for the reply.
I am asking you the question, because i am wondering if i could somehow control the joystick of a pc gamepad with my arduino/teeensy based locomotion system , also without crearing a custom xinput controller.
In the video below , for example, i am using the locomotion system to move the avatar in vr games (to control the joystick of the original vr controller) , while at the same time i am using the original vr controllers
https://youtu.be/xwyrvjKMSsE
Do you have any suggestion for achievingthe same with a regular pc controller ?
Thanks
Dave · January 10, 2021 at 12:54 am
As I said, it’s entirely dependent on the game and how the game is programmed to use inputs. If you’re trying to work with a specific game you would need to contact the developer. Otherwise if you’re trying to work with any game you would likely need to modify the controller you’re trying to “inject” inputs into, or perform what is effectively a man-in-the-middle attack.
Marco Balletta · January 17, 2021 at 3:33 pm
Hi Dave, I have been trying to use your xinput gamepad with cronus ZEN for using your xinput gamepad on consoles
https://cronusmax.com/forums/showthread.php/205317-ZEN-compatibility-with-arduino-based-custom-quot-game-locomotion-system-quot?p=1250417#post1250417
Unfortunately for whatever reason the Zen can’t recognize your xinput as a gamepad.
Do you think maybe you guys could work together to add compatibility of your xinput code to zen ?
mario · November 22, 2020 at 12:51 am
Thanks a lot! it’s working like a charm!
Gusane · January 8, 2021 at 3:32 am
Hi Dave
I have a question, how can I invert the analog input of the potentiometer, I’m using a vertical one, and the data reading is inverted (turning the pot left outputs right on joystick) so, how can I change it so I can get the correct reading for a racing wheel for example
Thanks!
Dave · January 8, 2021 at 7:15 am
With math! Subtract the current value from the maximum of the range and then add the minimum of the range to get the inverse. In practice most analog to digital converter (ADC) functions will return an unsigned value (i.e. starting at 0) so you only have to subtract from the maximum.
I’ll use the Leonardo as an example. The 32U4 microprocessor has a 10-bit ADC, which means calls to `analogRead()` return a value from 0 – 1023. A potentiometer set to its minimum will return the lowest possible value (0), set to its max it will return the highest possible value (1023), and set to center will return the midpoint ((1023 – 0)/2 = 511.5). To ‘invert’ it all you have to do is subtract the current value from the max value, and then add the minimum. For example to convert “50% right” to “50% left” we would take the starting value (767), subtract it from the maximum of the range (1023 – 767), and then add the minimum which in this case is 0. This gives us the ‘inverse’ value of 256, which you can see is the same distance from the midpoint but in the opposite direction.
The library’s “GamepadPins” example has a demo of this here.
Gusane · January 8, 2021 at 7:42 pm
Thank you so much, it worked , also thanks for the demo
Dave · January 18, 2021 at 10:20 am
For what it’s worth I’ve updated the library to include joystick axis inversion. For the single axis functions (e.g. `XInput.setJoystickX()`) pass ‘true’ as the third argument (invert) to automatically invert the axis.
A-N-T-Z · January 14, 2021 at 6:49 pm
thank you so much – alot of possibilities with your good work, I used a 3.3v 8mhz 32u4 Pro Micro in combination with a mini-USB=2.0-shield, so i can intercept the USB stream from a vintage 2004 Logitech Mini steering wheel, and convince GTA its an xbox controller. Next step is to add a transparent bluetooth module so a combo-gun-steering-yoke-controller. Im building, can have xbox output for the steering and flying rather than performing a PWM keytap ) (GTA has very limited controller support) thanks again – brilliant
Giallapo Marcelo · January 15, 2021 at 7:45 am
Hi Dave, thank you for the incredible work you do here and the prompt replies to all of the comments. You set a high bar in the open source world. I have a quick question because I was confused about this at first: it is not possible to connect this to an Xbox360 or XboxOne an pretend to be a controller right?
My idea for a project was a “key repeater”, trying to beat predictable games like StreetOfRage4 etc. But I do not get my input recognized when I connect my Arduino to the Xbox One.
Thank you for your help and let me know if you have any suggestions on how to achieve that.
Dave · January 15, 2021 at 6:07 pm
Hi Giallapo. Unfortunately it is not possible to use this with a console. The consoles use a security method to verify that controllers are genuine that to my knowledge has not been openly broken.
Giallapo Marcelo · January 16, 2021 at 3:30 pm
Thank you. I found a nice way to connect the Arduino to the phone and emulate the games there using Xbox Pass (Cloud). Which works perfectly.
One last question for you. I hit most of the time problems while trying to upload to the Arduino Leonardo new code. It works once every many many times. Usually I keep getting this error:
avrdude: verifying …
avrdude: verification error, first mismatch at byte 0x0700
0x97 != 0x18
avrdude: verification error; content mismatch
avrdude done. Thank you.
Any idea?
Giallapo Marcelo · January 16, 2021 at 3:36 pm
I may have found a solution (not really sure why it works) but I want to add it for future reference. I am working from Ubuntu.
And I found this fix:
https://github.com/qmk/qmk_firmware/issues/8060
TL;DR: Running in your own terminal
sudo systemctl disable –now ModemManager.service
Will make the Arduino IDE able to upload things successfully.
Thanks!
Ian M · January 30, 2021 at 11:04 am
Hi, I’m a little worried about bricking my Teensy LC.
When attempting to upload the sketch and the Xinput for the first time, am I supposed to press the white button on the board twice, or am I supposed to hook up a button to the board to reset it?
Dave · January 30, 2021 at 8:42 pm
Hi Ian. Don’t worry about the Teensy, you won’t brick it. The first time you upload it should “just work” as it does normally. As long as an XInput sketch is on the board, just press the reset button once after the Teensy Loader application has loaded.
Mark Mcquillan · January 31, 2021 at 11:45 am
Hello Dave, I’m having an issue trying to set up the analog triggers on my project. I’m using hall sensors and each one has slightly different ranges for the amount of movement. One is 499 – 492 and the other goes 480 – 476.
I tried the following for the range in the setup loop:
XInput.setRange(TRIGGER_LEFT, 499, 492);
XInput.setRange(TRIGGER_RIGHT, 480, 476);
And then in the main loop:
XInput.setTrigger(TRIGGER_LEFT, analogRead(xb_L2));
XInput.setTrigger(TRIGGER_RIGHT, analogRead(xb_R2));
But I’m getting no response from them. Is there a way to get these to function properly?
Dave · January 31, 2021 at 8:31 pm
Hi Mark. Your numbers are backwards – the highest part of the range goes last (min then max).
But with such a narrow response window those look like digital sensors. Instead of setting the range, I’d recommend using the `setButton` function to treat them as digital and an ‘if’ statement to see if they’re past the threshold. E.g.:
Or more succinctly with a bool:
Mark Mcquillan · February 1, 2021 at 6:00 am
Hi Dave, I got it fixed. Couldn’t view my post to add a reply until now, but I suspected the range numbers were at fault, so I flipped the magnets around so the sensor reads an ascending value and that fixed it.
I was originally using the Arduino Joystick Library and it was causing various issues for what I needed it to do, switching to your library let me get my controller functioning exactly the way I wanted. Thanks for making this library, it saved me scrapping a few months of work.
Dave · February 1, 2021 at 7:21 am
Awesome, I’m glad you’ve got it working and that the library was helpful. Good luck on the project!
Pistol · March 9, 2021 at 2:56 pm
I’m trying to use your XInput library with my Teensy LC, but after uploading an XInput sketch, the controller doesn’t work in Windows 10. The sketch uploads OK, and the controller does show up in joy.cpl, but you can’t select it at all to see its properties and test the buttons. If I go into Device Manager, it’s showing up under Xbox 360 Peripherals, but with the yellow warning triangle against Xbox 360 Controller for Windows. If I go into properties there it shows in the device status window “This device cannot start. (Code 10) – Insufficient system resources exist to complete the API.” This also happens if I upload one of the example XInput sketches.
Do you have any idea what might be wrong? This device was working fine as a serial+keyboard+mouse+joystick device, but I really wanted to get it working with XInput rather than DirectInput. Any help gratefully received!!
Dave · March 9, 2021 at 3:52 pm
If the error message is to be believed that’s a Windows issue, and not anything to do with the library or the Teensy itself. I’d try updating or reinstalling the controller drivers and make sure Windows is up to date. If the board is connected through a hub I’d also try connecting it directly to the PC.
Pistol · March 9, 2021 at 5:33 pm
Thanks for your reply!
I did try updating the driver, but no luck – it just said I have the most recent version already. Did the same on another PC too.
I have previously changed the name and serial number of this Teensy LC; would those changes persist even when programming it in XInput mode, could that be causing the problem?
I have another Teensy LC that I’ve never used, I might try programming that with the simulate all buttons sketch to see if that one has the same result.
Pistol · March 10, 2021 at 8:01 am
Ok, I have now tried the simulate all example on a virgin Teensy LC, with the same result. I also tried a genuine wired 360 controller and that worked fine. Tested it on multiple PCs with the same result. So, bit confused now!
I wondered whether it could be related to the issue that stopped third-party 360 wireless receivers from working; the fix for that required editing the driver file to accept the third party device’s usb vid and pid. But, from device manager, the Teensy in XInput mode has the same vid and pid as my official 360 pad, so it oughtn’t be that.
Dave · March 10, 2021 at 1:51 pm
I don’t know what to tell you. I’ve just tested the latest version on two separate Teensy boards (3.2 and LC) and on two separate computers both running the latest update for Windows 10 and everything works swimmingly. Unless you can find some way to replicate the problem I don’t have a solution for you. My only advice would be to do the same things you would do if this were any other device throwing that error: restart your PC, try a different USB cable, try a different USB port, update or reinstall drivers, and update your operating system.
Pistol · April 10, 2021 at 3:58 pm
Sorry I didn’t see your reply earlier Dave, notifications were going into my junk folder 🙁
Just thought I’d let you know I got it working with a fresh install of the Arduino IDE!
Also Dave · March 28, 2021 at 4:47 am
can it assign a player number to the controller like I want this to always be player 2 or have 4 separate boards each hard set to a player number so if system reset or unplugged it stays the same player number. I was thinking using it in a arcade project and wouldn’t want a chance of the players sticks getting jumbled up after a reboot
Dave · March 28, 2021 at 5:53 am
Hi (also) Dave. No, you cannot assign a player number. Remember that all it’s doing is emulating an Xbox controller; if you can’t assign a player number with the controller, you can’t assign it with the Arduino emulating the controller. The player numbers are assigned by the host, usually based on the order in which the controllers are enumerated.
Also Dave · March 28, 2021 at 1:08 pm
Kind of what I thought. Thanks for the quick response!
Gotthard · March 29, 2021 at 8:19 am
Hi Dave, I’m asking for your help. My Xbox 360 Slim not accept/recognise the Xinput programmed controller, but with Win10 is identifies my Leonardo fine.
Sketch uploaded to a Leonardo with Arduino IDE 1.8.13 with necessary libraries installed. Any idea? What I made wrong?
Thanks,
Gotthard
Dave · March 29, 2021 at 12:29 pm
Hi Gotthard. Unfortunately this library does not work with the consoles.
Wes · April 1, 2021 at 11:09 am
Hey Dave. Do you know the update rate of this controller emulation? Recently I learned that polling rate is how often your PC checks for new data, not necessarily how often a USB device will update with new data. As it turns out, even though an Xbox controller will be set to a 25oHz polling rate by default, the controller itself only provides new button states 124 times a second (124Hz). Even if you use tools to increase polling rate, the controller still only provides new data at 124Hz.
Rocket League related in-depth controller video: https://youtu.be/ahsO5bhBUtk?t=212 (timecode 3:32)
Is your controller emulation fixed to the same update rate? Can it be increased?
Dave · April 3, 2021 at 4:22 pm
Hi Wes. Take that video with a grain of salt. After doing some more digging it looks like he’s testing with Rocket League and not measuring the controllers outputs directly, so both the game and the driver also influence his results.
The Xbox 360 wired controller has a USB polling rate of 250 Hz (low speed, endpoint 1 IN `bInterval` of 4). The controller will only send data when the control inputs have changed, otherwise it will NACK the request. The library emulates the controller’s USB descriptors and its update behavior. For what it’s worth both the controller and the Arduino will send updates at 250 Hz if the controls are changing that quickly (this can be confirmed with a USB analyzer). Additional bottlenecks would be at the driver or application’s end.
I would not recommend trying to change the update rate. You can edit the descriptors to do so but the driver may not like it.
Gray · April 2, 2021 at 11:49 pm
Hi Dave! Thanks for the tutorial, this is my first time to make an arduino project and I’m planning to make a stickless XInput PC controller.
I have a few questions about your example code.
Will this work code (https://pastebin.com/b9Kc5pYX) work for a stickless controller setup? I copied that from your example code and removed the parts that I don’t need. Can you proofread it please? It compiled successfully on the Arduino IDE but I may have missed/deleted something important.
Does XInput.setDpad(dpadUp, dpadDown, dpadLeft, dpadRight); have an innate SOCD cleaning built in to it? Or do I still need to make an if/else statement before this?
Am I right to remove all the analog parts of your because I’m only using all button setup?
Again… Thank you for the nice tutorial, also for providing a clean Xinput Library. Cheers from the PH.
Dave · April 3, 2021 at 4:31 pm
Hi Gray! At a glance your code looks good to me. I’d recommend giving it a try and seeing how it goes – you can always change it later.
The `setDpad` function does have a built-in SOCD cleaner (Up + Down = Up, Left + Right = Neutral) and you do not need to add one. If you would like to add your own or if you’d like different behavior, you can pass a fifth bool argument to the `setDpad` function to enable or disable the built-in cleaner. It is enabled by default.
The example is written so that the analog inputs are disabled if you don’t need them. It’s fine to remove them if they’re not needed but they shouldn’t get in the way.
I hope that helps. Best of luck with the project!
Dave · April 5, 2021 at 9:40 pm
Hi Dave, just wanted to ask if this works with an Xbox one s controller or even this one https://www.xbox.com/en-ca/accessories/controllers/xbox-wireless-controller#white
Dave · April 5, 2021 at 9:44 pm
Sorry Dave, I don’t understand your question.
Dave · April 6, 2021 at 8:08 am
Im asking if emulating the controller will work wirelessly through Bluetooth with the controllers shown above
Dave · April 6, 2021 at 4:23 pm
Dave I think you’re misunderstanding what this library does. It’s for having the Arduino act as a controller itself, not for interfacing with existing controllers.
Dave · April 6, 2021 at 4:25 pm
Oh, i misunderstood.
Jacob Briggs · April 12, 2021 at 11:06 pm
Hiya Dave
I am pulling the guts out of an older directinput wheel and replacing it with a leonardo and your library. Currently, I have the 3 potentiometers working fine when they are sitting on the bench and I can rotate the rotor fully, but when I put 2 of them back into their enclosure (the pedals, which I plan on mapping to the triggers) the range of movement is restricted to about a quarter of the rotation.
Would Range Rescaling help me here?
Jake
Dave · April 13, 2021 at 5:29 am
Hi Jake. Yes, the library’s built-in range rescaling would be able to fix that. Use the `setRange` function with the constrained min and max values.
Jacob Briggs · October 12, 2021 at 9:31 pm
Hiya Dave
I knows its eons later but I’m still working on this project. I am down to tidying up the enclosure and dialing in the values coming from the pots to emit trigger values. The triggers emit from 0-255 , and accordingly when I build my code against the debug version of the board, the output in the serial monitor is from 0-255. The values “setRange” expects to see though are not in the range 0 to 255 though are they?
How can I see the “raw” numbers on the debug console?
Jake
Jacob Briggs · October 12, 2021 at 9:33 pm
It just occurred to me I could assign the value read from the pic connected to my “trigger” to a joystick axis temporarily and note the min/max value from there….
Dave · October 13, 2021 at 1:17 am
Hello again Jake. If you want to see the values read from the pots there’s no reason to go through the library – you can use the Arduino’s serial interface to print those numbers directly.
Jacob Briggs · October 14, 2021 at 3:20 am
Oh yes of course haha. I did this last night, I think I am nearly done, only some cleanup of the physical enclosure to go and maybe adding a reset button.
Thanks for the library!
A-N-T-Z · April 14, 2021 at 1:02 am
i just did something similar, but kept the original’s functionality – i had an old logitech black momo forcefeedback wheel, i added 8 buttons to the hub’s original 6 for a total of 14. using a pro micro 3v3 and a mini usb shield, i intercept the momo’s usb output, and translate that using daves brilliant library to xbox and also read the extra buttons .. i added some latching relays so i can switch between momo and xbox functions .
Defiantz · April 15, 2021 at 9:54 am
Hello,
I’m using this tool with my Circuit Playground Express and I can’t seem to get it to work even though I think I’m following the instructions. I have the board set to XInput’s Circuit Playground board and am trying to use the blink example to test Whenever I try to run it, it goes through everything and says that the programmer is not responding. When I activate bootloader mode by pressing the reset button while “uploading” is at the bottom, it instantly ends the upload saying that the port doesn’t exist or my board is not connected.
Do you know what the problem could be?
Dave · April 15, 2021 at 10:01 am
The Circuit Playground Express is not a supported board. The “Express” uses a different MCU than the original Circuit Playground, which Adafruit now sells as “Circuit Playground Classic”.
Defiantz · April 15, 2021 at 10:21 am
Dang. Thanks for the response.
Maddox Swan · May 13, 2021 at 7:49 pm
I’ve been working on making my own controller using a teensy lc, but have had some issues. It show’s up as an Xbox 360 controller in my windows settings and even works in windows. It also works on steam after taking just a second to set it up in the controller settings. The one issue I am having is that it is working as a gamepad, and not specifically an Xbox 360 controller. This prevents me from playing games that require official controllers to prevent cheating. I’m wondering if you know what is causing this issue and how I might fix it.
Dave · May 13, 2021 at 8:47 pm
Hi Maddox. I’m not aware of any games that require an ‘official’ controller. Could you give me an example?
You cannot use this library to bypass anti-cheat that checks for genuine controllers. There is a way around that, but I didn’t build this library to help people cheat.
Maddox Swan · May 17, 2021 at 9:12 am
My fault, the reason why it wasn’t working was that not all games support the 360 controllers like you said, which I have a fix for. Now I’m just wondering how do you change the x and y-axis to work for joysticks instead of potentiometers? By default, it has the joysticks a little towards the bottom right and I can’t find the code I need to edit to fix this.
Dave · May 17, 2021 at 10:00 am
I’m not sure I follow. Most common joysticks use potentiometers under the hood, there is no functional difference in how you use the code.
If your joysticks “drift” towards the bottom right, it’s possible that you’re using voltage levels that are higher than the board’s logic level (e.g. 5V VCC on a 3.3V board). That would cause the voltage divider to return a higher than normal value when the joysticks are centered.
Maddox Swan · May 17, 2021 at 10:42 am
Oh, that did it, thanks! I don’t know why but the joystick says 5+ V on it, but when I used the 3.3v pin on my teensy it worked perfectly. I’m a little new to microcontrollers and haven’t used c to code really so I appreciate the help.
Dave · May 17, 2021 at 10:55 am
Yep that’ll do it. The Teensy is a 3.3V device, so putting 5V into the potentiometer will give you ~75% of the axis’ max when centered. See this issue on GitHub for a user with the same problem.
Quinn · May 19, 2021 at 4:50 pm
Hi Dave.
Your code works perfectly with the xbox 360 generic joysticks, however ive been trying to use the Xbox series elite 2 analog sticks and in testing it shows the analog not moving far enough, these are the type that work 100% – https://ibb.co/FXcNzpg .. Heres an example – https://ibb.co/fD0G6sf – this shows the Xbox elite series 2 analog stick. and this shows the xbox generic analog stick – https://ibb.co/BqgbMwv – as you can see your code works perfectly with the normal analog sticks but with these – https://www.ebay.co.uk/itm/293993537648?hash=item4473616070:g:IK8AAOSwGcBgHGwG – these are the series 2 analog sticks. i was trying around with different ADC max numbers which do change how much it registers,
I am reaching out to you just incase you had a solution to make these work flawlessly. Thanks for your help, please let me know if i can explain anything better. Quinn
Dave · May 19, 2021 at 5:08 pm
Hi Quinn. The code is hardware agnostic, which is to say that it will work with any hardware so long as you feed it the right data. If the joysticks you’re using do not have the output you’re expecting, you’ll have to do your own experimentation to find what values they output and adjust the range rescaling accordingly.
Quinn · May 19, 2021 at 5:21 pm
Hi dave thank you for responding so fast!,
Ive measure the resistance to the best of my ability on the new analog stick,
the X potentiometer (up and down) measures at 10.10 OHM (using OHM setting on Fluke Meter)
and the Y potentiometer (left and right) measures at 10.81 OHM .
im not too sure if youd be able to figure out what number it should be , or if you could tell me how to scale, ive tried these numbers in code and it works better then it did. but it wasnt perfect. Thanks
Dave · May 19, 2021 at 5:38 pm
Most potentiometers are used as voltage dividers, so the static resistance measurement is not significant. What matters is the change in ratio between the two pins and the resulting min/max voltages at the edges of the travel range.
But that’s all academic. The simplest solution is to use the microcontroller itself to check:
Move the joystick, see what comes up, and set the range rescaling to the min/max. You can print the values over USB serial (without the XInput board version, of course).
Quinn · May 19, 2021 at 5:49 pm
sorry i didnt press reply instead i added a new comment below
Quinn · May 19, 2021 at 5:46 pm
Hi,
im really sorry but youd need to explain it a little more in depth for me. im very new to this sort of thing,
ive changed usb type to serial , ive changed the analog read pin to my correct pin, ive put it under void loop.
what do i use so i can see waht comes up? when i try use the serial monitor it says no connection. so if you would be able to add a little more instruction i would really appreciate it, thank you again
Maddox Swan · May 26, 2021 at 6:06 pm
Just curious if anyone knows any good ways to wrap the xinput to get the controller to work in games that don’t support it. I’m just wondering if I need to find another library or if I can do this the lazy way. This library does work perfectly, but I’d like to make this work in other games.
Quinn · June 3, 2021 at 3:14 pm
Hi maddox, i have a solution but with this solution the game wont register the input as a controller but. There is a program called AntiMicro , you can program your joystick or controller buttons to a keyboard output, there are tons of tutorials on YouTube,
Pistol · August 13, 2021 at 10:46 am
Hi Dave, have you ever looked into getting this working with multiple device types? Just as you can have a Teensy present itself to the PC as Keyboard + Mouse + Joystick, it would be really great if we could use XInput the same way… I know some people have got it working, but it’s all a bit beyond me! This looks promising: https://github.com/joshtsen/ArduinoXInput_Teensy-w-OS-1.0-Descriptors
Alex · August 27, 2021 at 6:06 pm
Hi Dave,
Thank you for this incredible tutorial!
I’m really beginner with Arduino and I’m trying to figure out how to use an hall sensor instead of a potentiometer like in this exemple with a AS5600 sensor :
https://www.element14.com/community/community/project14/sensors/blog/2020/11/15/hall-sensor-as5600-for-game-wheel
Xinput library doesn’t seem to support I2C SCL SDA input.
Any hints on how to do this?
Thanks in advance!
Dave · August 27, 2021 at 8:35 pm
Hi Alex!
The library is input agnostic, which is another way of saying that it will work with whatever data you want to throw at it. Wherever an analog input is used, either the joystick axes or the triggers, you can directly replace the input value with the output from the hall effect sensor. Just be sure to match the input ranges to the data you expect (see the section on range rescaling).
Alex · August 30, 2021 at 4:12 pm
Thanks Dave for your reply!
It pretty much work now, but I have problem with the center value that stick to ‘0’ for some range. (see video)
https://youtu.be/zdBrbWHoEdQ
Any hints?
Here’s my code:
Dave · August 30, 2021 at 9:39 pm
The XInput library doesn’t do any sort of deadzone checks so my guess is that it’s an issue with the data from the encoder. I’d recommend trying without the XInput code – print the encoder position to serial and see if you have the same problem.
Alex · August 31, 2021 at 4:06 pm
It doesn’t have dead zone with the Arduino Joystick Library
https://youtu.be/v__icaBSLhA
Code:
Dave · August 31, 2021 at 6:27 pm
It still looks like it’s having issues to me. Slow down the video to 0.25x and look at around 5 seconds. You’re still turning the knob but the output is stuck at ~0.43 for another second before it jumps to -0.24.
As before I’d recommend leaving out the HID outputs and do more testing on the encoder itself. It looks as though it’s losing position.
Alex · September 1, 2021 at 1:32 pm
Hi Dave, I’ve try with serial output and the value is between 0-4095
When it pass 4095 it restart at 0.
Dave · September 1, 2021 at 1:41 pm
Alex: it’s not the range, it’s the consistency. If it’s pausing like that then the encoder must be losing position somehow.
As I’ve said this does not appear to be related to the XInput code in any way. I’d recommend seeking help elsewhere.
Alex · September 1, 2021 at 2:01 pm
Understand. Thanks for your help! I’ll come back when I resolve this.
Thanks again!
kyle · September 13, 2021 at 12:43 am
hi i have followed all instructions to get the board package and it wont come up in ide
any help would be tremendous
thanks kyle
Dave · September 13, 2021 at 2:41 am
Hi Kyle. Unfortunately there’s not much I can say in the way of help. If the boards aren’t showing up in the IDE then you must have missed a step in the instructions. My only advice would be to try again and take extra care to make sure you placed the files in the correct directory.
Marco Balletta · September 25, 2021 at 8:42 pm
Hi Dave, how are you?
Is it posaible to add L1 and R1 button in your code/library?
https://ibb.co/J5w7hs2
Thank you!
Dave · September 26, 2021 at 12:15 am
Hi Marco. The equivalent buttons on the Xbox controller are LB and RB (`BUTTON_LB` / `BUTTON_RB`).
Evan · November 7, 2021 at 12:56 pm
Hi Dave,
This library is awesome!
I’m currently working on something with it and I was wondering if you’d suggest adding a bit of debouncing to the buttons ?
Or does the library takes care of this in any way ?
Thank you very much !
Dave · November 7, 2021 at 2:03 pm
Hi Evan, that’s a great question. The library has no built-in debouncing whatsoever. This gives you direct control over the output values. If you are using physical buttons then I would absolutely recommend implementing some sort of debouncing.
Evan · November 8, 2021 at 8:21 pm
Thank you very much for the quick reply.
I only have one more question if you don’t mind.
I’m currently using an hall effect joystick (an apem hfx joystick) and I’m having strange results when using it compared to my xBox controller. The problem seems to be that even when the joystick is centered, the arduino keeps sending the centered position. (not sure if that makes any sense)
I saw in one of the examples that we should use a regular potentiometer joystick with this library.
Is there any way to desactivate the joystick in the code and re-activate it when I need it ? A function ? anything will help.
Thank you very much again,
Dave · November 8, 2021 at 9:11 pm
You’re probably seeing noise, which will cause the axes to wiggle a little bit when the joystick is untouched.
In most cases that’s a non-issue because games will have their own software deadzone around the joystick’s center point. If it’s causing trouble though you can implement your own deadzone on the microcontroller before you send the data to the XInput library. I made a small library with my own deadzone implementation in case it’s helpful.
Evan · November 9, 2021 at 2:32 pm
Thank you once more for answering my questions.
My issue was that when writing 1023/2 to send the center position, the arduino was sending a -33 value.
To get it working I simply mapped the value from 0, 1023 to -32768, 32767 and simply sent 0 when centering.
Probably something you could patch in the library if, or add to this tutorial 🙂 !
Once more, very nice and useful library.
Dave · November 12, 2021 at 8:17 pm
That’s a quirk of the remapping math, unfortunately. There’s no good way to implement that in the library without making assumptions about what the user is doing. If you need absolute 0 then it’s easy enough to do what you did and forego the automatic remapping and handle the centering yourself.
It’s worth pointing out that the axis not being exactly zero is usually a non issue. The real Xbox controllers themselves will rest the joysticks wherever the spring holds them, and it’s up to the driver / application to implement a deadzone if need-be.
Santiago · November 11, 2021 at 12:17 am
Tremendous work you’ve done here. I’ve been working on porting your library over to Teensy 4.1 Took me like 4 days to get it to show up to windows as an xbox controller and I hit a stumbling block where the device keeps reporting that it is stalling. Finally just ordered a Teensy 3.6 as I want to move on. Just curious if you had any experience with the teensy 4.1 or if you were sticking with the 3.6 or LC for now?
Dave · November 12, 2021 at 8:20 pm
Hello. I have never used a Teensy 4 board myself, and I don’t currently have any projects that require one. Adding support for the newer boards is on my radar but I have no plans for when that may happen.
Michael · January 24, 2022 at 5:03 pm
Dave,
I am not a coder. I barely have even a basic understanding and your tutorial was great. I got my Arduino Leonardo all set up and tested the X-input libraries and all is working great
But I can’t wrap my head around how to write the code I need
I am making a pinball table and need a XBOX controller emulator that uses LB and RB ( no need for analog triggers )
A right analog stick
A left analog stick
The 4-way D-pad
The four face buttons A B X Y
I tried for a few hours to modify your code here on the tutorial but I am obviously missing something important because nothing I cobble together will verify, and because I don’t understand coding I can’t make sense of the error messages
Is there anywhere I can find pre-written code that has all the standard controller functions already set up and ready to use?
I have searched the internet but for the life of me can not find any pre-written examples of the code needed to make an arduino leonardo work just like a normal Xbox controller with all the standard controls enabled
I really appreciate any help you can give me on where to look to find what I need to get my controller up and running, and absolutely appreciate your time taken reading this.
Thanks !
Dave · January 24, 2022 at 10:21 pm
Hi Michael!
I’m sorry to say it but the library is not a turn-key solution, it’s aimed at developers that want to use XInput outputs for their programs. If you don’t know how to program then this library may not be what you need. You may be better served by modifying an existing Xbox controller or using an off the shelf encoder board.
Gray · January 24, 2022 at 11:18 pm
Hi Michael! I have been helped by Dave in the past, I used his library to make this code for a custom xbox controller (a fight stick) on arduino leonardo. I think you can also use this to make your controller, IF you can at least read and make sense of the button pinout. the code is sufficiently commented so I think it will be easy for you. You can contact me @ gray_balanag@yahoo.com so I can email you the sketch file on arduino.
Jason · January 31, 2022 at 3:05 pm
Been working alongside your already posted projects and tutorials. I’ve currently mastered the thumbstick and even implemented the Y-axis into your Rocket League code so that I might have 2-axis control for FPS games.
I’ve run into a problem. The push pin buttons don’t seem to respond at all on the GamePad tester that you linked above. I’ve tried several buttons to make sure none of them are faulty. I have one of the button pins grounded and the other button pin set to Digital Pin 2 however I do not get a response while the thumbstick is working perfectly.
Have you run into this problem yourself? Do you know of any solutions?
Dave · January 31, 2022 at 3:57 pm
Hi Jason. Are you using the Rocket League code from the tutorial? I haven’t run into that issue myself.
The first thing I’d check is if you have the `INPUT_PULLUP` pin mode set in the `setup()` function. In the past I’ve also seen a few people perform a `digitalRead()` from the pin and set a variable but forget to set the output using the `setButton` function.
If you’re using typical breadboard tactile switches try connecting diagonally from corner to corner instead of straight across. Depending on how their rotated, two contacts are internally connected and two contacts are switched. If you connect corner to corner you’ll make a switched connection no matter the orientation.
Lastly, try testing without the “with XInput” version of the board so you get the debug output over serial. That will also out the XInput core / library as a factor.
Good luck!
Jason · February 16, 2022 at 3:29 pm
Sorry I haven’t gotten back to you Dave. Here’s an update.
I’ve currently fixed my previous problem that I commented on. I’ve got the Left Thumb-stick and ABXY buttons coded and working. I’ve managed to get inputs working on Fallout: New Vegas and Trackmania Nations Forever.
My next big problem is getting the Right Thumb-stick working. My overall goal is to make my controller playable with only one hand. To accomplish this, I’m going to use an MPU-6050 gyroscope/accelerometer to act as the Right Thumb-stick. An example of using the MPU-6050 for aiming on a controller can found be at the link below:
https://www.youtube.com/watch?v=k0mU0DkX9Pc
I am trying to replicate the video’s idea of “aiming” in game with the MPU-6050. Do you know how I would be able to get the XInput library and MPU-6050 to work properly together, as in get the MPU-6050 to be recognized as a thumb-stick? I just got the sensors in the mail today, so I haven’t broken much ground.
Any help is greatly appreciated. Thanks
Dave · February 16, 2022 at 8:07 pm
Hi again Jason. You’re in luck – I wrote the aiming code that is used in that video (see @1:46). Check out the documentation for that project (McCree Hammershot) which goes into detail on how it works.
Daniel Ceneski · March 27, 2022 at 4:11 pm
Hello!
This is really helpful!
I was just wondering if you could help me out with some tips and tricks for coding the entire Xbox 360 controller with 2 joysticks. I am a complete newbie and really don’t know what I am doing.
I there a way to learn this stuff? Other then experimenting without knowing what I am doing xD
Have a nice one!
Dave · March 30, 2022 at 8:59 am
Hi Daniel. This tutorial should cover the basics of what you need.
For more detailed information, look up some Arduino or C++ tutorials, and some tutorials about electronic circuits and microcontrollers.
Tom · April 19, 2022 at 11:07 pm
Would you be able to add the guide button (xbox center button) to your github master file?
Dave · April 19, 2022 at 11:15 pm
Hi Tom. I’m not sure what you mean. The library on GitHub does support the guide button.
Porridge2215 · April 28, 2022 at 4:35 pm
Great article, Ordered a Leonardo to play with.
My two worrys are
1. how easy is it to reset, as you say you overwrite some core files and that’s a little scary!
2. I intend to to connect this to the PC to program some basic operations eg joystick 90 degrees, forward for 2.5 seconds, joystick 30 degrees , walk forward 1 second, button a click, lb hold, etc.
I know that I have to get the timings exactly right fit those commands.
But I assume I have to UNPLUG it from the PC then PLUG it into to the Xbox series x and hit the go/run/execute button. I cannot see in the article how to connect what, as you know I don’t have the card, and never programmed that before.
But how do I execute the code, when I am disconnected from the pc? Or…
Can I program on the pc at the SAME TIME as it is churning out the xinput commands out of the usb that is connected to the Xbox series X?
Would love you to clear this up for me, obviously there will be a lot of iterations before I have an exact set of instructions to get a character to a certain place.
How would you approach this please?
3. Oh, while I’m here I may add well ask hany way to record inputs from a controller to get buttons and timings etc?
Many thanks
Dave · April 29, 2022 at 3:47 am
This does not work with the Xbox Series X.
Porridge2215 · May 1, 2022 at 12:17 pm
Apologies, should have said Xbox streaming app on pc… is reset simply the red button on the board? And can I program it, and run it BOTH from the same usb cable, or do you have to do something in between.
Hoping the streaming app sees the controller ok
Dave · May 1, 2022 at 12:54 pm
You can program and run the board from the same USB cable, but not at the same time. The program on the board is executed independently from the PC and the board needs to be restarted and flashed to change it. If you want to send commands to the board on the fly, you will need a second development board on a second USB port communicating with the first using some sort of bus (UART, I2C, SPI, etc.).
For what it’s worth, if you’re trying to record and play back inputs on the same computer this is probably not the way to go. You would be better served by using some controller emulation software on the PC.
Paulo R. Bertholdi · May 13, 2022 at 1:55 pm
Hi Dave. I’m Brazilian, but not the same person as the previous post. Great job. I had good experiences with your works. I made modifications to get better rumble signals. I plan to use it in the chair with the P3D v4.5 flight simulator. But even through the “callback” and separating rumble-right/left, I had only signs of retraction and gear touching the runway. No sign roll across the runway (which is very important for my chair vibration project).
I appreciate the help if it’s within your reach.
Dave · May 14, 2022 at 11:33 pm
Hi Paulo. The controller’s rumble is entirely dependent on what it receives from the game, so if there’s no data received there’s not much you can do. You can always sniff the USB packets using Wireshark or a logic analyzer if you think there’s packets that aren’t being caught by the library. Let me know if you find a discrepancy.
Paulo R. Bertholdi · May 31, 2022 at 9:33 am
Hi Dave. I appreciate your feedback.
As I had already said, my proposal is to obtain vibration for a chair.
I refined the programming with Pin_PWM outputs, 2 separate channels rumble_left and rumble_right 8bits-256. They worked in Microsoft Flight Simulator (MSFS-2020), at least gears-ground effects, track scrolling and gear retraction (that was my interest). The problem occurs when I press any device, click on keyboard or mouse or other controller. The vibration effect stops. It only comes back if I press any button or joy on the arduino. As if he lost focus. Thanks
Dave · May 31, 2022 at 9:52 am
Hi Paulo. That’s likely intended behavior. The vibration is meant for a controller, if you’re using a different input device then it’s reasonable that the game turns off the vibration on the controller you’re not using. There is nothing that can be done on the controller side, you would have to take up the issue with the developers of the game.
Jannis · August 19, 2022 at 7:12 am
Hey Dave!
I am happy with your work! I plan to jump into this project. An important question: Only Xbox controller functions work as:
10 + 1 Digital Buttons
2 Analog Joysticks (16 bit)
2 Analog Triggers (8 bits)
1 Four-Way Directional Pad (D-Pad)
or can I add some keyboard functions as well?
I appreciate the help! Thanks! 🙂
Dave · August 19, 2022 at 7:31 am
Hi Jannis. Only Xbox functions work. If you need keyboard functionality in the same device you will have to add a second microcontroller and a USB hub. You could alternately use the class-compliant gamepad implementation with something like the “Joystick” library, which is compatible with keyboard output, but then you will need software like x360ce to use the controller with modern games.
Jared · September 21, 2022 at 3:04 pm
Thanks for putting this together Dave! I’ve got the library working on a TeensyLC and should eventually incorporate it into a portable RetroPie build.
A-N-T-Z · March 20, 2023 at 2:03 am
3 of my projects using Dave’s brilliant software, arduino code is included
https://www.youtube.com/watch?v=u9Xae6atRJo
build a DirectInput-Joystick to Xbox360-controller hardware-adapter, GTA DInput to XInput, no x360ce
https://www.youtube.com/watch?v=R41vlkI0p4Y
add XInput to Logitech MOMO FF DInput wheel, GTA, DirectInput, Arduino USB Host Shield, no x360ce
https://www.youtube.com/watch?v=5XD2XMuHfLs
ake an xbox360 controller with a psMove wheel, a headtracker, 2x Arduinos, and 2x USB Host Shields
Dave · March 20, 2023 at 4:38 pm
Nice projects!
Tim · April 27, 2023 at 6:32 pm
Hey, thank you for this awesome how to & the code,
I’ve managed to get the code to work for the most part of what I need,
My only issue is that I need the rumble feature to output to pin A2 on the my Leonardo from low to high, instead of using a motor I need it to fire an Arduino relay (5v).
I have attempted to get the rumble code to work with the built-in led but it’s not doing anything so I’m not to sure if it’s a communication issue? I have tested the pin being written high and low in my code and it has switched pinmodes appropriately on upload but won’t receive /output the data.
Please let me know if you can help!
Many thanks,
Tim
Dave · April 27, 2023 at 9:53 pm
Hi Tim. Try setting a flag whenever rumble data is received and use that to drive the output for a given period of time. Some applications “pulse” the rumble motors and the duration can be too short to see reliably. If you’re not getting any rumble data at all I’d recommend testing with a real controller to verify the application is sending the rumble data when you expect it.
Tim · May 1, 2023 at 2:43 pm
thanks your your response, I’m still quite new to coding so I don’t know how to setup flags at the moment but I’ll loo into it.
When I plug in the Leonardo, it shows in my joystick setup that its an Arduino Leonardo Controller and gives me a test option but it doesn’t show vibration anywhere, do I need to install a specific driver for vibration to be recognized?
Dave · May 9, 2023 at 9:15 pm
On Windows you don’t need a special driver, but the `joy.cpl` panel doesn’t use the XInput driver. For vibration you need to test in a third party program that supports the XInput interface.
Geoff · December 20, 2023 at 9:34 pm
Thanks for this tutorial. I’m able to use the USB gamepad on my Xbox through a third party app. I’m wondering if you would know how to tweak the code to emulate a HOTAS throttle/joystick setup like the Thrustmaster that works with Xbox.
Dave · December 20, 2023 at 9:39 pm
Glad that it worked for you! The library emulates an Xbox 360 controller. If you want to design a controller that physically works in a different way but has the same output data as the Xbox 360 controller, no changes are necessary to the code. If you want to design a controller that has different output data, I’d recommend looking into libraries that implement the USB HID standard.
Leo · January 17, 2024 at 12:32 pm
Hi Dave!
1st A big thank you for your work!
I would like to inquire about uploading the sketch.
I would like to avoid having to manually reset the board, but according to the guide, this is only possible with Teensy boards or a dedicated programmer. Is the dedicated programmer hardware-only, or is it possible to achieve it through software as well? If yes, how? It would be a great help if you could respond.
Thank you very much!
Dave · January 17, 2024 at 7:41 pm
The dedicated programmer is a hardware device that attaches to the programming header on the board.
It is possible but not easy to have the auto-reset work in software. You would need to write a program that sends an arbitrary ‘reset’ signal to the controller, rewrite the core files to pick up on that signal, and then modify the Arduino IDE integration to use your program during the upload process. You would also need to make the same modifications to the vanilla IDE files if you want to remove the XInput firmware with a software reset.
charlie · March 24, 2024 at 10:37 am
Just a big Thanks. Got my 90’s 35mhz fm Sanwa Transmitter controlling a drone in FPV.Skydive. Mine was a really odd use case, mainly determined by what I had to hand. You made it possible, Thanks again.
Derek · May 6, 2024 at 4:45 pm
The typical SparkFun Pro Micro, has a Processor selection in the Tools menu to select between the 3.3V and 5V versions, but that option doesn’t exist with your version of the libraries. With the 5V processor, the board shows up as an unknown device so I’m guessing this might be the issue? Thanks!
Dave · May 7, 2024 at 12:45 am
Hi Derek. Are you confusing the Micro and the Pro Micro? The Micro is an official Arduino board and is included in the AVR package. The Pro Micro is a SparkFun board, and requires the SparkFun boards package to get the 5V/3.3V option.
Derek · May 7, 2024 at 7:36 am
Not sure what happened, but I removed the AVR and Sparkfun packages and installed them again and I got the processor option as expected and it worked this time! Sorry about that! Thanks for your work putting this together!
Sebastien · August 26, 2024 at 11:03 am
Hello everyone ! Does someone know if the library handles the controller battery reading ? I can’t find anything in the documentation…
The code works as expected but I would like the micro controller to send the battery level, just like an xbox gamepad
Dave · August 26, 2024 at 1:33 pm
The library emulates a wired Xbox 360 controller, which does not have a battery or a battery level.
Sebastien · August 26, 2024 at 1:36 pm
Damn… I thought it did
Thank you for your quick answer