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.



46 comments:

Matti Virta 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.

Ken Bou 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.

Matti Virta 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

Kuba Tatara 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??

Ben P 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)

Ben P 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! :)

Shawn Roelofsen 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?

Bryan Davidson 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
}

Eli Cherem 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.

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

Dennie Theissen 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

Dennie Theissen 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.
Martijn Hoving 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

Patrick McEnaney 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

Patrick McEnaney 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?

Patrick McEnaney 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...

Patrick McEnaney 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

Dennie Theissen 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);
}

Patrick McEnaney 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.

Patrick McEnaney 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