teensy axis also sending numerical digits to windows.

skypickle

Active member
I have a Teensy 4.1 with 5 buttons mapped and 6 axes. It also runs a small display which I can change with two buttons so I can have a readout of my controls for various aircraft. They work as intended except two axes seem to do more than I ask for them.
The potentiometers mapped to the X and Y axis correctly move the little cross in the windows usb controllers control panel. All axes and buttons were calibrated. However, if I open up a text editor and spin the X axis dial all the way left I get a '4' in text editor. Spinning right gives a '6'. These numbers only appear at the extreme of excusion. The Y axisa dial gives '8' and '2'. Somehow these axes are being interpreted as the num pad?
Here is the code :

Code:
/* button box has 6 potentiometers,5 buttons and one display
 *  two of the buttons function to page the display forward and back
 *  TOOLS->USB TYPE-> serial/keyboard/mouse/joystick
*/
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_HX8357.h"
#include <Bounce.h>

#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8 
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
//array of potentiometer pins
char potPins[] = {
A0,A1,A2,A3,A4,A10
}; 
byte potCount = 6;  
int inputPot = 0;  
int screenNumber = 1; 

// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button0 = Bounce(19, 10);
Bounce button1 = Bounce(20, 10);  // 10 = 10 ms debounce time
Bounce button2 = Bounce(21, 10);  // which is appropriate for
Bounce button3 = Bounce(22, 10);  // most mechanical pushbuttons
Bounce button4 = Bounce(23, 10);

void setup() {
  //Serial.begin(9600);
  //while (!Serial) { delay(10); }
  tft.begin();
  Apache();
  for (int thisPot = 0; thisPot < potCount; thisPot++) 
     pinMode(potPins[thisPot], INPUT);

  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, INPUT_PULLUP);
  pinMode(22, INPUT_PULLUP);
  pinMode(23, INPUT_PULLUP);

  // Please be aware the X, Y, Z, Zr and Slider axes will have default
  // settings, if you only use the buttons.  This can give the appearance
  // of the buttons interfering with the axes, if your PC software shows
  // different default assumed values before your first button press.
  //  More details here:
  //  https://forum.pjrc.com/threads/29320-Teensy-3-1-Button-problems?p=80275#post80275
  //these next lines center the axes
  // same as Windows default
   Joystick.Z(512);
   Joystick.X(512);
   Joystick.Y(512);
   Joystick.Zrotate(512);
   Joystick.sliderLeft(512);
   Joystick.sliderRight(512);
   //Joystick.slider(512);
}

void loop() {
  for (int thisPot = 0; thisPot < potCount; thisPot++) {
    inputPot = analogRead(potPins[thisPot]);
    switch (thisPot) {
     case 0:
      Joystick.Z(inputPot);
     break;
     case 1:
      Joystick.X(inputPot);
     break;
     case 2:
      Joystick.Y(inputPot);
     break;
     case 3:
      Joystick.Zrotate(inputPot);
     break;
     case 4:
      Joystick.sliderLeft(inputPot);
     break;
     case 5:
      Joystick.sliderRight(inputPot);
     break;
     default: 
     break;
    }//end switch
   }//end for
   
  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button0.update();
  button1.update();
  button2.update();
  button3.update();
  button4.update();

  // Check each button for "falling" edge.
  // Update the Joystick buttons only upon changes.
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
  if (button0.fallingEdge()) {
    Joystick.button(1, 1);
  }
  if (button1.fallingEdge()) {
    Joystick.button(2, 1);
  }
  if (button2.fallingEdge()) {
    Joystick.button(3, 1);
  }
  if (button3.fallingEdge()) {
    changeScreen(-1);
  }
  if (button4.fallingEdge()) {
    changeScreen(1);
  }

  // Check each button for "rising" edge
  // Update the Joystick buttons only upon changes.
  // rising = low (pressed - button connects pin to ground)
  //          to high (not pressed - voltage from pullup resistor)
  if (button0.risingEdge()) {
    Joystick.button(1, 0);
  }
  if (button1.risingEdge()) {
    Joystick.button(2, 0);
  }
  if (button2.risingEdge()) {
    Joystick.button(3, 0);
  }
}//end main loop

void changeScreen(int var)  {
  screenNumber = screenNumber + var;
  if (screenNumber < 0) {
    screenNumber = 5;
  }
  if (screenNumber > 5) {
    screenNumber = 0;
  }
 //   Serial.println("entering changeScreen function");
 // Serial.print("screenNumber is ");
  //Serial.print(screenNumber);
    switch (screenNumber) {
     case 0:
      Hog();
      break;
     case 1:
      Apache();
      break;
     case 2:
      CPG();
     break;
     case 3:
      Huey();
      break;
     case 4:
      BlackHawk();
      break;
     case 5:
      F5E();
      break;
  }//end switch
}//end changeScreen

void Hog()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("A10-C ");
  tft.println("");
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("  1   2   3\n");
  tft.println("Lights                Vols\n");
  tft.println("AUX                    AIM\n");
  tft.println("CONSOLE                ILS\n");
  tft.println("ENGINE                 TCN\n");
  tft.println("FLT                     FM\n");
  tft.println("FLOOD                  UHF\n");
  tft.println("FORM                   VHF\n");
  tft.println("--------------------------\n");
  tft.println(" COLL     POS        SIG  \n");
  tft.println("ON/OFF  FLSH/STDY  BRT/DIM\n");
  tft.println("");
  tft.println("          OFF\n");
}

void Apache()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("AH64\n");
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("  1    2    3\n");
  tft.println();
  tft.println(" L  VID            R  VID\n");
  tft.println(" L  BRT            R  BRT\n");
  tft.println(" PRI               FLOOD \n");
  tft.println(" STBY              SIG    \n");
  tft.println(" FORM              ACTION\n");
  tft.println(" CMWS LT          MSTR VOL\n");
  tft.println("--------------------------\n");
  tft.println(" COLL       EXT     FIRE  \n");
  tft.println(" WHT        BRT      LT ");
  tft.println(" RED        DIM      RT\n");
  tft.println(" OFF        OFF     TST\n");
  tft.println("                   FLSHLT ");
}

void CPG()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("CPG\n");
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("  AZ  ACM  FRZ");
  tft.println("   \n");
  tft.println(" L  VID            R  VID\n");
  tft.println(" L  BRT            R  BRT\n");
  tft.println(" PRI               FLOOD \n");
  tft.println("                   SIG    \n");
  tft.println(" LEVEL             EUFD\n");
  tft.println(" GAIN             MSTR VOL\n");
  tft.println("--------------------------\n");
  tft.println("          TEDAC\n");
  tft.println(" RF        SYM     BRT  \n");
  tft.println("                    ");
  tft.println(" EL        AZ      CON\n");
  tft.println();

}

void Huey()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("UH1 ");
  tft.println();
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("    1   2   3\n");
  tft.println("Lights                Vols\n");
  tft.println("CONSOLE               INT \n");
  tft.println("PEDSTL                UHF \n");
  tft.println("SECNDRY               VHF \n");
  tft.println("PILOT            MRKR BCN \n");
  tft.println("COPLT                 ADF \n");
  tft.println("--------------------------\n");
  tft.println("COLL      NAV            ");
  tft.println(" ON       FLSH             ");
  tft.println("     ");
  tft.println("DOME      STDY");
  tft.println("OFF  \n");
  tft.println("                    FLSHLT\n");
  tft.println("WHT/GRN  BRT/DIM   WHT/RED \n");

}

void BlackHawk()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("BlackHawk ");
  tft.println();
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("    1   2   3\n");
  tft.println("PLT INST LTS    Eng 1 FUEL\n");
  tft.println("CP INST  LTS    Eng 2 FUEL\n");
  tft.println("CONSOLE UP       \n");
  tft.println("CONSOLE DN        \n");
  tft.println("GLARE SHLD      SWITCH LTS\n");
  tft.println("FORM LTS     OTHR INST LTS\n6");
  tft.println("--------------------------\n");
  tft.println("COLL   DOME            ");
  tft.println("DAY    BLUE    AIR ENG");
  tft.println("NIGHT  WHITE   AIR APU");
  tft.println("     ");
  tft.println("OFF            APU GEN ON");
  tft.println("               APU GEN OFF\n");
  
}

void F5E()  {
//unsigned long testText() {
  tft.fillScreen(HX8357_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(HX8357_RED);    
  tft.setTextSize(3);
  tft.println("F5E");
  tft.println();
  tft.setTextColor(HX8357_GREEN);
  tft.setTextSize(2);
  tft.println("    1   2   3\n");
  tft.println();
  tft.println("           LIGHTS\n");
  tft.println("     ");
  tft.println("RDR BRIGHT            NAV \n");
  tft.println("RDR CRSR             FORM \n");
  tft.println("RDR PERSIST      FLT INST \n");
  tft.println("VIDEO            ENG INST \n");
  tft.println("                  CONSOLE \n");
  tft.println("                    FLOOD \n");
  tft.println("--------------------------");
 // tft.println("COLL       NAV            \n");
  //tft.println(" ON       FLSH             ");
  //tft.println("     ");
  //tft.println("DOME");
  //tft.println("OFF       STDY\n");
  //tft.println("                    FLSHLT\n");
  //tft.println("WHT/GRN  BRT/DIM   WHT/RED \n");

}

Is this a known windows bug?
 
Might help to know things like what version of Arduino are you using, and likewise Teensyduino.

Likewise what version of windows you are running.

Also maybe might debug it a bit in your code, where you set the X, and Y values, maybe print out the values are at the extremes.
 
Might help to know things like what version of Arduino are you using, and likewise Teensyduino.

Likewise what version of windows you are running.

Also maybe might debug it a bit in your code, where you set the X, and Y values, maybe print out the values are at the extremes.

Arduino 1.8.19
Teensyduino 1.56

The values output on the serial monitor are the same for all axes
when turned to the left they bounce around 0,1,2
when turned all the way to the right 1021,1022,1023

I can discern no difference in the distribution of these output values for any of the axes.
 
Again no idea who might be outputting something. Will try to setup something like it.

Right now I don't have a Teensy Joystick setup... Although maybe can emulate with a remote control I was playing with years ago...
screenshot.jpg

This currently has a T3.2 in it, the display appears to be busted and has has collected a lot of dust. I never used it as a USB Joystick class instead it talked using XBees to an XBee on Robot, but probably would not be hard try to emulate your 4 axis... Buttons a little more complicated as these are setup using button matrix code. So probably 10 IOs to handle all of them...

Will try to do a partial setup hopefully tomorrow.

Edit: but one thing I wanted to mention, was with these joysticks, I would have code to calibrate up/down left/right such that you get the full range of value.
BUT if you went at a diagonal the values would exceed the straight left and right or up and down and if your code did not handle that, especially if you were doing mappings then you could get strange results.

Don't know what your axis are so maybe not an issue.
 
I did some more testing. The potentiometer has an excursion of 300 degrees. Roughly from5 oclock turning counterclockwise to 7 oclock. The digits will appear in any text editor when the dial moves counterclockwise from 9 oclock to 8 oclock or clockwise from 3 oclock to 4 oclock.

IT does not happen in safe mode.

I tracked done the issue to user error.

I am running an app in the background called 'JoytoKey' It allows me to send a keystroke when an axis reaches a specific limit. Unfortunately, the Teensy usurped the axis ID of another controller as 'Axis 1' and the motions were being mapped to those digits. Please excuse my mistake and I only post this analysis here as an example of how different pieces of software can interfere with hardware mappings.
 
Back
Top