Teensy 4.1 is being used as a joystick controller and a display.
3 buttons and 6 axes are monitored and sent as joystick controls
2 buttons are used to advance screen forward and backward- the screen simply displays labels for the axes and buttons. I have hardcoded different screens for different aircraft I fly so I dont have to remember which switch is mapped to what control.
code below
When I look at the USB controller settings the teensy is labeled as
'Serial/Keyboard/Mouse/Joystick' and the status is OK
But the properties control panel shows the 'point of view hat' pushed forward.
As you can see in the code, three buttons are detected as joystick buttons and pressing these properly lights up the correct red lights on the USB game controller panel.
How can the point of view hat be 'stuck' in the forward position?
How can I troubleshoot this?
Interestingly, in the post here:
https://forum.pjrc.com/threads/29320-Teensy-3-1-Button-problems?p=80275#post80275
They talk about windows 'making up' values for axes that are not initialized. Setting the axes to 512 corrects this. But in that SAME post there is a picture of the hat being activated in the forward position though the problem is not addressed.
The reason this is a problem for me is that I have a tactical flight analysis program (TACVIEW) that continually scrolls left unless I disconnect the teensy. I am guessing that the forward activated hat is being interpreted by the program causing it to scroll left.
3 buttons and 6 axes are monitored and sent as joystick controls
2 buttons are used to advance screen forward and backward- the screen simply displays labels for the axes and buttons. I have hardcoded different screens for different aircraft I fly so I dont have to remember which switch is mapped to what control.
code below
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 = 3;
}
if (screenNumber > 3) {
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:
Huey();
break;
case 3:
F5E();
}//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 1 2 3");
tft.println();
tft.setTextColor(HX8357_GREEN);
tft.setTextSize(2);
tft.println("Lights Dials 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("\n");
tft.println(" OFF\n");
tft.println("\n");
}
void Apache() {
//unsigned long testText() {
tft.fillScreen(HX8357_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(HX8357_RED);
tft.setTextSize(3);
tft.println("AH64 1 2 3");
tft.println();
tft.setTextColor(HX8357_GREEN);
tft.setTextSize(2);
tft.println(" Lights MFDs \n");
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");
tft.println(" FLSHLT ");
}
void Huey() {
//unsigned long testText() {
tft.fillScreen(HX8357_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(HX8357_RED);
tft.setTextSize(3);
tft.println("UH1 1 2 3");
tft.println();
tft.setTextColor(HX8357_GREEN);
tft.setTextSize(2);
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("--------------------------");
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");
}
void F5E() {
//unsigned long testText() {
tft.fillScreen(HX8357_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(HX8357_RED);
tft.setTextSize(3);
tft.println("F5E 1 2 3");
tft.println();
tft.setTextColor(HX8357_GREEN);
tft.setTextSize(2);
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("--------------------------");
}
When I look at the USB controller settings the teensy is labeled as
'Serial/Keyboard/Mouse/Joystick' and the status is OK
But the properties control panel shows the 'point of view hat' pushed forward.
As you can see in the code, three buttons are detected as joystick buttons and pressing these properly lights up the correct red lights on the USB game controller panel.
How can the point of view hat be 'stuck' in the forward position?
How can I troubleshoot this?
Interestingly, in the post here:
https://forum.pjrc.com/threads/29320-Teensy-3-1-Button-problems?p=80275#post80275
They talk about windows 'making up' values for axes that are not initialized. Setting the axes to 512 corrects this. But in that SAME post there is a picture of the hat being activated in the forward position though the problem is not addressed.
The reason this is a problem for me is that I have a tactical flight analysis program (TACVIEW) that continually scrolls left unless I disconnect the teensy. I am guessing that the forward activated hat is being interpreted by the program causing it to scroll left.