Teensy 4.1 - Can't get over 32 buttons to recognize

foxmi

New member
Good evening everyone,

First time here and very new to all this. I've been working on a flight sim button box project for a while and just got into coding it a few weeks ago. As stated in the title, for the life of me, I can't seem to get more than 32 buttons to register. For context, I have 45 switch inputs and 6 potentiometers. Testing each switch by itself, they work fine. When combining everything, I lose buttons 33 - 45. I have used multiple USB Types and most recently tried out the Flight Sim Controls + Joystick type as I saw it supports 128 inputs with 8 axes. I'm kind of at a dead end. I did make sure the JOYSTICK_SIZE in usb_desc.h was changed to 64 to accommodate more inputs. I didn't see any changes needed in usb_desc.c. I will post my sketch below - again, very new to this and know the code could be significantly shorter using arrays, but starting out, I wanted something easy for me to read and learn from. Obviously there is some FastLED stuff in there too for my backlighting of this button box.

Any help or direction would be greatly appreciated! I'm sure I'm missing something stupidly simple but I just haven't found it. Thanks again!

Code:
#include <FastLED.h>
// LED Setup
#define LED_PIN 23
#define NUM_LEDS 214
CRGB leds[NUM_LEDS];
// LED Color Control
CRGB colors[] = {CRGB::Green, CRGB::Red, CRGB::Blue, CRGB::Yellow, CRGB::White};
int currentColorIndex = 0;
unsigned long lastLtTestPressTime = 0;
int ltTestPressCount = 0;
bool lastLtTestState = false;
void setup() {
    Joystick.begin();
    FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
    FastLED.clear();
    FastLED.show();
    // Setup L GEN and R GEN switches (2-position switches)
    pinMode(2, INPUT_PULLUP); // L GEN switch (up position)
    pinMode(3, INPUT_PULLUP); // R GEN switch (up position)
   
    // Setup BATT switch (3-position switch)
    pinMode(0, INPUT_PULLUP); // BATT switch (up position)
    pinMode(1, INPUT_PULLUP); // BATT switch (down position)
   
    // Setup MODE switch (3-position switch)
    pinMode(4, INPUT_PULLUP); // MODE switch (up position)
    pinMode(5, INPUT_PULLUP); // MODE switch (down position)
   
    // Setup CABIN PRESS switch (3-position switch)
    pinMode(6, INPUT_PULLUP); // CABIN PRESS switch (up position)
    pinMode(7, INPUT_PULLUP); // CABIN PRESS switch (down position)
   
    // Setup PITOT switch (2-position switch)
    pinMode(8, INPUT_PULLUP); // PITOT switch (up position)
   
    // Setup ENG HEAT switch (3-position switch)
    pinMode(9, INPUT_PULLUP); // ENG HEAT switch (up position)
    pinMode(10, INPUT_PULLUP); // ENG HEAT switch (down position)
   
    // Setup LT TEST switch (1-position switch)
    pinMode(26, INPUT_PULLUP); // LT TEST switch (up position)
   
    // Setup DAY/NITE MODE switch (3-position switch)
    pinMode(27, INPUT_PULLUP); // DAY/NITE MODE switch (up position)
    pinMode(28, INPUT_PULLUP); // DAY/NITE MODE switch (down position)
   
    // Setup FLIR switch (3-position switch)
    pinMode(29, INPUT_PULLUP); // FLIR switch (up position)
    pinMode(30, INPUT_PULLUP); // FLIR switch (down position)
   
    // Setup LTD/R switch (2-position switch)
    pinMode(33, INPUT_PULLUP); // LTD/R switch (up position)
   
    // Setup LST/NFLR switch (2-position switch)
    pinMode(31, INPUT_PULLUP); // LST/NFLR switch (up position)
   
    // Setup BLEED AIR switch (4-position rotary)
    pinMode(11, INPUT_PULLUP);
    pinMode(12, INPUT_PULLUP);
    pinMode(24, INPUT_PULLUP);
    pinMode(25, INPUT_PULLUP);
   
    // Setup RADAR switch (4-position rotary)
    pinMode(13, INPUT_PULLUP);
    pinMode(14, INPUT_PULLUP);
    pinMode(15, INPUT_PULLUP);
    pinMode(16, INPUT_PULLUP);
   
    // Setup GPS switch (8-position rotary)
    pinMode(34, INPUT_PULLUP);
    pinMode(35, INPUT_PULLUP);
    pinMode(36, INPUT_PULLUP);
    pinMode(37, INPUT_PULLUP);
    pinMode(38, INPUT_PULLUP);
    pinMode(39, INPUT_PULLUP);
    pinMode(40, INPUT_PULLUP);
    pinMode(41, INPUT_PULLUP);
}
void loop() {
    bool switchLGenUpState = !digitalRead(2);
    bool switchRGenUpState = !digitalRead(3);
    bool switchBattUpState = !digitalRead(0);
    bool switchBattDownState = !digitalRead(1);
    bool switchBattCenterState = !switchBattUpState && !switchBattDownState;
    bool switchModeUpState = !digitalRead(4);
    bool switchModeDownState = !digitalRead(5);
    bool switchModeCenterState = !switchModeUpState && !switchModeDownState;
    bool switchCabinPressUpState = !digitalRead(6);
    bool switchCabinPressDownState = !digitalRead(7);
    bool switchCabinPressCenterState = !switchCabinPressUpState && !switchCabinPressDownState;
    bool switchPitotUpState = !digitalRead(8);
    bool switchPitotDownState = !switchPitotUpState;
    bool switchEngHeatUpState = !digitalRead(9);
    bool switchEngHeatDownState = !digitalRead(10);
    bool switchEngHeatCenterState = !switchEngHeatUpState && !switchEngHeatDownState;
    bool switchLtTestState = !digitalRead(26);
    bool switchDayNiteUpState = !digitalRead(27);
    bool switchDayNiteDownState = !digitalRead(28);
    bool switchDayNiteCenterState = !switchDayNiteUpState && !switchDayNiteDownState;
    bool switchFlirUpState = !digitalRead(29);
    bool switchFlirDownState = !digitalRead(30);
    bool switchFlirCenterState = !switchFlirUpState && !switchFlirDownState;
    bool switchLtdrUpState = !digitalRead(33);
    bool switchLtdrDownState = !switchLtdrUpState;
    bool switchLstNflrUpState = !digitalRead(31);
    bool switchLstNflrDownState = !switchLstNflrUpState;
   
    int bleedAirPosition = (!digitalRead(11) * 1) + (!digitalRead(12) * 2) + (!digitalRead(24) * 3) + (!digitalRead(25) * 4);
    int radarPosition = (!digitalRead(13) * 1) + (!digitalRead(14) * 2) + (!digitalRead(15) * 3) + (!digitalRead(16) * 4);
    int gpsPosition = (!digitalRead(34) * 1) + (!digitalRead(35) * 2) + (!digitalRead(36) * 3) + (!digitalRead(37) * 4) + (!digitalRead(38) * 5) + (!digitalRead(39) * 6) + (!digitalRead(40) * 7) + (!digitalRead(41) * 8);
   
    Joystick.button(0, switchLGenUpState);
    Joystick.button(1, !switchLGenUpState);
    Joystick.button(2, switchRGenUpState);
    Joystick.button(3, !switchRGenUpState);
    Joystick.button(4, switchBattUpState);
    Joystick.button(5, switchBattDownState);
    Joystick.button(6, switchBattCenterState);
    Joystick.button(7, switchModeUpState);
    Joystick.button(8, switchModeDownState);
    Joystick.button(9, switchModeCenterState);
    Joystick.button(10, switchCabinPressUpState);
    Joystick.button(11, switchCabinPressDownState);
    Joystick.button(12, switchCabinPressCenterState);
    Joystick.button(13, switchPitotUpState);
    Joystick.button(14, switchPitotDownState);
    Joystick.button(15, switchEngHeatUpState);
    Joystick.button(16, switchEngHeatDownState);
    Joystick.button(17, switchEngHeatCenterState);
    Joystick.button(18, switchLtTestState);
    Joystick.button(19, switchDayNiteUpState);
    Joystick.button(20, switchDayNiteDownState);
    Joystick.button(21, switchDayNiteCenterState);
    Joystick.button(22, switchFlirUpState);
    Joystick.button(23, switchFlirDownState);
    Joystick.button(24, switchFlirCenterState);
    Joystick.button(25, switchLtdrUpState);
    Joystick.button(26, switchLtdrDownState);
    Joystick.button(27, switchLstNflrUpState);
    Joystick.button(28, switchLstNflrDownState);
   
    Joystick.button(29, bleedAirPosition == 1);
    Joystick.button(30, bleedAirPosition == 2);
    Joystick.button(31, bleedAirPosition == 3);
    Joystick.button(32, bleedAirPosition == 4);
   
    Joystick.button(33, radarPosition == 1);
    Joystick.button(34, radarPosition == 2);
    Joystick.button(35, radarPosition == 3);
    Joystick.button(36, radarPosition == 4);
    Joystick.button(37, gpsPosition == 1);
    Joystick.button(38, gpsPosition == 2);
    Joystick.button(39, gpsPosition == 3);
    Joystick.button(40, gpsPosition == 4);
    Joystick.button(41, gpsPosition == 5);
    Joystick.button(42, gpsPosition == 6);
    Joystick.button(43, gpsPosition == 7);
    Joystick.button(44, gpsPosition == 8);
   
        // Potentiometer readings
    Joystick.X(1023 - analogRead(17)); // TEMP Pot
    Joystick.Y(1023 - analogRead(18)); // CONSOLES Pot (Also LED Brightness Control)
    Joystick.Z(1023 - analogRead(19)); // INST PNL Pot
    Joystick.Xrotate(1023 - analogRead(20)); // FLOOD Pot
    Joystick.Yrotate(1023 - analogRead(21)); // WARN/CAUT Pot
    Joystick.Zrotate(1023 - analogRead(22)); // CHART Pot
    unsigned long currentTime = millis();
   
    // LT TEST switch color cycling logic with debounce
    if (switchLtTestState && !lastLtTestState) { // Detects only new presses
        if (currentTime - lastLtTestPressTime < 1000) {
            ltTestPressCount++;
        } else {
            ltTestPressCount = 1;
        }
        lastLtTestPressTime = currentTime;
    }
    lastLtTestState = switchLtTestState;
   
    if (ltTestPressCount >= 3) {
        currentColorIndex = (currentColorIndex + 1) % (sizeof(colors) / sizeof(colors[0]));
        ltTestPressCount = 0; // Reset counter
    }
   
    // LED Brightness and Color Control
    int brightness = map(analogRead(18), 0, 1023, 255, 0);
    FastLED.setBrightness(brightness);
    fill_solid(leds, NUM_LEDS, colors[currentColorIndex]);
    FastLED.show();
   
    Joystick.send_now();
    delay(5);
}
 
Check <this> older thread which may have some info that may be helpful to you.

Mark J Culross
KD5RXT
Thanks, Mark! I’ve actually been across that post before and that was something that I had tried previously but it didn’t seem to make a difference. I still currently have that enabled in the usb descriptors.
 
I did make sure the JOYSTICK_SIZE in usb_desc.h was changed to 64 to accommodate more inputs.

In usb_desc.h used on Teensy 4, the define JOYSTICK_SIZE appears in 4 places. Did you edit the correct ones? Or all of 4 of them?

As a quick sanity test, try editing them one at a time into something wrong, like a word rather than a number. You should find 2 of them result in compile errors. It should be 2 because one is used when USB connects at 480 Mbit speed and the other is used for 12 Mbit speed.

Many people (myself included) have wasted a lot of time wondering why our edits seem to have no effect, only to later discover the wrong file was edited. Adding an obvious error and seeing it when you click Verify in Arduino IDE is a good way to quickly check you really are editing the place that really does matter.
 
What are you using on the PC to see how many buttons the joystick presents?
Have used a few different methods but currently using Virpl’s Joystick Tester software. Works with any device up to 128 buttons. I have also tested in the sim to make sure.

In usb_desc.h used on Teensy 4, the define JOYSTICK_SIZE appears in 4 places. Did you edit the correct ones? Or all of 4 of them?

As a quick sanity test, try editing them one at a time into something wrong, like a word rather than a number. You should find 2 of them result in compile errors. It should be 2 because one is used when USB connects at 480 Mbit speed and the other is used for 12 Mbit speed.

Many people (myself included) have wasted a lot of time wondering why our edits seem to have no effect, only to later discover the wrong file was edited. Adding an obvious error and seeing it when you click Verify in Arduino IDE is a good way to quickly check you really are editing the place that really does matter.
Interesting. I’m not at my computer right now to look but I know I did 1 of them for sure with no compilation error. And I do remember seeing multiple spots where it appeared. I’ll check this today to make sure and report back.

EDIT: I went back into the usb_desc.h - I messed with all 4 instances of JOYSTICK_SIZE and found where it would cause errors when compiling. Changed the one that caused the error and it seems to have done the trick. Funny enough that's what I had edited already. I decided to reinstall Teensyduino just to get a fresh start before editing as well. There's a possibility I had mistakenly messed with something else inadvertently. I don't know know what that would be but regardless, it's working now and I appreciate all the help! I will post what I changed in usb_desc.h below for anyone else that runs across this in the future (probably me lol)

Code:
#elif defined(USB_FLIGHTSIM_JOYSTICK)
  #define VENDOR_ID        0x16C0
  #define PRODUCT_ID        0x0488
  #define BCD_DEVICE        0x0211
  #define MANUFACTURER_NAME    {'T','e','e','n','s','y','d','u','i','n','o'}
  #define MANUFACTURER_NAME_LEN    11
  #define PRODUCT_NAME        {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'}
  #define PRODUCT_NAME_LEN    26
  #define EP0_SIZE        64
  #define NUM_ENDPOINTS         4
  #define NUM_INTERFACE        3
  #define FLIGHTSIM_INTERFACE    0    // Flight Sim Control
  #define FLIGHTSIM_TX_ENDPOINT    3
  #define FLIGHTSIM_TX_SIZE    64
  #define FLIGHTSIM_TX_INTERVAL    1
  #define FLIGHTSIM_RX_ENDPOINT    3
  #define FLIGHTSIM_RX_SIZE    64
  #define FLIGHTSIM_RX_INTERVAL    1
  #define SEREMU_INTERFACE      1    // Serial emulation
  #define SEREMU_TX_ENDPOINT    2
  #define SEREMU_TX_SIZE        64
  #define SEREMU_TX_INTERVAL    1
  #define SEREMU_RX_ENDPOINT    2
  #define SEREMU_RX_SIZE        32
  #define SEREMU_RX_INTERVAL    2
  #define JOYSTICK_INTERFACE    2    // Joystick
  #define JOYSTICK_ENDPOINT     4
  #define JOYSTICK_SIZE         64    //  12 = normal, 64 = extreme joystick
  #define JOYSTICK_INTERVAL     1
  #define ENDPOINT2_CONFIG    ENDPOINT_RECEIVE_INTERRUPT + ENDPOINT_TRANSMIT_INTERRUPT
  #define ENDPOINT3_CONFIG    ENDPOINT_RECEIVE_BULK + ENDPOINT_TRANSMIT_BULK
  #define ENDPOINT4_CONFIG    ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT
 
Last edited:
Back
Top