Create a Joystick Using the Arduino Joystick Library 2.0

21,151

134

17

Published

Introduction: Create a Joystick Using the Arduino Joystick Library 2.0

Since I released the original Arduino Joystick Library (see https://www.instructables.com/id/Arduino-LeonardoMicro-as-Game-ControllerJoystick/ for more details) I have received numerous requests for enhancements. Most of these requests fall into the following two categories:

  • Increase the precision of the axes.
  • Make a version with only a specified set of features.

To accommodate these requests (and a few others) I have release Version 2.0 of the Arduino Joystick Library.

Step 1: Arduino Joystick Library 2.0

Out of the box the Arduino Leonardo and the Arduino Micro appear to the host computer as a generic keyboard and mouse. This article discusses how the Arduino Leonardo and the Arduino Micro can also appear as one or more generic Game Controllers or Joysticks. The Arduino Joystick Library Version 2.0 can be used with Arduino IDE 1.6.6 (or above) to add one or more joysticks (or gamepads) to the list of HID devices an Arduino Leonardo or Arduino Micro (or any Arduino clone that is based on the ATmega32u4) can support. This will not work with Arduino IDE 1.6.5 (or below) or with non-32u4 based Arduino devices (e.g. Arduino UNO, Arduino MEGA, etc.).

Step 2: Features

The joystick or gamepad can have the following features:

  • Buttons (default: 32)
  • Up to 2 Hat Switches
  • X, Y, and/or Z Axis (up to 16-bit precision)
  • X, Y, and/or Z Axis Rotation (up to 16-bit precision)
  • Rudder (up to 16-bit precision)
  • Throttle (up to 16-bit precision)
  • Accelerator (up to 16-bit precision)
  • Brake (up to 16-bit precision)
  • Steering (up to 16-bit precision)

These features are configured using the Joystick_ class’s constructor.

Step 3: Installation

The latest build of Version 2.0 of the Arduino Joystick Library can be downloaded from the following GitHub repository:

https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-2.0

The library can also be downloaded directly using the following: https://github.com/MHeironimus/ArduinoJoystickLibrary/archive/version-2.0.zip

Copy the Joystick folder to the Arduino Libraries folder (typically located at %userprofile%\Documents\Arduino\libraries on Microsoft Windows machines). On Microsoft Windows machines this can be done by executing deploy.bat. The library should now appear in the Arduino IDE list of libraries.

Step 4: Included Examples

The example Arduino sketch files listed below are included in this library. These will appear in the Arduino Example menu when the Arduino Joystick Library is installed.

JoystickTest – Simple test of the Joystick library. It exercises many of the Joystick library’s functions when pin A0 is grounded.

MultipleJoystickTest - Creates 4 Joysticks using the library and exercises the first 16 buttons, the X axis, and the Y axis of each joystick when pin A0 is grounded.

JoystickButton - Creates a Joystick and maps pin 9 to button 0 of the joystick, pin 10 to button 1, pin 11 to button 2, and pin 12 to button 3.

JoystickKeyboard - Creates a Joystick and a Keyboard. Maps pin 9 to Joystick Button 0, pin 10 to Joystick Button 1, pin 11 to Keyboard key 1, and pin 12 to Keyboard key 2.

GamepadExample - Creates a simple Gamepad with an Up, Down, Left, Right, and Fire button.

DrivingControllerTest - Creates a Driving Controller and tests 4 buttons, the Steering, Brake, and Accelerator when pin A0 is grounded.

FlightControllerTest - Creates a Flight Controller and tests 32 buttons, the X and Y axis, the Throttle, and the Rudder when pin A0 is grounded.

HatSwitchTest - Creates a joystick with two hat switches. Grounding pins 4 - 11 cause the hat switches to change position.

Step 5: Running the JoystickTest Example

The JoystickTest example sketch is included with the library. I recommend using this example to verify everything is working properly before beginning to write your own sketch files. Load, compile, and upload this example sketch file to an Arduino Leonardo or Micro using the Arduino IDE (version 1.6.6 or above).

Once you have uploaded the JoystickTest sketch file to the Arduino Leonardo or Micro, perform the following steps to verify everything is working properly. Note: the following steps are for Windows 10. If you have a different version of Windows or a different operating system, these steps may differ.

Open the “Devices and Printers” window. This can be done by clicking the Start menu or pressing the Windows Key and typing “Devices and Printers”.

Step 6: Arduino Settings Menu

The Arduino Leonardo or Arduino Micro should appear in the list of devices.

Right mouse click on the Arduino Leonardo or Arduino Micro
to display the settings menu.

Select “Game controller settings” to get to the “Game
Controllers” dialog.

Step 7: Select the Arduino

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

Step 8: Testing the Arduino Joystick

While this dialog has focus, ground pin A0 on the Arduino to activate the test script.

The test script will test the game controller functionality in the following order:

  • 32 buttons
  • throttle and rudder
  • X and Y Axis
  • Z Axis
  • 2 Hat Switches
  • X, Y, and Z Axis Rotation

Step 9: Simple Gamepad Example - Hardware

Once the Arduino Leonardo or Micro has been tested using the JoystickTest example, I suggest making a simple gamepad controller. You will need five buttons to build this simple example. Each button will correspond to one of the following joystick functions: up, down, left, right, and fire.

Connect one end of each button to the ground pin of the Arduino. Connect the other end of each button as indicated below:

  • Up Button => Pin 2
  • Right Button => Pin 3
  • Down Button => Pin 4
  • Left Button => Pin 5
  • Fire Button => Pin 6

Step 10: Simple Gamepad Example - Sketch File

Upload the GamepadExample example sketch file to the Arduino Leonardo or Micro. This example is included with the Arduino Joystick Library.

Step 11: Simple Gamepad Example - Testing

Open the game controller properties or use the joystick testing application of your choice to test the behavior of your gamepad.

Step 12: For More Information

More information about the Arduino Joystick Library Version 2.0, including the complete API documentation, can be found at https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-2.0.

Share

    Recommendations

    • Make it Move Contest

      Make it Move Contest
    • Planter Challenge

      Planter Challenge
    • Woodworking Contest

      Woodworking Contest
    user

    We have a be nice policy.
    Please be positive and constructive.

    Tips

    2 Questions

    Hello, I was wondering could I run this emulator and the keyboard emulator at the same time on the same Arduino?
    All I need is a two axis(x,y) joystick, I’m still new to Arduino so this is a lot to take in. Not sure how to set this up, any chance that there’s a video explaining how to use the code?

    Hi Matthew,

    after placing the joystick folder in my libraries i open the JoystickTest file in my IDE, however when I tried to compile the sketch, I was met with a error and I can't figure out why it's happening. This is what the console is giving me:

    readlink C:\Users\dylan\OneDrive\Documents\ArduinoData\packages: The system cannot find the file specified.

    Error compiling for board Arduino Leonardo.

    any help would be much appreciated! thanks!

    Dylan

    I tried installing everything but I'm ending up with the same issues when I try to verify the sketch. :/

    readlink C:\Users\dylan\OneDrive\Documents\Arduino\libraries\Joystick\examples\JoystickKeyboard\JoystickKeyboard.ino: The system cannot find the file specified.

    Error compiling for board Arduino Leonardo.

    1 more answer

    0

    I have never encountered that error before. Are you able to open and compile any of the examples via the following menu option: File -> Examples -> Joystick -> JoystickTest (or any of the others)?

    17 Comments

    Matthew,

    I have things mostly working. I have 8 analog channels, but channel 5, in particular seems to have a "range" issue. That is, sometimes my device sees the controller output as 0 to 100 (on a scale of 0 to 100), sometimes it reads it as 50 to 80. The results aren't consistent. Is there something wrong with my setup? Could channel (or any others) be mis-configured?

    My code is below.

    #include <Joystick.h>

    Joystick_ Joystick;

    int8_t joystickType = 0x08;


    float Multiplier = 1.2;

    int Offset = 0;

    float Multiplier2 = .9;

    int Offset2 = -300;



    bool includeXAxis = true;

    bool includeYAxis = true;

    bool includeZAxis = true;

    bool includeRxAxis = true;

    bool includeRyAxis = true;

    bool includeRzAxis = true;

    bool includeThrottle = true; //not really throttle
    bool includeRudder = true; // not really rudder


    const int Analog1 = 0;

    const int Analog2 = 1;

    const int Analog3 = 2;

    const int Analog4 = 3;

    const int Analog5 = 4;

    const int Analog6 = 5;

    const int Analog7 = 6;

    const int Analog8 = 7;



    int XValue = 0;

    int YValue = 0;

    int ZValue = 0;

    int RxValue = 0;

    int RyValue = 0;

    int RzValue = 0;

    int SxValue = 0;

    int SyValue = 0;



    void setup() {

    Joystick.begin();

    delay(1000);

    }

    void loop() {



    XValue = (analogRead(Analog1));

    YValue = (analogRead(Analog2));

    ZValue = (analogRead(Analog3));

    RxValue = (analogRead(Analog4));

    RyValue = (analogRead(Analog5));

    RzValue = (analogRead(Analog6));

    SxValue= (analogRead(Analog7));

    SyValue = (analogRead(Analog8));


    XValue = (XValue * Multiplier2) + Offset2;

    YValue = (YValue * Multiplier2) + Offset2;

    ZValue = (ZValue * Multiplier2) + Offset2;

    RxValue = (RyValue * Multiplier2) + Offset2;

    RyValue = (RyValue * Multiplier2) + Offset2;
    RzValue = (RzValue * Multiplier) + Offset;

    SxValue = (SxValue * Multiplier2) + Offset2;

    SyValue = (SyValue * Multiplier2) + Offset2;

    Joystick.setXAxis(XValue); //YAW

    Joystick.setYAxis(YValue); // Throttle

    Joystick.setZAxis(ZValue); //PITCH

    Joystick.setRxAxis(RxValue); // Roll

    Joystick.setRyAxis(RyValue);// Chan 6

    Joystick.setRzAxis(RzValue);// Chan 5

    Joystick.setThrottle(SxValue);// Slider 1- not really throttle

    Joystick.setRudder(SyValue);//Slider 2 - not really rudder
    }

    Please note that the Joysticks are not being read by Windows. They are instead being read by a program running on a PC called "Mission Planner", which lets me re-map the channels to various functions.

    A picture of the "work in progress is attached.

    IMG_20171112_155030.jpg
    2 replies

    I am not sure.

    It does appear you are calculating the value of "channel 5" differently from the other channels: RzValue = (RzValue * Multiplier) + Offset;
    vs.
    RxValue = (RyValue * Multiplier2) + Offset2;

    I haven't messed with this for awhile. I gave up and moved on to other things. But I'll get back to it.

    Channel 5 has different values because the program on the "other end" isn't consistently reading that channel properly. I tried to change the values in order to make it work. Sometimes, I get a huge offset. For example, if you assume the normal joystick output is 0 to 100, my computer interprets it as 50 to 80 when I move the stick side to side, so I have to add huge offsets and change the scale factors to make it work. But that doesn't always work either - possibly because of variable overflows. It is as if the library expects channel 5 to be digital and trying to make it analog messes it up.

    It could be that the program I'm running on my computer (Mission Planner) is handling the input improperly.

    I made a steering wheel based on this library and a arduino leonardo it works but there is a about 100ms delay from a axis turn and the response on the computer (the buttons are with an apparently satisfactory delay) and there's also an annoying fluctuation on the axis(my best guess is that the arduino is to slow to process all the inputs) i would be grateful for a solution or workaround.

    here's my code:

    #include <Joystick.h>
    Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
    8, 0, // Button Count, Hat Switch Count
    false, false, false, // X , Y, Z Axis
    false, true, false, // Rx, Ry, Rz Axis
    false, false, // rudder , throttle
    true, true, true); // accelerator, brake, steering

    void setup() {
    Joystick.begin();
    Joystick.setSteeringRange(0,1023); //steering
    Joystick.setBrakeRange(110,180); //brakes
    Joystick.setRyAxisRange(25,118); //clutch
    Joystick.setAcceleratorRange(943,1023); //throttle
    pinMode(A0, INPUT_PULLUP);
    pinMode(A1, INPUT_PULLUP);
    pinMode(A2, INPUT_PULLUP);
    pinMode(A3, INPUT_PULLUP);
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
    pinMode(4, INPUT_PULLUP);
    pinMode(5, INPUT_PULLUP);
    pinMode(6, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    pinMode(8, INPUT_PULLUP);
    pinMode(9, INPUT_PULLUP);
    digitalWrite(2,HIGH);
    digitalWrite(3,HIGH);
    digitalWrite(4,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,HIGH);
    digitalWrite(7,HIGH);
    digitalWrite(8,HIGH);
    digitalWrite(9,HIGH);
    }



    void loop() {
    bool gear0 = digitalRead(2),gear1 = digitalRead(3),gear2 = digitalRead(4),
    gear3 = digitalRead(5),gear4 = digitalRead(6),gear5 = digitalRead(7),
    gear6 = digitalRead(8),gear7 = digitalRead(9);
    Joystick.setSteering(analogRead(A0)); //steering
    Joystick.setAccelerator(analogRead(A1)); //throttle
    Joystick.setBrake(analogRead(A2)); //brakes
    Joystick.setRyAxis(analogRead(A3)); //clutch
    Joystick.setButton(0,!gear0); //gear 1
    Joystick.setButton(1,!gear1); //gear 2
    Joystick.setButton(2,!gear2); //gear 3
    Joystick.setButton(3,!gear3); //gear 4
    Joystick.setButton(4,!gear4); //gear 5
    Joystick.setButton(5,!gear5); //gear 6
    Joystick.setButton(6,!gear6); //gear 7
    Joystick.setButton(7,!gear7); //reverse


    }

    2 replies

    Do you have any sort of delay in your loop function? With out a delay, you will send too much data over USB. I have found that putting a delay(50) in your loop function works well.

    sorry for the duplicated comment I wrote the second one due to not seeing the first and I wrongly concluded it wasn't sent to the server

    i used this code to make a steering wheel (its in pieces for repair so i can't show the problem),but i was having some very annoying issues with delay(i didn't measured but it was probably higher than 100ms(<10ms ideal delay) and fluctuations on the axis here's my code:

    #include <Joystick.h>
    Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
    8, 0, // Button Count, Hat Switch Count
    false, false, false, // X , Y, Z Axis
    false, true, false, // Rx, Ry, Rz Axis
    false, false, // rudder , throttle
    true, true, true); // accelerator, brake, steering

    void setup() {
    Joystick.begin();
    Joystick.setSteeringRange(0,1023); //steering
    Joystick.setBrakeRange(110,180); //brakes
    Joystick.setRyAxisRange(25,118); //cluth
    Joystick.setAcceleratorRange(943,1023); //throttle
    pinMode(A0, INPUT_PULLUP);
    pinMode(A1, INPUT_PULLUP);
    pinMode(A2, INPUT_PULLUP);
    pinMode(A3, INPUT_PULLUP);
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
    pinMode(4, INPUT_PULLUP);
    pinMode(5, INPUT_PULLUP);
    pinMode(6, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    pinMode(8, INPUT_PULLUP);
    pinMode(9, INPUT_PULLUP);
    digitalWrite(2,HIGH);
    digitalWrite(3,HIGH);
    digitalWrite(4,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,HIGH);
    digitalWrite(7,HIGH);
    digitalWrite(8,HIGH);
    digitalWrite(9,HIGH);
    }

    void loop() {
    bool gear0 = digitalRead(2),gear1 = digitalRead(3),gear2 = digitalRead(4),
    gear3 = digitalRead(5),gear4 = digitalRead(6),gear5 = digitalRead(7),
    gear6 = digitalRead(8),gear7 = digitalRead(9);
    Joystick.setSteering(analogRead(A0)); //steering
    Joystick.setAccelerator(analogRead(A1)); //throttle
    Joystick.setBrake(analogRead(A2)); //brakes
    Joystick.setRyAxis(analogRead(A3)); //cluth
    Joystick.setButton(0,!gear0); //gear 1
    Joystick.setButton(1,!gear1); //gear 2
    Joystick.setButton(2,!gear2); //gear 3
    Joystick.setButton(3,!gear3); //gear 4
    Joystick.setButton(4,!gear4); //gear 5
    Joystick.setButton(5,!gear5); //gear 6
    Joystick.setButton(6,!gear6); //gear 7
    Joystick.setButton(7,!gear7); //reverse
    }

    i would be grateful if you can find the problem in it, and by the way the delay in the buttons is smaller than in the axis.

    Hi Matthew,

    nice tutorial.

    is there a way to use analogue sticks/rockers using the same library or same arduino???

    4 replies

    No, that code appears to map the joystick buttons to keyboard key presses. This library makes the Leonardo appear like a joystick to the host computer.

    If the flight simulator can work with a USB joystick, it should be able to work with this.

    Wow, thanks for sharing your library... I'll test it on my Leonardo...

    Good working!