Friday, November 25, 2016

Arduino Joystick Library - Version 2.0

Introduction

Since I released the original Arduino Joystick Library (see http://mheironimus.blogspot.com/2015/11/arduino-joystick-library.html or http://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.

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.).

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.

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 URL:
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, only, this can be done by executing deploy.bat. The library should now appear in the Arduino IDE list of libraries.

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.

Example Description
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.

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”.

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.



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.



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

Simple Gamepad Example


Once the Arduino Leonardo or Micro has been tested using the JoystickTest example, I suggest making a simple gamepad controller. This controller will have five buttons: up, down, left, right, and fire.

Connecting the Buttons


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

Arduino Pin Description
2
Up
3
Right
4
Down
5
Left
6
Fire

Sketch File


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


Test


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



Joystick Library API


The complete documentation for the Arduino Joystick Library can be found at https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-2.0.



95 comments:

masawaan said...

you have good site how to do it

32 buttons
throttle and rudder
X and Y Axis
Z Axis
2 Hat Switches
X, Y, and Z Axis Rotation
BUT how i add arduino micro trimm wheel too rudder and pitch ?
i no need all button but need all micro analog input use to my game controller.
add example tutorial how made , X,Y,trottle,propell,mix,rudder,2x trimm wheel,1x hat switch,and all other potentiometers/slider what want add too.
buttons i not need, i no understand how i add all analog input can use to game controller. micro have 12 analog.but if 8-9 input can then i can made my cessna simulator cocpit ready. send help to me mail, please.

Unknown said...

how Can i use 8axis ?
i can use only 7axis now, just like this.
https://3.bp.blogspot.com/-OvR4Bjnt9WY/WDiqBoSzz1I/AAAAAAAABsQ/SHZiHbWQnewi0o2H6BZsOA8DRLpVhc63wCLcB/s320/Arduino%2BJoystick%2BProperties.png


Matthew Heironimus said...

@Ken Bou - The Windows Game Controller Test dialog only shows 7 axis, but there can be more than that (for games and applications that support it). You will need to use a third-party joystick test application to see over 7 axis. One I have used in the past can be found at http://www.planetpointy.co.uk/joystick-test-application/.

Matthew Heironimus said...

@Matti Virta

Here is a simple sketch file that reads an analog input from a potentiometor that is wired to pin A0:

#include <DynamicHID.h>
#include <Joystick.h>

/*
  AnalogReadSerial
  Reads an analog input on pin 0, prints the result to the serial monitor.
  Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

  This example code is in the public domain.
*/

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 4, 0,
  false, false, false, false, false, false,
  false, false, false, false, true);

// the setup routine runs once when you press reset:
void setup() {
  
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }

  Joystick.setSteeringRange(0, 800);
  Joystick.begin();

  // Init Pins
  pinMode(A0, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);

  Joystick.setSteering(sensorValue);
  
  // print out the value you read:
  Serial.println(sensorValue);
  delay(200);        // delay in between reads for stability
}

Not sure if that will help you or not, but it shows how to read a value from A0 and send it to the Joystick library.

masawaan said...

thanks, what mean all many false,false,true, were mean this do ?
i must test you code how work after i can orden new micro, old has bro0ken now i try burn mmjoy hex file and now all micro no working and not found any port. and software

Matthew Heironimus said...

@Matti Virta - The mean of the Constructor arguments is documented at https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-2.0#joystick_

Unknown said...


Good morning
it is possible to have a code example on how to operate the analog sticks?
Thanks in advance

Unknown said...

Hey. J have this code
------------------------------------------------------------------------------------------
//#include DynamicHID.h
#include Joystick.h

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 4, 0,
false, false, false, false, false, false,
false, false, false, true, true);

// the setup routine runs once when you press reset:
void setup() {

// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}

Joystick.setBrakeRange(0, 1023);
Joystick.begin();

// Init Pins
pinMode(A0, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {

// read the input on analog pin 0:
int sensorValue = analogRead(A0);
Joystick.setBrake(sensorValue);

// print out the value you read:
Serial.println(sensorValue);
//delay(200); // delay in between reads for stability
}
----------------------------------------------------------------------------------------
DynamicHID.h - what for is this ?
I use Brake analog and in serial monitor is working fine, i got range 0-1023. But in joystick properties in windows i get only value min and max, no range. Any ideas why??

Unknown said...

Matt, sorry to comment on an older post, but I've been at this a few days and am stuck. My first problem was I was using version 1 of your sketch, but that's fixed now. :)

Pretty much what I want to do is disable all the axis and hat so I can have 20 buttons. I can petty much do that, except whenever I press any button the "16" button presses and remains pressed. Also, the X, Y and Throttle move from 100% to 0 and the x/y axis moves back to 0 from center. I can turn all these off in joystick.h as you described with the true/false statements, only I still have the button 16 problem. It looks like my buttons are showing up as 1-15 and then 19-20.

I don't recall having this issue in version 1 but, I couldn't get the axis and hat to disable.

Can you get me pointed into the right direction? Thanks! (Leonardo R3, if it matters)

Unknown said...

Ok, I had to get creative. I figured it out though. I used the Gamepad Example and did this:

// Simple gamepad example that demonstraits how to read five Arduino
// digital pins and map them to the Arduino Joystick library.
//
// The digital pins 2 - 6 are grounded when they are pressed.
// Pin 2 = UP
// Pin 3 = RIGHT
// Pin 4 = DOWN
// Pin 5 = LEFT
// Pin 6 = FIRE
//
// NOTE: This sketch file is for use with Arduino Leonardo and
// Arduino Micro only.
//
// by Matthew Heironimus
// 2016-11-24
//--------------------------------------------------------------------

#include

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
24, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
false, false, false, // No Rx, Ry, or Rz
false, false, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering

void setup() {
// Initialize Button Pins
pinMode(1, 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);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(17, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);

// Initialize Joystick Library
Joystick.begin();
//Joystick.setXAxisRange(-1, 1);
//Joystick.setYAxisRange(-1, 1);
}

// I added this
const int pinToButtonMap = 0;

// Last state of the button
int lastButtonState[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0};

void loop() {

// Read pin values
//for (int index = 0; index < 24; index++)
//{
// int currentButtonState = !digitalRead(index + 2);
// if (currentButtonState != lastButtonState[index])
//{
// switch (index) {
// case 0: // UP
// if (currentButtonState == 1) {
// Joystick.setYAxis(-1);
// } else {
// Joystick.setYAxis(0);
// }
// break;
// case 1: // RIGHT
// if (currentButtonState == 1) {
// Joystick.setXAxis(1);
// } else {
// Joystick.setXAxis(0);
// }
// break;
// case 2: // DOWN
// if (currentButtonState == 1) {
// Joystick.setYAxis(1);
// } else {
// Joystick.setYAxis(0);
// }
// break;
// case 3: // LEFT
// if (currentButtonState == 1) {
// Joystick.setXAxis(-1);
// } else {
// Joystick.setXAxis(0);
// }
// break;
// case 4: // FIRE
// Joystick.setButton(0, currentButtonState);
// break;
// }
// lastButtonState[index] = currentButtonState;
// }
// }
for (int index = 0; index < 24; index++)
{
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index])
{
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
}
}
delay(50);
}

Matthew Heironimus said...

@Ben P - Glad you were able to get something working. Sorry for the delay in getting to your comment. I have been falling behind in answering requests.

DeAnander said...

Hi Matthew and many thanks for the Joystick Library v2.0

Rather than waffle on at length here, I will post a link to my unanswered question on Arduino forum

http://forum.arduino.cc/index.php?topic=468358.0

I have almost -- but not quite -- got the hang of HID joystick emulation :-) I can make my Arduino actuate a selected axis, no problem; but I have not figured out how to expose all the axes to the application level, or how to make them map to the axes that any given game is expecting to find when the user configures input devices. I think I'm just one key concept away from enlightenment here... can you point me at an article or document that will make that last connection for me?

Matthew Heironimus said...

@Kuba Tatara - I uploaded your sketch file to my Leonardo and it worked fine for me. As I adjusted my variable resister, both the value on the serial monitor and the value of the brake on the Window's game controller test dialog seemed to match. One thing to note: it has been my observation that the Window's game controller test dialog must have focus or it will not update. The Serial Monitor can be running in the background, however.

Matthew Heironimus said...

@Kuba Tatara - You can ignore the DynamicHID.h. It is used internally, but does not have to be included in your sketch file. It was being incorrectly included in early versions of 2.0.x, but the current version 2.0.3 this issue has been corrected.

Yves Maurischat said...

Hi Matthew, I'm in the process of building my own little Raspberry Pi based retro gaming console and your library will be of great help. Awesome work!
I've got one question though: The standard joystick constructor has 32 buttons. How would I get 32 buttons from the pins of an Arduino (Micro) (or a Pro Micro)? The only way I can think of would be to map multi-button-pushes/pin activations to single (API-level) buttons. Or am I missing something?
Also, let's assume I would like to switch between Joystick and Mouse input using the same controller (and thus the same buttons and joysticks/d-pads). Would it suffice to just send different commands/call the right functions (like Mouse.move(...), Mouse.press(...)) instead of the Joystick commands? Or is there something that has to be done with the HIDs?

Yves Maurischat said...

Ps.: I also noticed that Joystick.end() is empty and does nothing. Is this by design? If so, would there be any reason to call it?

Matthew Heironimus said...

@Yves Maurischat

> How would I get 32 buttons from the pins of an Arduino (Micro) (or a Pro Micro)?
There are various techniques one can use to do this. I have listed a few for your reference:
- https://www.instructables.com/id/How-to-Multiple-Buttons-on-1-Analog-Pin-Arduino-Tu/
- http://www.instructables.com/id/How-to-access-5-buttons-through-1-Arduino-input/
- https://www.arduino.cc/en/Tutorial/ShiftIn


> Would it suffice to just send different commands/call the right functions (like Mouse.move(...), Mouse.press(...)) instead of the Joystick commands?
Yes

> Or is there something that has to be done with the HIDs?
No. The Arduino Micro can appear as multiple USB devices at the same time (e.g. Keyboard, Mouse, and Joysticks)

Matthew Heironimus said...

@Yves Maurischat

> I also noticed that Joystick.end() is empty and does nothing. Is this by design? If so, would there be any reason to call it?
You do not need to call it. It was just added so the interface of the Joystick would be similar to the Mouse and Keyboard.

Yves Maurischat said...

Thank you! That helped a lot! :)

Unknown said...

Thank you for the sample code it was very helpful! how could I go about mapping the value from the potentiometer to the X axis to make a game character turn left or right?

Unknown said...

All of this is daunting to me Matthew. My goal is to use this in my button box creation. Is it possible to have 28 - 30 button presses and 2 analogue stick using an arduino pro micro? And how do I best go about learning what I need to accomplish?

Matthew Heironimus said...

@Bryan Davidson - In order to get that many buttons on a Arduino Pro Micro, you will need to use some extra circuitry. There are various techniques you can use to read more that one button with a single Arduino pin. The following are a few techniques one can use to do this:
- https://www.instructables.com/id/How-to-Multiple-Buttons-on-1-Analog-Pin-Arduino-Tu/
- http://www.instructables.com/id/How-to-access-5-buttons-through-1-Arduino-input/
- https://www.arduino.cc/en/Tutorial/ShiftIn

Matthew Heironimus said...

@Shawn Roelofsen - To map a potentiometer value to the X or Y axis all you need to do is read in the value and call the appropriate Joystick function (e.g. Joystick.setXAxis or Joystick.setYAxis). The following is a sketch that shows how to read A0 and set the steering. This could be modified to set X instead.

#include <Joystick.h>

/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the serial monitor.
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

This example code is in the public domain.
*/

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 4, 0,
false, false, false, false, false, false,
false, false, false, false, true);

// the setup routine runs once when you press reset:
void setup() {

// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}

Joystick.setSteeringRange(1000, 50);
Joystick.begin();

// Init Pins
pinMode(A0, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {

// read the input on analog pin 0:
int sensorValue = analogRead(A0);

Joystick.setSteering(sensorValue);

// print out the value you read:
Serial.println(sensorValue);
delay(200); // delay in between reads for stability
}

Unknown said...

will this code press a the joystick button when i press a button connected to pin 13?

am i missing something here?



//Testing the joystick button connected to pin 13
#include

//buttons
const int ALT_UP = 13;

int ALT_Upstate = 0;

void setup() {

Serial.begin(57600);
pinMode(ALT_UP , INPUT_PULLUP);
Joystick.begin();

}

void loop() {


// checks if a button is being pressed
ALT_Upstate = digitalRead(ALT_UP);

if ( ALT_Upstate == LOW) {

Joystick.pressButton(ALT_UP);
delay(10);
Joystick.releaseButton(ALT_UP);
delay(120);
}
}

Matthew Heironimus said...

@Eli Cherem - It looks like your code will press button 14 (or thirteen if you consider the first button #0) for 10 milliseconds and then release it. I suspect you will not be able to see a button press that is that short. I recommend you look at the example at https://github.com/MHeironimus/ArduinoJoystickLibrary#simple-example. This is a simple push button example.

Marc said...

Hi Matthew.

How would I go about changing the device name from "Arduino Leonardo" to one of my own choosing?

Matthew Heironimus said...

@Marc - There is a long discussion about this at https://github.com/MHeironimus/ArduinoJoystickLibrary/issues/14. This is not currently supported, but can be done by following some of the instructions provided in the discussion.

Marc said...

@Matthew Thanks for the link. I know you can change the name in the USB core source files, I was able to do it with STM32 boards, and using the STM32Cube profiler its a simple config change for the board your programming, but Arduino is not so straight forward it would seem.

Unknown said...

Hi Matthew!

Which pins do we use on the Arduino for the x and y data from the potentiometers? I'm not seeing it in the code but I'm probably overlooking something...

Matthew Heironimus said...

@Ashley Webb

You can use any of the analog pins you like (A0 - A5). You read the analog value from the pin and then call the appropriate set?Axis function (i.e. setXAxis, setYAxis, or setZAxis).

Unknown said...

Dear Matthew,

I really Need help now. I use the following sketch to use digital and analog pins as Joystick Buttons. It works very well and I can use 20 pins. But now I Need the analog pins for potentionmeters as I will use it as throttle. I Need 3 Rotation axis. How to modify this sketch to have 17 Buttons and 3 rotation axis?
Highly appreciate any help!

// Simple gamepad example that demonstraits how to read five Arduino
// digital pins and map them to the Arduino Joystick library.
//
// The digital pins 2 - 6 are grounded when they are pressed.
// Pin 2 = UP
// Pin 3 = RIGHT
// Pin 4 = DOWN
// Pin 5 = LEFT
// Pin 6 = FIRE
//
// NOTE: This sketch file is for use with Arduino Leonardo and
// Arduino Micro only.
//
// by Matthew Heironimus
// 2016-11-24
//--------------------------------------------------------------------

#include

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
24, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
false, false, false, // No Rx, Ry, or Rz
false, false, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering

void setup() {
// Initialize Button Pins
pinMode(1, 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);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(17, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);

// Initialize Joystick Library
Joystick.begin();
//Joystick.setXAxisRange(-1, 1);
//Joystick.setYAxisRange(-1, 1);
}

// I added this
const int pinToButtonMap = 0;

// Last state of the button
int lastButtonState[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0};

void loop() {

// Read pin values
//for (int index = 0; index < 24; index++)
//{
// int currentButtonState = !digitalRead(index + 2);
// if (currentButtonState != lastButtonState[index])
//{
// switch (index) {
// case 0: // UP
// if (currentButtonState == 1) {
// Joystick.setYAxis(-1);
// } else {
// Joystick.setYAxis(0);
// }
// break;
// case 1: // RIGHT
// if (currentButtonState == 1) {
// Joystick.setXAxis(1);
// } else {
// Joystick.setXAxis(0);
// }
// break;
// case 2: // DOWN
// if (currentButtonState == 1) {
// Joystick.setYAxis(1);
// } else {
// Joystick.setYAxis(0);
// }
// break;
// case 3: // LEFT
// if (currentButtonState == 1) {
// Joystick.setXAxis(-1);
// } else {
// Joystick.setXAxis(0);
// }
// break;
// case 4: // FIRE
// Joystick.setButton(0, currentButtonState);
// break;
// }
// lastButtonState[index] = currentButtonState;
// }
// }
for (int index = 0; index < 24; index++)
{
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index])
{
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
}
}
delay(50);
}

Greetings Danny

Unknown said...

Please help...

Matthew Heironimus said...

@Dennie Theissen - What you need to do is as follows:

Reconfigure three of the analog pins to be INPUT, rather than INPUT_PULLUP.

Wire each of your potentionmeters to these analog pins.

In the loop function, remove the existing UP, DOWN, LEFT, RIGHT logic.

In your loop function, read the value of each pin (using the analogRead function) and send it to the Joystick.setXAxis (or Y or Z) functions.

Hope this helps.

Unknown said...
This comment has been removed by the author.
Unknown said...

Hi Matthew.

I have been pondering a lot lately.
I am trying to get a cd4021 shiftregister to work with the jostick.h.
Is there an example somewhere to be downloaded ?

Somehow i can not get it to work, have been reading the above links.
So an example would be very helpful.
Thanks

Unknown said...
This comment has been removed by the author.
Unknown said...

Hi Matthew
Is there an example code somewhere with the shiftin register code (cd4021) somewhere to be found.
Been reading a lot of links but couldn't find a link with the shiftin and jostick.h merged.
thanks in advance

Unknown said...

Hi Matthew,

I'd like to start by saying I think it's great you're still supporting this library so well, and helping users get it working for them. I've got a fair bit of experience in C# and VB.net, but this is my first foray into Arduino, so forgive the rookie mistakes...

I'm trying to get a simple 2-Axis, 2-Button joystick working using your library, but can't seem to figure out exactly where my issue is. I've got it showing up correctly in my devices, and get no errors compiling/uploading to my board, but none of the inputs seem to be doing anything. I'm using an off-brand Arduino Micro, and it shows up in devices as "Arduino Leonardo".

Here's the sketch I'm trying to get working:

// Pin A2 = X Axis
// Pin A3 = Y Axis
// Pin 10 = Button 1
// Pin 16 = Button 2
//
//--------------------------------------------------------------

#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 2, 0, true, true, false, false, false, false, false, false, false, false, false);

void setup() {

Serial.begin(9600);
while (!Serial) {
;
}

pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(10, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);

Joystick.begin();
Joystick.setXAxisRange(-512, 512);
Joystick.setYAxisRange(-512, 512);
}

void loop() {

// X-Axis
int xAxis = analogRead(A2);
Joystick.setXAxis(xAxis);
Serial.println(xAxis);

// Y-Axis
int yAxis = analogRead(A3);
Joystick.setYAxis(yAxis);
Serial.println(yAxis);

// Button 1
int button1State = !digitalRead(10);
if (button1State = 1)
{
Joystick.pressButton(0);
}

// Button 2
int button2State = !digitalRead(16);
if (button2State = 1)
{
Joystick.pressButton(1);
}
}


Thanks in advance,

Patrick

Unknown said...

A found one of those rookie mistakes I mentioned... I didn't check the serial monitor...

So it seems My joystick is outputting X and Y axis as intended to the serial monitor, but what do I need to change so that I can see my actions on the Windows game controller settings panel?

Matthew Heironimus said...

@Patrick McEnaney

One thing I have noticed is you set the X and Y axis range to go from -512 to 512, but Arduino analog pins go from 0 to 1023 by default. This happens to be the default for the Joystick library, so you should be able to remove those lines.

Another thing to watch for is you need to have a delay in your loop or you can "overload" things. Adding a delay(50); might be a good idea.

Note: The Windows Game Controller Settings panel will only update if it has focus.

Have you tried using any of the example projects that come with the library?

Unknown said...

Thanks for the reply.

I'll remove the axis range, since I guess it isn't needed, but being new to this, where exactly should I add the delay in my code?

And yes, I've fooled around with the example files, and had them working just fine in the Game Controller Dialog (except for some reason the button set to PIN 10 isn't working, and I'm not sure why; I've tried with two different joysticks, so my next step is to try a different pin, in case PIN 10 might by faulty on my board), but couldn't figure out how to adapt them to my use-case, so I figured starting from scratch was my best bet. I'm not sure what I'm missing that's causing my sketch to not work in the dialog though...

Unknown said...

Adding a delay seems to have fixed my joystick axis (although I still don't exactly understand why, lol). But now my issue is that both of my buttons are stuck in the "ON" state, and pressing them doesn't do anything. I tried switching `if (button1State = 1)` to "0", but that just makes them stuck in the "OFF" state. Where am I going wrong with this part?

Also, I added a delay on the buttons too, is this necessary?

Thanks

Unknown said...

Dear Patrick,

Use the following Sketch.
Then you have 6 axis and 14 buttons

#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
14, 0, // Button Count, Hat Switch Count
false, false, true, // X and Y, but no Z Axis
true, true, true, // Rx, Ry, or Rz
false, true, // rudder or throttle
true, false, false); // accelerator, brake, or steering

// declare variables
int axe1Value;
int axe2Value;
int axe3Value;
int axe4Value;
int axe5Value;
int axe6Value;


// init joystick libary
void setup() {
// Initialize Button Pins
pinMode(0, INPUT_PULLUP);
pinMode(1, 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);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);

// Initialize Joystick Library
Joystick.begin();
}

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 0;

// Last state of the button
int lastButtonState[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void loop() {
// Axe 1
axe1Value = analogRead(A0);
Joystick.setThrottle(axe1Value);
delay(1);

// Axe 2
axe2Value = analogRead(A1);
Joystick.setZAxis(axe2Value);
delay(1);

// Axe 3
axe3Value = analogRead(A2);
Joystick.setRxAxis(axe3Value);
delay(1);

// Axe 4
axe4Value = analogRead(A3);
Joystick.setRyAxis(axe4Value);
delay(1);

// Axe 5
axe5Value = analogRead(A4);
Joystick.setRzAxis(axe5Value);
delay(1);

// Axe 6
axe6Value = analogRead(A5);
Joystick.setAccelerator(axe6Value);
delay(1);


// Read pin values
for (int index = 0; index < 14; index++)
{
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index])
{
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
}
}

delay(50);
}

Unknown said...

Turns out something was wrong with the serial communication I had set up. I removed it, and now everything is working fine (except for one button, but I think it may be a faulty pin).

Here is what I ended up with incase it helps someone else in the future:

// Pin A2 = X Axis
// Pin A3 = Y Axis
// Pin 16 = Button 1
// Pin 10 = Button 2
//
//--------------------------------------------------------------

#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 2, 0, true, true, false, false, false, false, false, false, false, false, false);

void setup() {

pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(16, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);

Joystick.begin();
}

void loop() {

// X-Axis
int xAxis = analogRead(A2);
Joystick.setXAxis(xAxis);

// Y-Axis
int yAxis = analogRead(A3);
Joystick.setYAxis(yAxis);

// Button 1
int button1State = !digitalRead(16);
if (button1State == 1)
{
Joystick.pressButton(0);
}
else
{
Joystick.releaseButton(0);
}

// Button 2
int button2State = !digitalRead(10);
if (button2State == 1)
{
Joystick.pressButton(1);
}
else
{
Joystick.releaseButton(1);
}

delay(50);
}

Thanks for the help!

Matthew Heironimus said...

@Patrick McEnaney - Glad to hear you got it working.

Unknown said...

Hi Matthew, I've got my simple joystick working but now I'm having issues with my 2nd project with your library. I'm using the same code that I got working with my joystick, but modified it to have a total of 8 buttons and 2 axis for a custom gamepad I've made. Everything worked exactly as planned at first, but the 2nd time I plugged it in I'm getting random twitchy movements on the thumbstick (which seems to favor the bottom-right corner) and most of the time "button 8" is stuck in the "ON" position, with 3 other buttons behaving erratically. "Button 8" is also stuck "ON" if I power up the board without even connecting my buttons to it.

I know my code is fine, because it worked exactly as intended at first, but all of a sudden it's behaving very erratically.

If I plug my joystick into the board, and reupload my original code for the joystick it works fine. It just seems to behave this way when I switch to my 8-button/2-axis sketch.

Any ideas? I've triple-checked my code, and there shouldn't be any issues there (as I said, it was working at first and I've made no changes to the code since).

Thanks,

Patrick

Matthew Heironimus said...

@Patrick McEnaney - I would go ahead and submit an issue on the GitHub site (https://github.com/MHeironimus/ArduinoJoystickLibrary). Someone in the community may have an idea what is going on.

These kinds of issues do sometimes turn out to be code related, so I would be sure to include a copy of your sketch file in your issue submission.

Unknown said...

Yet another question Matthew...

I didn't see it listed anywhere on GitHub, but I'd like to add a deadzone to my joystick (same sketch as listed above), but I'm not sure if it's possible with your library or not.

My theory was that if I set 'autosendstate' to 'false' and wrote an 'if' statement that would poll my joystick to see if either axis was outside of my desired deadzone and 'then' either 'Joystick.begin()' or 'Joystick.sendState()' else 'break' or something similar.

Am I on the right track?

Thanks.

Anonymous said...

Dennie Theissen, I'm interested in your code, but how do you use pins 0 and 1, does not it conflict with serial communication? How did you solve it?

Mik said...

I don't know if this is related to your work, but I've come across some Arduino-based joysticks/adapters where in DirectInput the reported X axis range is 0-0 for buttons (instead of, say, 0-65535). That is not considered a valid range by some apps.

I am trying to establish whether there is an issue in interpretation, in hardware or in drivers. Any thoughts?

Unknown said...

Hi Matthew
I am looking to create my own rudder pedal set and your code looks ideal (I'm definitely not a programmer, simply a user/adaptor). I have loaded your code and tried to compile the test programmes but get an error that the #include cannot be found. I note that the dynamicHID.h is not included in the joystick sketch code but is referenced in the Joystick.h file. I also note that the dynamicHID.h file is included as part of the download from GitHub. I've tried relocating the dynamicHID.h file into different folders to see if the compiler picks it up without success.
Any guidance would be appreciated.
Martin

Matthew Heironimus said...

Martin,

The error you describe usually is a result of the library not being installed correctly. When you open the Arduino IDE, click on File -> Examples and scroll to the bottom of the list. You should see an entry in the "Examples from custom libraries" section called Joystick. Another thing to check is the "Library Manager" (Sketch -> Include Library -> Manage Libraries...). If the library is installed correctly, you should see an entry called Joystick by Matthew Heironimus Version 2.0.5 INSTALLED. If either of these things are not present, the library was not installed correctly. Installation instructions can be found at https://github.com/MHeironimus/ArduinoJoystickLibrary/#installation-instructions.

Hope this helps,
Matt

Unknown said...

Hi again Matthew
I'm not a blogger so please forgive my poor protocol and appearing as unknown.
My first comment this morning referred to the compiler not being able to find the dynamicHID.h file - the posted message seems to have been corrupted during the upload.
I have a second question - could you please confirm that your code support 12-bit resolution (i.e. two 8-bit bytes to send a signed integer) for joystick/analogue inputs?
Many thanks
Martin

Unknown said...

Hi Matt
Re-installation - all now good - I'd made a numpty error. Sorry to have wasted your time a school boy mistake.
Many thanks
Martin

Matthew Heironimus said...

Martin,

DynamicHID.h is included in the Joystick\src\DynamicHID folder and should have been installed when the deploy.bat (or deploy.sh if you are on Linux) was executed.

The library supports up to 16 bits of precision. That being said, the analog pins on most Arduino boards (at least the ones I have worked with) are only 10-bits in resolution. That is why the library defaults axis from 0 to 1024. If you are using some other mechanism to read in analog values, then you can get up to 16-bits (or -32,768 to 32,767).

Matt

Unknown said...

Matthew,
Many thanks for your timely responses.
Best regards,
Martin

Unknown said...

Matthew
Re precision/resolution of analogue inputs.
The API documentation refers to, typically, .setXAxis(byte value) and a range of -127 to +127. This implies 8-bit (i.e. one byte) resolution over the USB interface. How does the code handle 10-bit (-512 to +512) or higher resolution (implying two 8-bit bytes to hold the digital representation of the analogue value)?
I suspect I'm missing something obvious but can't see any references anywhere else to greater than 8-bit resolution.
Kind Regards,
Martin

Matthew Heironimus said...

Martin,

You may be refering to older documentation (i.e. version 1.0). The current version shows Joystick.setXAxis(int16_t value) having a 16-bit value. See https://github.com/MHeironimus/ArduinoJoystickLibrary#joysticksetxaxisint16_t-value for more details.

Matt

Unknown said...

Hi Matthew,

That will be the reason! I'm not sure how I managed to get an older version, but many thanks for persevering with me.

Kind regards,
Martin

Unknown said...

Hi Matthew,

The ‘bad penny’ has turned up again.
With your previous help I have a sketch that compiles and loads successfully to my Arduino Micro.

However, it does not appear as a HID. I have tried a couple of the test examples from the joystick library (without inserting any changes!), but the result is always the same.

In Device Manager I can see the Micro as a USB device (on Com 8) and I can see that there are 2 entries in the Device Manager/HID list that relate to the Micro - one as a "HID-compliant device" and one as a "USB Input Device" (the HID entries are not explicitly identified as the Micro but by inserting/removing the Micro and recording differences in the Device Manager's HID list I have been able to isolate which entries appear/disappear when the Micro is connected/not connected). If I double click either of these [HID list] entries the HID-compliant device properties dialogue opens where everything looks OK, except on the Events tab where there are 3 Events listed, all with the same timestamp. The descriptions of these events are:
"Device not migrated"
"Device configured (input inf)"
"Device started (HIBUsb)"

The information text box (on the HID-compliant device properties dialogue) for the "Device not migrated" event reads:
"Device USB\VID_2341&PID_8037&MI_02\6&1163e5c6&0&0002 was not migrated due to partial or ambiguous match.
Last Device Instance Id: USB\VID_04D9&PID_1603&MI_01\6&34E0FEB6&0&0001
Class Guid: {745A17A0-74D3-11D0-B6FE-00A0C90F57DA}
Location Path:
Migration Rank: 0xF000FFFF0000F120
Present: false
Status: 0xC0000719"

I have Googled (a lot today) finding many references/’resolutions’ to "Device not migrated" issues and problems associated with corrupt/’bad’ drivers. I have tried several of the recovery methods (such as deleting/re-installing new/updated drivers) but, despite all efforts, I remain in a "Device not migrated" situation. (The issue only affects the HID configuration as the serial comms still works because I can update the sketch on the Micro.)

I'm using Windows 10 (ver 1803, OS build 17134.407) and Arduino IDE v 1.8.5.

I appreciate with is not directly involved with the Joystick library but any thoughts/advice would be appreciated (hopefully it's just another simple issue).

Kind regards,
Martin

Unknown said...

Hi Matthew,
Further investigation indicates my previous missive may be a red herring (after great effort to eliminate fish)! "Events" in device/properties are entered as last at the bottom (not at the top as I thought previously), which puts a different spin on things. It seems the drivers are correctly installed and running. However this still leaves the basic problem of the Micro not being seen as a joystick/game controller (as well as a serial device).
I have now tried the Micro on 2 other Windows 10 machines and get exactly the same results - it appears in Device Manager in the following areas:
HID list as a HID-compliant device and USB Input Device;
Ports (COM & LPT) list as Arduino Micro (COMx); and
USB Controllers list as USB Composite Device.

(I've assumed the Micro can operate simultaneously as a serial device and a joystick.... or does it have to be somehow 'switched' between functions?).

Any thoughts/guidance would be appreciated.

Kind Regards,
Martin

Matthew Heironimus said...

Martin,

The Micro can appear as a Joystick, Mouse, and Keyboard all at once if the correct header files (e.g. Mouse.h, Keyboard.h, and Joystick.h) are included in the sketch file. The JoystickKeyboard example that is include with the library demonstrates this ability. It will always appear as a serial port as well.

I will have to investigate your issue further to provide any more information.

Matt

Unknown said...

Hi Matt,

Thanks for your reply.

I have good news - I have tried several other things today without success then, in desperation, I removed and reloaded IDE (now ver 1.8.7). After this I loaded the flightcontroller example (twice) without any change in outcomes. I then loaded the JoystickTest example which worked instantly. I then retried flightcontroller example, my developmental version of flightcontroller and joystick where all worked instantly. I have removed and re-inserted the micro several times with one or other of the 3 sketches loaded and it seems rock solid.

I have noted that sometimes the Micro comes up on COM4 and other times on COM6 (seems to be a random selection at this point of investigation). I also note that in the programme load progress/report window at the bottom of the IDE window it always seems to refer to "Using COM port 5". I'm not sure if this apparent discrepancy is a predictable situation or error.

Anyway - for now at least, the Micro is doing what I want (albeit I haven't contributed anything to the functionality yet) and, assuming it remains stable/predictable, provides a good reference point where any problems are due to my code [in]ability.

Thanks for your support on what has been a frustrating rather than challenging issue.

Best regards,
Martin

Unknown said...

Hi Matthew,

This time I have some real observations(!).

As I noted yesterday, the sketch seems to be working as it should, I even get the data appearing in my target application DCS World, so all good - except:
I have 7 axis active in Joystick namely X, Y, Z, Rudder, Throttle, Brake, Steering (I appreciate Z, rudder and steering are synonymous but they do get used differently as rudder, left wheel brake and view zoom; brake is used as right wheel brake). However, only 5 of the 6 axis show in Microsoft's Game Controller and in DCS (rudder & steering do not shown).

I then changed the Rudder data to be on AxisRz and Steering data to be on AxisRy. In Game Controller and DCS the 2 new channels appear but Brake disappears (now a total of 6 axis).

I then tried all examples in the Joystick library and noted:
Driving Controller only displayed Brake - Accelerator and Steering were not displayed.
Flight Controller Test had all 3 axis and 32 buttons displayed.
Gamepad had all 2 axis and 1 button.
HAT Switch Test had 4 buttons but only 1 of the 2 HATs (maybe a limitation of Game Controller)
Analysis of the 3 remaining examples were inconclusive as Game Controller might have limited capacity.

I have also increased the delay between Axis reports to 10 (from 1) without improvement.

Is there any reason why Joystick might limit the numbers of axis reported?

I will try further testing with Planet Pointy but wondered if you had any thoughts that might be related to the issue.

Best regards,

Martin

Chris Del Castor said...

Hi Matthew!

I am trying to put together a working 7-axis 8-button setup.

[Code]
#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
JOYSTICK_TYPE_MULTI_AXIS, 8, 0,
true, true, false, true, true, false,
false, true, false, true, true);
[\Code]

Nothing special there, but I need one axis to be controlled by two separate inputs.
I'm going to use two load cells (or something similar) for the "steering" axis.

Is it somehow possible to set something like Steeringleft from A0 and Steeringright from A1, or how should I get around this problem?

Best regards,

Chris

Anonymous said...

Hi,

Why this simple accelerator example does not work with me?

I am using slider potentiometer.

Is the hardware wrong type?

This slider potentiometer works if it is marked as rotational axis.



#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 32, 2, true, true, true, true, true, true, true, true, true, true, true);

void setup() {
int axe5Value;
pinMode(A5, INPUT);
Joystick.begin();
}

void loop() {


int axe5Value = analogRead(A5);
Joystick.setAccelerator(axe5Value);


delay(50);
}

Anonymous said...

Hi, I'm building a video game console and I wanted to make sure that using a button on this console lights up a LED and then pressing the same button again turns the LED off. What I can't understand is how to keep the LED lit until the button is pressed again. (example: pin 2 button, pin 3 led). Can anyone help me, please?

Luan Luckemeier said...

Porque as portas digitais não funcionam?

Luan Luckemeier said...

Porque as portas digitais não funcionam?

Roven said...

Dennie Thiessen

Thank you for the 6 axis 14 button sketch! It has me up and running immediately and makes understanding the code much easier.

As I was setting up switches and pots on a breadboard I decided to try and use a PS2 thumb stick on pins A05 and A06 for their X and Y input.
While I didn't expect it to work (there is no code for a thumb stick) I still had partial success; one axis worked. However, if I moved one axis off of pin A05 and put it on pin A03 (Y Rotation I think) the axis on pin A06 stopped working. I'm assuming this has to do with the thumbstick having the 2 axis wired together internally. But, when I wired the thumbstick to the RY and RX axis, both axis worked fine.
What got me interested is that pin A06 for Accelerator showed up in what is typically the thumbstick graphic box in Windows game controller settings. Why? Does Windows know it's a thumbstick and belongs there? I didn't have time to put a normal potentiometer on A06 to see if Windows saw it differently and took it out of the thumbstick box but I will tomorrow.
I'm not trying to solve an actual problem but trying to understand the relationship between the Arduino and how Windows sees it as a game controller. I'm completely new to this as is obvious.
Last question, if I replaced two of the axis with code for the thumbstick, does the code have to be completely rewritten or can much of the code for the thumbstick be inserted and adjusted?

Thank you again for the sketch.

Roven said...

I figured out the reason for only seeing one axis of the thumbstick. The power pin was not in the right hole on the bread board..... Also, I had no need for the code to enable the thumbstick as the code you posted saw it as an axis once I put it on the pins for RX axis and RY.

Thank you again.

Chris Mitchell

Fer Goosen said...

Hello M. Heironimus,
I am currently working on a helicopter controller where I use your library and want to connect a series of 5 switches with resistors to pin A7 with a 100K resistor between A7 and earth. This means that I should be able to read the values of the different switches (resistors). However, this does not work. In the serial monitor I only see a huge wave movement that is not influenced by the switches. If I connect the whole to A6 (or A5 or A4 etc) then it works well. I have tried different (Leonardo) boards but all gave the same result.

Up to A6 I have in use and therefore actually need one more analog port, but I get the impression that v.a. A7 they are not real analogue ports. Can I perhaps solve this in the sketch? Or is there another way?

I hope you can help me.

Thank you, Fer

Fer Goosen said...

I found it! On the back of the board is A7, A8, A9, A10, A11, but according to a pinout overview, A7 is actually A11! So very confusing!

For your information:
pin 4 = A6
pin 6 = A7
pin 8 = A8
pin 9 = A9
pin 10 = A10
pin 12 = A11

Not very logical that it is completely different on the back of the board. This will put you on the wrong track.

But it works now and is therefore solved

Fer

Darkseide said...

Hi everyone, I just wanna say thank you for this awesome library. A have a Guitar Hero guitar controller and I wanted to play Clone Hero on PC but the main board of the guitar was no longer working so I replaced it for an Arduino Leonardo. And work flawless, better than the original I would say. I've only activated the buttons that I needed on joystick settings. Here is the code, I hope it could help you guys a bit.

https://github.com/JacksonFSilva/CLONE-HERO

Darkseide said...

Hi everyone, I just wanna say thank you for this awesome library. A have a Guitar Hero guitar controller and I wanted to play Clone Hero on PC but the main board of the guitar was no longer working so I replaced it for an Arduino Leonardo. And work flawless, better than the original I would say. I've only activated the buttons that I needed on joystick settings. Here is the code, I hope it could help you guys a bit.

https://github.com/JacksonFSilva/CLONE-HERO

Darkseide said...

Hi everyone, I just wanna say thank you for this awesome library. A have a Guitar Hero guitar controller and I wanted to play Clone Hero on PC but the main board of the guitar was no longer working so I replaced it for an Arduino Leonardo. And work flawless, better than the original I would say. I've only activated the buttons that I needed on joystick settings. Here is the code, I hope it could help you guys a bit.

https://github.com/JacksonFSilva/CLONE-HERO

Darkseide said...

Hi everyone, I just wanna say thank you for this awesome library. A have a Guitar Hero guitar controller and I wanted to play Clone Hero on PC but the main board of the guitar was no longer working so I replaced it for an Arduino Leonardo. And work flawless, better than the original I would say. I've only activated the buttons that I needed on joystick settings. Here is the code, I hope it could help you guys a bit.

https://github.com/JacksonFSilva/CLONE-HERO

Fer Goosen said...

Hello M. Heironimus,

I want to put together a sketch which has 1 Hat switch and 4 buttons. I use your sample hat "SwitchSwitch Test". I managed to adjust this to 1 hat switch and that works. Now I want to read the 4 other buttons. I use pins 1, 2, 3, 4 for the buttons and 8, 9, 10, 11 for the Hatswitch. I've been working on it for 3 days but I just can't get it working. How can I solve this problem?

I also want to add 3 more axes (joystick X, Y and rudder). I succeeded, but I don't get the point of rest in the middle. They are also shaking properly.
How can I also solve this problem?

My customized sketch for the Hatswitch / buttons:


// by Matthew Heironimus
// 2016-05-30
//--------------------------------------------------------------------

#include

Joystick_ Joystick(0x31, 0x05, 12, 1,
false, false, false, false, false, false,
false, false, false, false, false);

// declare variables
const int pinToButtonMap = 0;


void setup() {

pinMode(0, INPUT_PULLUP);
pinMode(1, 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);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);

// Initialize Joystick Library
Joystick.begin();
}

int lastButtonState[4] = {0,0,0,0};

void loop() {
bool valueChanged[2] = {false, false};
int currentPin = 4;

// Read pin values
for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++)
{
for (int index = 0; index < 4; index++)
{
int currentButtonState = !digitalRead(currentPin++);
if (currentButtonState != lastButtonState[index])
{
valueChanged[hatSwitch] = true;
lastButtonState[index] = currentButtonState;
}
}
}

for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++)
{
if (valueChanged[hatSwitch]) {

if ((lastButtonState[0] == 0)
&& (lastButtonState[1] == 0)
&& (lastButtonState[2] == 0)
&& (lastButtonState[3] == 0)) {
Joystick.setHatSwitch(hatSwitch, -1);
}
if (lastButtonState[0] == 1) {
Joystick.setHatSwitch(hatSwitch, 0);
}
if (lastButtonState[1] == 1) {
Joystick.setHatSwitch(hatSwitch, 90);
}
if (lastButtonState[2] == 1) {
Joystick.setHatSwitch(hatSwitch, 180);
}
if (lastButtonState[3] == 1) {
Joystick.setHatSwitch(hatSwitch, 270);
}

} // if the value changed

} // for each hat switch

}

I hope you can help me again.
Fer

Anonymous said...

Hi everyone.
I wanted to make a controller with 25 buttons and 4 axes. I have reconstructed the scheme on this site (https://www.instructables.com/id/How-to-Multiple-Buttons-on-1-Analog-Pin-Arduino-Tu/) but I can't understand how to implement it with Matthew's code/library to make it work with windows 10.
Can anyone kindly help me and give me a little example?

ManLo said...

Hello there.
I downloaded the library and I saw that it can be used with an arduino DUE. But I can't get it to be recognized by my pc as a game controller. Any advice on that?

ManLo said...

Hello.
I'm trying to use the library with an Arduino DUE, but my pc doesn't recognize it as a game controller. Any advice please?

Unknown said...

Hi, thanks for this great library.

I just wanted to know if it is possible to rename the axis as they appear in the Windows control panel. So instead of being labelled as 'Z Axis' it could be labelled as 'Clutch'.

STD2A said...

Hi,

First thank you for providing such great library.
I am a newbie (55yo...)and it is highly appreciated.

With childrens at school we plan to build a flight controller for soaring with Condor (trim, airbrake, some buttons ... and rudder to add to a Thrustmaster T16000M joystick.

I meet an issue when I upload the code in an Arduino Micro.

Windows 10 recognizes GamepadExample, HatSwitchTest, JoystickButton, JoystickTest and MultipleJoystickTest as game controllers.

But when I want to use FlightControllerTest for testing before building, Windows 10 shows that it is a "not specified" device.

Did you meet this issue ?

Your feedback will be appreciated.
Thank you.
Gilles

moby said...

Hello Matthew. Thank you for providing these libraries.

Is there any reason for not detecting a joystick built with version 2.07 on FSX? This does not occur with version 1.0

Moby

Matthew Heironimus said...

@moby - Not that I know of, but I do not have FSX, so I cannot test it.

acc said...

Hello, first of all I congratulate you on its contents. I would like to ask a question, I want to make 3 pedals for my driving simulator. throttle, brake and clutch, but I'm too novice to perform electronics.
Buy arduino leonardo, by any chance you won't have a sketch already made for accelerator, brake and clutch, configured with 10 or 12 bit ?? it is possible 12 bit in arduino leonardo ??
I hope you can help me, but I also thank you and again I congratulate you on its content.

I'm sorry about my English, greetings from Argentina.

Matthew Heironimus said...

The Arduino Leonardo's analog inputs provide 10 bits of resolution (i.e. 1024 different values - see https://www.arduino.cc/en/Main/Arduino_BoardLeonardo for more details).

You can find various examples of how to use this library at https://github.com/MHeironimus/ArduinoJoystickLibrary/wiki/Examples.

Hope this information helps.

acc said...

Hello, thanks to your sketches I manage to make my potentiometers work properly, and using another sketch manage to run my 100kg load cell.
But I can't get them to work together in the same sketch. I'd appreciate it if anyone can help me, that's what I need to finish my 3-pedal set.

Nevohteeb said...

Hello everyone,

I am tying to deal with 2 genuine NES (2 axis and 4 buttons) and SNES (2 axis and 8 buttons) controllers on the same Arduino Micro.
I first created a sketch for the 2 NES controllers and it worked like a charm.
Then I created a sketch for the 2 SNES controllers and it also worked perfectly.

Now I merged the 2 sketches in the same file I experience a weird issue : only the 2 first controllers are recognised as controllers, the 2 last controllers are just recognised as buttons. In other words, if I declare the NES controllers first, I can see 2 gamepads with 2 axis and 4 buttons each, and then 20 other buttons. Note that the exact same thing happens if I declare the SNES controllers first but in this case I can se 2 gampads with 2 axis and 8 buttons each, and then 12 other buttons.

The weird thing is that the axis of the two last controllers are recognised as buttons, not as axis.

I then compiled the MultipleJoystickTest example and uploaded it in the Arduino Micro and the same thing happened : I can only see the 2 first controllers !!!.

Did anyone experienced the same thing ?

Matthew Heironimus said...

@Nevohteeb - I have not seen that particular issue before. Can you post the constructor calls for your joysticks? For example:

Joystick_(0x03, JOYSTICK_TYPE_GAMEPAD, 4, 2, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x04, JOYSTICK_TYPE_JOYSTICK, 8, 1, true, true, true, true, false, false, false, false, false, false, false),
Joystick_(0x05, JOYSTICK_TYPE_MULTI_AXIS, 16, 0, false, true, false, true, false, false, true, true, false, false, false),
Joystick_(0x06, JOYSTICK_TYPE_MULTI_AXIS, 32, 1, true, true, false, true, true, false, false, false, true, true, true)

You might try changing the ID number for the joysticks. Each one must be unique and it should not be 0, 1, or 2.

Nevohteeb said...

Hello Mathew,

thank you for your answer.
I chose the ID number carefully to be sure they are unique.

Here is the setup part of my sketch :

#include

#define NbrGamePad 4

Joystick_ Joystick[NbrGamePad] = {
Joystick_(0x10, JOYSTICK_TYPE_GAMEPAD, 4, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x11, JOYSTICK_TYPE_GAMEPAD, 4, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x12, JOYSTICK_TYPE_GAMEPAD, 8, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x13, JOYSTICK_TYPE_GAMEPAD, 8, 0, true, true, false, false, false, false, false, false, false, false, false)
};

uint16_t lastStatusNESPort1 = 0xffff;
uint16_t newStatusNESPort1 = 0xffff;
uint16_t lastStatusNESPort2 = 0xffff;
uint16_t newStatusNESPort2 = 0xffff;
uint16_t lastStatusSNESPort1 = 0xffff;
uint16_t newStatusSNESPort1 = 0xffff;
uint16_t lastStatusSNESPort2 = 0xffff;
uint16_t newStatusSNESPort2 = 0xffff;

#define clkPin 3
#define latchPin 9

#define NESdata1Pin 7
#define NESdata2Pin 8
#define SNESdata1Pin 16
#define SNESdata2Pin 14

#define latchLow digitalWrite(latchPin, LOW)
#define latchHigh digitalWrite(latchPin, HIGH)
#define clkLow digitalWrite(clkPin, LOW)
#define clkHigh digitalWrite(clkPin, HIGH)

#define NESdata1Read digitalRead(NESdata1Pin)
#define NESdata2Read digitalRead(NESdata2Pin)
#define SNESdata1Read digitalRead(SNESdata1Pin)
#define SNESdata2Read digitalRead(SNESdata2Pin)

#define clkSemiPeriodus delayMicroseconds(10)

int ControllerId = 0 ;

int NESConctroller1Id = 0 ;
int NESConctroller2Id = 1 ;
int SNESConctroller1Id = 2 ;
int SNESConctroller2Id = 3 ;

uint16_t NESoutput1 ;
uint16_t NESoutput2 ;
uint16_t SNESoutput1 ;
uint16_t SNESoutput2 ;

void setup()
{

// Serial.begin(9600) ;

// Initialize button pins
pinMode(latchPin, OUTPUT) ;
pinMode(clkPin, OUTPUT) ;
pinMode(NESdata1Pin, INPUT) ;
pinMode(NESdata2Pin, INPUT) ;
pinMode(SNESdata1Pin, INPUT) ;
pinMode(SNESdata2Pin, INPUT) ;

// Initialize joystick library
for (ControllerId = 0 ; ControllerId < NbrGamePad ; ControllerId++ )
{
Joystick[ControllerId].begin(false) ;
Joystick[ControllerId].setXAxisRange(-1, 1) ;
Joystick[ControllerId].setYAxisRange(-1, 1) ;
}

}

Matthew Heironimus said...

@Nevohteeb - I did a quick test with the following code and it worked as expected (i.e., two 4-button game controllers and two 8-button game controllers):

#include Joystick.h

#define NbrGamePad 4

Joystick_ Joystick[NbrGamePad] = {
Joystick_(0x10, JOYSTICK_TYPE_GAMEPAD, 4, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x11, JOYSTICK_TYPE_GAMEPAD, 4, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x12, JOYSTICK_TYPE_GAMEPAD, 8, 0, true, true, false, false, false, false, false, false, false, false, false),
Joystick_(0x13, JOYSTICK_TYPE_GAMEPAD, 8, 0, true, true, false, false, false, false, false, false, false, false, false)
};

void setup() {
// put your setup code here, to run once:

}

void loop() {
// put your main code here, to run repeatedly:

}

If you want to post an issue on the GitHub site (https://github.com/MHeironimus/ArduinoJoystickLibrary/issues), I can reply with my screenshots of it working.

What version of the Arduino IDE are you using? I used 1.8.19 for my test.

Nevohteeb said...

Dear Mathiew,

as you recommended I created an issue in the Github repository.
To better explain my problem I made a very simple sketch (4 controllers with only 1 button each) and posted the output provided by the Controllers Lite software.

Thank you very much for the time you are spending on my case :).

Unknown said...

#include

//variable
int val;

//constants
const int analogIn = A0;
const int minPot = 50;
const int maxPot = 700;

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
9, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
false, false, false, // No Rx, Ry, or Rz
false, true, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering

void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}


// Initialize Button Pins
pinMode(1, INPUT_PULLUP);//1st
pinMode(2, INPUT_PULLUP);//stick1
pinMode(3, INPUT_PULLUP);//2nd
pinMode(4, INPUT_PULLUP);//3rd
pinMode(5, INPUT_PULLUP);//4th
pinMode(6, INPUT_PULLUP);//5th
pinMode(7, INPUT_PULLUP);//6th
pinMode(8, INPUT_PULLUP);//stick2
pinMode(9, INPUT_PULLUP);//stick3

pinMode(A0, INPUT);

Joystick.setThrottleRange(0, 255);
Joystick.begin();
}
// Last state of the buttons
int lastButtonState[9] = {0,0,0,0,0,0,0,0,0};


void loop() {



// Read pin values
for (int index = 0; index < 9; index++)
{
int currentButtonState = !digitalRead(index + 2);
if (currentButtonState != lastButtonState[index])
{
switch (index) {
case 0: // 1st
Joystick.setButton(0, currentButtonState);
break;
case 1: // 2nd
Joystick.setButton(1, currentButtonState);
break;
case 2: // 3rd
Joystick.setButton(2, currentButtonState);
break;
case 3: // 4th
Joystick.setButton(3, currentButtonState);
break;
case 4: // 5th
Joystick.setButton(4, currentButtonState);
break;
case 5: // 6th
Joystick.setButton(5, currentButtonState);
break;
case 6: // stick1
Joystick.setButton(6, currentButtonState);
break;
case 7: // stick2
Joystick.setButton(7, currentButtonState);
break;
case 8: // stick3
Joystick.setButton(8, currentButtonState);
break;
}
lastButtonState[index] = currentButtonState;
}
}

int Val = analogRead(A0);
val = map(val, minPot, maxPot, 0, 255); //mapping value between min and max pot value
val = constrain(val, 0, 255); // Constrains min and max range between 0 and 255
//Serial.println(val);
// use the desired option
Joystick.setThrottle(val);

delay(20);
}


I have no input to my pc from a quick glance do you think this is a hardware or software issue.

Unknown said...

with the following code I constantly have no input from the first or second button in the controller in windows but the buttons are connected to pins 9 & 10, I've tried with different switches, on a breadboard, using 3 different pro micros. to rule out a hardware issue any help would be very appreciated.

"#include "Joystick.h"

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
9, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
false, false, false, // Rx, Ry, or Rz
false, false, // rudder or throttle
true, false, false); // accelerator, brake, or steering

// declare variables
int pot;


// init joystick libary
void setup() {
// Initialize Button Pins
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);
pinMode(10, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);


// Initialize Joystick Library
Joystick.begin();
}

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 0;


// Last state of the button
int lastButtonState[9] = {0,0,0,0,0,0,0,0,0};

void loop() {
// Axe 1
pot = analogRead(A0);
Joystick.setAccelerator(pot);
delay(1);

// Read pin values
for (int index = 0; index < 9; index++)
{
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index])
{
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
}
}

delay(50);
}"