Many axis joystick

Where is the correct usb_desc.c to be modified located??

Teensy 4.0 Teensyuino 1.53, I can delete it from Teensy4 and Teensy3 folders and makes no difference, nor the changes I do on them.
 
I think this is the same question you asked in the usb descriptor fun thread...

If building for Teensy 4.x you use the files in cores\teensy4

If you delete the files I doubt it will build

The joystick stuff again depends on how you build the system and what the USB type is set to.

And again for joysticks. if you change the HID format in usb_desc.c (and .h) then you must also update the code that generates and sends the data.
which is in same core directory (usb_joystick.h and .c)

And if you change the actual size of the data (number of bytes) you will need to generate a new section in there as the code is setup like:
#if JOYSTICK_SIZE == 12
#elif JOYSTICK_SIZE == 64

And make sure you stuff the raw data into the right bits of the right bytes

Again this size needs to match the actual size of your data...
 
"If building for Teensy 4.x you use the files in cores\teensy4"

The problem is exactly that I can delete usb_desc.c from the teensy4 directory and it builds (and joystick works). The usb_desc.h on the same directory can not be deleted and the edits on that are effective.
 
Here is a video the usb_desc.c has been renamed usb_desc_d.c there is no usb_desc.c

The joystick name has been edited on the usb_desc.h that is on the same directory, so the directory should be correct.

https://vimeo.com/555199322


So the question is, where should I edit the stuff that is on usb_desc.c so that it is effective?
 
Last edited:
Note renaming a usb_desc.c to usb_desc_d.c

Makes 0 differences to the build. You could call it foo.c and it would still build. The build system will compile every .c .cpp file within that directory.

If you actually setup your system to do verbose builds, you would see that it built usb_desc_d.c and as such satisfied any external references needed.
 
I do not understand. That is very strange, but seems to be the case. I removed the file form the directory, and still compiles just fine.

But after restarting Arduino environment does not compile any more, so clearly it notice now that the file is missing.


But this is also pretty frustrating, do I always need to restart the Arduino environment after changing the usb_desc.c?

and also the problem maybe was that I did a usb_desc_copy.c before editing the usb_desc.c and left it on the same directory, so maybe it used that instead of the usb_desc.c... This does not feel smart. Really, is it not caring about the file names at all, but good to know, I could not have figured that out without help, thanks Kurt.

verbose build, what is that and why is it not default.

And hey, it worked. actually what I edited before provided the wanted result, only 10 buttons shown

Screenshot 2021-05-26 at 17.24.46.jpg

Code:
#if JOYSTICK_SIZE == 12
static uint8_t joystick_report_desc[] = {

        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x04,                     // Usage (Joystick)
        0xA1, 0x01,                     // Collection (Application)

        0x05, 0x09,                     //   Usage Page (Button)
        0x19, 0x01,                     //   Usage Minimum (Button #1)
        0x29, 0x0A,                     //   Usage Maximum (Button #32) was 0x20, reduced to 10 buttons 0x0A
        0x15, 0x00,                     //   Logical Minimum (0)
        0x25, 0x01,                     //   Logical Maximum (1)
        0x75, 0x01,                     //   Report Size (1)
        0x95, 0x0A,                     //   Report Count (32) was 0x20, reduced to 10 buttons 0x0A



        0x81, 0x02,                     //   Input (variable,absolute)

        0x75, 0x01,                     //   Report Size (1)
        0x95, 0x16,                     //   Report Count (22) to fill the original 32 buttons
        0x81, 0x01,                     //   Constant


        0x15, 0x00,                     //   Logical Minimum (0)
        0x25, 0x07,                     //   Logical Maximum (7)
        0x35, 0x00,                     //   Physical Minimum (0)
        0x46, 0x3B, 0x01,               //   Physical Maximum (315)
        0x75, 0x04,                     //   Report Size (4)
        0x95, 0x01,                     //   Report Count (1)
        0x65, 0x14,                     //   Unit (20)

        0x05, 0x01,                     //   Usage Page (Generic Desktop)
        0x09, 0x39,                     //   Usage (Hat switch)
        0x81, 0x42,                     //   Input (variable,absolute,null_state)

        0x05, 0x01,                     //   Usage Page (Generic Desktop)
        0x09, 0x01,                     //   Usage (Pointer)
        0xA1, 0x00,                     //   Collection ()
        0x15, 0x00,                     //     Logical Minimum (0)
        0x26, 0xFF, 0x03,               //     Logical Maximum (1023)
        0x75, 0x0A,                     //     Report Size (10)
        0x95, 0x04,                     //     Report Count (4)
        0x09, 0x30,                     //     Usage (X)
        0x09, 0x31,                     //     Usage (Y)
        0x09, 0x32,                     //     Usage (Z)
        0x09, 0x35,                     //     Usage (Rz)
        0x81, 0x02,                     //     Input (variable,absolute)
        0xC0,                           //   End Collection
        0x15, 0x00,                     //   Logical Minimum (0)
        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
        0x75, 0x0A,                     //   Report Size (10)
        0x95, 0x02,                     //   Report Count (2)
        0x09, 0x36,                     //   Usage (Slider)
        0x09, 0x36,                     //   Usage (Slider)
        0x81, 0x02,                     //   Input (variable,absolute)
        0xC0                            // End Collection


};
 
Last edited:
Hi all, I'm building a Sim control panel.
Just wondering if the post36 attached files are still valid? I don't seem to be able to download them? Maybe it's just me being a noob on this forum.

Edit: I was viewing the forum in mobile mode! All downloads fine when viewing in full site. Lol
 
Last edited:
Hi all, I'm building a Sim control panel.
Just wondering if the post36 attached files are still valid? I don't seem to be able to download them? Maybe it's just me being a noob on this forum.

Edit: I was viewing the forum in mobile mode! All downloads fine when viewing in full site. Lol

Sorry I have not played much with the many axis... But I would not recommend using the files in the posting #36. They are going on 8 years old, and the the files that these would replace have had some significant changes in that time frame.

It has been awhile since I built using the setup, as to mainly test for other things.

But I think the better route is to edit the current source files.

Most of this I believe is now controlled by simply editing the usb_desc.h (either the teensy3 or the teensy4 version)

Then depending on which USB type you wish to use like "Keyboard + Mouse + Joystick" that gives you: #elif defined(USB_HID)

You will find a line like:
Code:
  #define JOYSTICK_SIZE         12	//  12 = normal, 64 = extreme joystick
Which in my file is about line 289

Change it to 64 and I believe this drive the other files that were in the zip file to use the extreme joystick.
 
Cool Kurt

Sorry I have not played much with the many axis... But I would not recommend using the files in the posting #36. They are going on 8 years old, and the the files that these would replace have had some significant changes in that time frame.

It has been awhile since I built using the setup, as to mainly test for other things.

But I think the better route is to edit the current source files.

Most of this I believe is now controlled by simply editing the usb_desc.h (either the teensy3 or the teensy4 version)

Then depending on which USB type you wish to use like "Keyboard + Mouse + Joystick" that gives you: #elif defined(USB_HID)

You will find a line like:
Code:
  #define JOYSTICK_SIZE         12	//  12 = normal, 64 = extreme joystick
Which in my file is about line 289

Change it to 64 and I believe this drive the other files that were in the zip file to use the extreme joystick.

Thanks so much for your help Kurt. I'll leave the files well alone and just amend the usb_desc.h file as advised. Nice catch man:cool:
 
Before swapping to a 3.0, 3.1 or buying a new teensy....

Is there anyway I can run the following modded snippet on a teensy++2.0? I have three on hand. It compiles but I have no serial output and windows 10 shows an unresponsive joystick.


Code:
// Encoders are just being used to pulse joystick buttons.

// Encoder MODE buttos will be set to loop over three mode per encoder, to change which joystick buttons are pulsed.
// The Mode funtionality hasn't been added yet.

const int numButtons = 10;  // Standard Buttons

const int numEncoderIncrementButtons = 8; // Standard Buttons used as encoder up/down

const int numEncoder_MODE_Buttons = 4; // Standard Buttons used as encoder up/down

  const int EncIncrBtnPinNum_Min = numButtons + 1;
  const int EncIncrBtnPinNum_Max = numButtons + numEncoderIncrementButtons;
  
    const int EncModeBtnPinNum_Min = EncIncrBtnPinNum_Max + 1;
    const int EncModeBtnPinNum_Max = EncIncrBtnPinNum_Max + numEncoder_MODE_Buttons;

void setup() {
  
  // you can print to the serial monitor while the joystick is active!
  Serial.begin(9600);
  
  Joystick.useManualSend(true);
  
  // assign button pin numbers and pinModes
  
  for (int i=0; i<numButtons; i++) {
    pinMode(i, INPUT_PULLUP);
  }

  
  // assign EncoderButton pin numbers and pinModes
  
  for (int i=EncIncrBtnPinNum_Min; i<EncIncrBtnPinNum_Max; i++) {
    pinMode(i, INPUT_PULLUP);
  }

  // assign EncoderModeButton pin numbers and pinModes
  
  for (int i=EncModeBtnPinNum_Min; i<EncModeBtnPinNum_Max; i++) {
    pinMode(i, INPUT_PULLUP);
  }
}

byte allButtons[numButtons];
byte prevButtons[numButtons];

byte allEncoderIncrementButtons[numEncoderIncrementButtons];
byte prevEncoderIncrementButtons[numEncoderIncrementButtons];

byte allEncoder_MODE_Buttons[numEncoder_MODE_Buttons];
byte prevEncoder_MODE_Buttons[numEncoder_MODE_Buttons];


void loop() {
  
// read pins and use them for the buttons

  for (int i=0; i<numButtons; i++) {
    if (digitalRead(i)) {
      // when a pin reads high, the button is not pressed
      // the pullup resistor creates the "on" signal
      allButtons[i] = 0;
    } else {
      // when a pin reads low, the button is connecting to ground.
      allButtons[i] = 1;
    }
    Joystick.button(i + 1, allButtons[i]);
  }
  
  for (int i=EncIncrBtnPinNum_Min; i<EncIncrBtnPinNum_Max; i++) {
    if (digitalRead(i)) {
      // when a pin reads high, the button is not pressed
      // the pullup resistor creates the "on" signal
      allEncoderIncrementButtons[i] = 0;
    } else {
      // when a pin reads low, the button is connecting to ground.
      allEncoderIncrementButtons[i] = 1;
    }
    Joystick.button(i + 1, allEncoderIncrementButtons[i]);
  }

  for (int i=EncModeBtnPinNum_Min; i<EncModeBtnPinNum_Max; i++) {
    if (digitalRead(i)) {
      // when a pin reads high, the button is not pressed
      // the pullup resistor creates the "on" signal
      allEncoder_MODE_Buttons[i] = 0;
    } else {
      // when a pin reads low, the button is connecting to ground.
      allEncoder_MODE_Buttons[i] = 1;
    }
    Joystick.button(i + 1, allEncoder_MODE_Buttons[i]);
  }
  
  
  // Because setup configured the Joystick manual send,
  // the computer does not see any of the changes yet.
  // This send_now() transmits everything all at once.
  Joystick.send_now();
  
  // check to see if any button changed since last time
  boolean anyBtnChange = false;
  for (int i=0; i<numButtons; i++) {
    if (allButtons[i] != prevButtons[i]) anyBtnChange = true;
    prevButtons[i] = allButtons[i];
  }
  
  // if any Button Changed, print them to the serial monitor
  if (anyBtnChange) {
    Serial.print("Buttons: ");
    for (int i=0; i<numButtons; i++) {
      Serial.print(allButtons[i], DEC);
    }
    Serial.println();
  }
  
  // check to see if any Encoder Increment Button Changed since last time
  boolean anyEncBtnChange = false;
  for (int i=EncIncrBtnPinNum_Min; i<EncIncrBtnPinNum_Max; i++) {
    if (allEncoderIncrementButtons[i] != prevEncoderIncrementButtons[i]) anyEncBtnChange = true;
    prevEncoderIncrementButtons[i] = allEncoderIncrementButtons[i];
  }
  
  // if any button changed, print them to the serial monitor
  if (anyEncBtnChange) {
    Serial.print("Encoder Increment Buttons: ");
    for (int i=EncIncrBtnPinNum_Min; i<EncIncrBtnPinNum_Max; i++) {
      Serial.print(allEncoderIncrementButtons[i], DEC);
    }
    Serial.println();
  }

    // check to see if any Encoder Increment button changed since last time
  boolean anyEncoder_MODE_BtnChange = false;
  for (int i=EncModeBtnPinNum_Min; i<EncModeBtnPinNum_Max; i++) {
    if (allEncoder_MODE_Buttons[i] != prevEncoder_MODE_Buttons[i]) anyEncoder_MODE_BtnChange = true;
    prevEncoder_MODE_Buttons[i] = allEncoder_MODE_Buttons[i];
  }
  
  // if any Encoder MODE Button changed, print them to the serial monitor
  if (anyEncoder_MODE_BtnChange) {
    Serial.print("Encoder MODE Buttons: ");
    for (int i=EncModeBtnPinNum_Min; i<EncModeBtnPinNum_Max; i++) {
      Serial.print(allEncoder_MODE_Buttons[i], DEC);
    }
    Serial.println();
  }
  
  
  // A brief delay, so this runs "only" 200 times per second
  delay(5);
}
 
Wrong thread?

Hi all,

I've got the code above working now. I just needed to change # I= xyx to i1, i2, i3 etc...

Serial is printing perfectly too, and all buttons are reading correct pin, joystick and Val's.

Thanks for your support. Kurt.

I still need to add separate modes to each encoder by pressing their respective push knobs and I also want any button held low for longer than X to give an additional joystick press on the rising edge so I can use toggle switches.I'd love any suggestions on how to implement this using the sketch above please.

I want to add some LEDs to indicate which mode is active per encoder.

Question is, should I start a new tread since the portion of the many axis joystick I'm using is now working perfectly? Or is it still appropriate here since with mode selection any button or encoder or even axis can be multi purposed making a relatively small control box have enormous number of controls?

The basic concept of the original sketch is fantastic to be able to just specify how many of each input you want like that. Thanks so much.

Scott
 
Hi,
this is my first post here, but I have been reading this forum for several months now.
I am building (for years) an F-16 cockpit with all switches and knobs "functional", that is,
they are all wired. As simulation software I plan to use BMS.

To make wiring not too messy, I use (for the Left Console) 3 Arduino Nano on a self-developed
"carrier board" using MCP23017 to expand to 64 digital inputs and 64 digital outputs.
I chose the MCP23017 for I2C connection, because I needed the SPI connection for the
RF24L01 transceiver in the 2.4 GHz band. These Arduino Nanos are called "slaves", and they
connect via the RF24L01s to the Teensy 4.1. The T4.1 also has an RF24L01. Works really perfect.

Using the standard Teensy 4.1 Joystick configuration, I get 32 DX buttons and 6 sliders,
but for my application that is not enough. I tested this configuration and the 32 DX buttons
all work fine and the axes/sliders also work as expected.

So, I changed JOYSTICK_SIZE to 64 (to be sure all 4 entries) in usb_desc.h
Using Pointy's great JoystickTest.exe (version 0.9.2), I see 128 DX buttons, and they all work!!
Also, I *see* 6 axes and 17 sliders, but none of them work, they remain 0.
I did not change the setting of all potmeters, and did not switch power. Only edited usb_desc.h
and compiled the T4.1 code again. And now I am stuck ...

I thought that the JOYSTICK_SIZE to 64 in usb_dec.h was all it takes, but maybe I am wrong.
Is there more to be changed to get the sliders working ?

BTW, not switching power, only changing usb-desc.h to the original (JOYSTICK_SIZE 12) and
compiling the T4.1 sketch shows working sliders again ...

Thanks for reading!
 

Attachments

  • joy-12.jpg
    joy-12.jpg
    38.2 KB · Views: 156
  • joy-64.jpg
    joy-64.jpg
    90.3 KB · Views: 143
Thanks Experi1.

I have read the entire thread at least twice!
It seems that I was a bit fatigued at the end, so I missed that.

By reading this thread a few times, I have the feeling I will succeed changing the .c files.
When I have it working, I will post the changed files here (if that's OK by the admin).
 
Well, I had a look at usb_dec.h / usb_desc.c / usb_joystick.h / usb_joystick.c
and got the impression that #if JOYSTICK_SIZE == 64 statements solve all issues.

And post #209 states that it is sufficient to change the JOYSTICK_SIZE definition from 12 to 64 in usb_desc.h to do the trick.
(Change it to 64 and I believe this drive the other files that were in the zip file to use the extreme joystick.)
That is also what I would expect <whistle>.

I only noticed that for JOYSTICK_SIZE == 12 the axes and sliders are 10 bits, and for JOYSTICK_SIZE == 64 the axes / sliders are 16 bits. I don't care about that, for me 10 bits is enough, but if it is 16 bits it would not matter to the application.
I assume that the values are stuffed at the correct place in the packet using the defined number of bits ...

So, I am still stuck :confused:
 
Hopefully Kurt or Pointy can help. It's beyond me sorry. When I made the changes Kurt suggested everything just worked for my application. I really just made use of all the extra buttons by way of second and third functions from each button and added extra (millis) long-press rising edge joystick button press so toggles fire a joystick press on both falling and rising edges. I don't know enough to figure out what's going on with your sliders. Best of luck.
 
Thanks for your reply.
To my consolation is that Pointy has shown that it works, so there is a solution (although it is still beyond the horizon for me).

Just some more info.
After I edited usb_desc.h (and changed all 4 JOYSTICK_SIZE definitions to 64), I terminated the Arduino IDE, and then started the IDE again, and subsequently compiled my program again. I am sure that the changes are "accepted", because Pointy's JoystickTest.exe (v0.9.2) shows all the sliders.
And I selected "RawInput" in JoystickTest.exe. All DX buttons work, but all sliders and axes just remain 0.
Hoping Kurt or Pointy will read this.

I am using Arduino 1.8.13 and Teensyduino 1.55.
 
Did you ever get the sliders working?

I have arrived to the party a little late.

I mad ethe modifications in usb_desc to JOYSTICK_SIZE 64.

I have been able to compile and upload to my Teensy 3.1 board. Buttons work, XYZ axis both work, but the sliders do not appear to do anything. Not sure what I am missing, or if maybe I somehow damaged by board during soldering.

pin 14 is A0, 15 is A1, etc. so A0 thru A5 (14 thru 19) are working. Pin 20 should be the input for the first slider, right? Maybe i am doing something wrong with the input; do sliders work just like potentiometers?



Thanks for your reply.
To my consolation is that Pointy has shown that it works, so there is a solution (although it is still beyond the horizon for me).

Just some more info.
After I edited usb_desc.h (and changed all 4 JOYSTICK_SIZE definitions to 64), I terminated the Arduino IDE, and then started the IDE again, and subsequently compiled my program again. I am sure that the changes are "accepted", because Pointy's JoystickTest.exe (v0.9.2) shows all the sliders.
And I selected "RawInput" in JoystickTest.exe. All DX buttons work, but all sliders and axes just remain 0.
Hoping Kurt or Pointy will read this.

I am using Arduino 1.8.13 and Teensyduino 1.55.
 
I had a little time to play today. I found that DirectX is reporting the slider values associated with the last two sliders... I changed the sample code to reference the last two against the Analog 0 and 1 inputs and now have all the analog axis reporting under the Windows gamepad setup properties screen.

Next up is to figure out the buttons /digital inputs. There appeared to be some overlap with the analog inputs.


Nope, not yet ...
Hope to get back to the issue next week. At the moment I am down with the flu :(
 
Hello together,

I am currently running into the same problem. The code for many-axis-joystick compiles and should work under Windows.
The 18 axis (sliders) are also recognized by the application I intend to use the device I am currently building (quadrant
with nine sliders and puttys). But still only 7 axis are usable/working.

However, when I was searching for reasons why the Teensy's Joystick-code is not working it was suggested/implied that the
code itself maybe implemented correctly and the reason why the axis are not recognized is on the side of Windows to find.
Simply, Windows does not stick to their own API. Maybe the case of "extreme" number of axis (>8) was never considered by
the developers. I do not have the site I read about it (it is three weeks since then) and at this point it does not matter.

What I wanted to ask are several questions about a possible workaround. Since apparently we are stuck with 6 till 8 axis,
my idea is to run three instances of a joystick, where each instance reads from respective pins (PIN0 till 5, PIN6 till 11
and PIN12 till 17) on one micro-controller. In this case Windows would recognize 3 devices/joysticks in its system.
This is maybe not an elegant solution but still better than nothing.

So,

1. Is it possible with current implementation to run several instances of a Joystick on one micro-controller?
(Unfortunately, my suspicion is that it won't be possible. I could speculate why but it doesn't matter here.)
In case it is possible can someone provide an example of a working code?

2. In case no, can the source files be easily adjusted so it would be possible? And with easily I mean adding simple code
lines without being forced to study/reverse engineer the code. Although I find this topic interesting I unfortunately do not
have the time to study it in details.

3. I found a project (video, github), which theoretically (the code compiled without any issues) allows to run several instances of a joystick on one micro-controller. However, this project works only for Arduino Pro Micro or Leonardo (which I do not posses, thus, I can't test my idea).
Can this Library be easily adjusted so it can be used with Teensy (The compiler is refusing to compile if Teensy is used)?

Best regards,
Non Vi Sed Arte
 
Ok, I've updated this code and merged it into the official core library.

https://github.com/PaulStoffregen/cores/commit/f5f05e9adee9ab9eca1ca83897e4114bf6e767fa

If you want to play with it now, you can get the updated files from github and put them into your copy of Arduino. Starting with 1.36-beta2 they will always be there by the installer.

To actually use this (after you have the new files installed), edit usb_desc.h. Change JOYSTICK_SIZE from 12 to 64. Remember, there's 4 copies for the different USB Types which use joystick. Edit the one you need, or all of them if unsure. I've set everything else to automatically adapt.

As always, on Windows your old USB device detection might be cached in the Windows Registry. You might need to increase the BCD version number or change the product ID or do other stuff to get Windows to re-detect the device.

Hi is this still the most recent library?
 
Back
Top