Teensy lc : Analog joystick not calibrated & do not work on retropie

Status
Not open for further replies.
Hello,

I'm looking for some help as I can't resolve two issues with my Teensy LC card running Retropie and Raspberry PI 3A +. From time to time I make handheld consoles and bartop for fun (https://www.elektronicaone.fr/) to take on new relevant challenges, but here I am blocking šŸ˜Š.

Problem nĀ° 1: The analog joystick:
I am unable to center or calibrate my analog joystick. When I let the joystick in the home position (without touching it), it always positions itself to the right, visible in the Windows utility joy.cpl. I tried all the codes I found on the Internet and in the examples (Sketches) from the Arduino IDE, i modified the X & Y position values of the joystick in the code, I replaced the joystick, the Teensy LC card but no change.

JOY.jpg

Result: In Retropie, in the Emulationstation menu, no problem. But when I enter in a game and to the Retroarch menu, the right direction is automatically maintained as if I were moving the joystick to the right. I also changed the UDEV driver to SLD2, reinstall Retropie, launched Retropie update, Raspberry pi firmware and still no resolution

Problem nĀ°2: Teensy LC controller does not work in Retropie 4.7.1 games
My Teensy LC Joystick and Buttons work fine in Emulationstation but not in games.
it works a few rare times (which allowed me to see that the joystick went to automatically go to the right.)
What I did to try to fix this but still issue.
-force the Teensy lc controller in Player 1 in Retroarch
-Reset the controller in Emulationstation to remove all controllers and remap the keys.
-Change the Gamepad drivers in Retroarch: UDEV, SDL2 ...
-Install the Raspbian OS then Retropie

In reading my topic , I realize that the problem may be definitely between the computer screen and the keyboard (this is a French expression :D)
Thank you in advance for your help.

Here is one of the Teensly Gamepad code used

Code:
#include <EEPROM.h>

#define  STICK_X 0
#define STICK_Y 1

int Xstick;
int Ystick;
int deadzone;
int upperBound;
int lowerBound;
bool isInCalibration;
bool isCalibrationButtonPressed;
unsigned long calibrationButtonLastPressedTimeStamp;
unsigned long calibrationButtonPressedDuration;
unsigned long calibrationWriteLastTimeStamp;

#include <Bounce.h>

// 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(0, 10);
Bounce button1 = Bounce(1, 10);  // 10 = 10 ms debounce time
Bounce button2 = Bounce(2, 10);  // which is appropriate for
Bounce button3 = Bounce(3, 10);  // most mechanical pushbuttons
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10);
Bounce button6 = Bounce(6, 10);
Bounce button7 = Bounce(7, 10);
Bounce button8 = Bounce(8, 10);
Bounce button9 = Bounce(9, 10);
Bounce button10 = Bounce(10, 10);
Bounce button11 = Bounce(11, 10);
Bounce button12 = Bounce(12, 10);

void setup() {
  Joystick.useManualSend(true);
  setDeadzone();
  setBounds();
  isInCalibration = false;
  isCalibrationButtonPressed = false;
  calibrationButtonLastPressedTimeStamp = 0;
  calibrationButtonPressedDuration = 0;
  calibrationWriteLastTimeStamp = 0;

  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(0, INPUT_PULLUP);

   // 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(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);  // Teensy++ LED, may need 1k resistor 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);
}

void loop() {
  Xstick = analogRead(STICK_X);
  Ystick = analogRead(STICK_Y);
  isCalibrationButtonPressed = !digitalRead(0);
  
  if (!isInCalibration) {
    checkCalibrationTrigger();
    
    if ((Xstick > 512 && Xstick <= upperBound) || (Xstick < 512 && Xstick >= lowerBound)) {
      Xstick = 512;
    }
  
    if ((Ystick > 512 && Ystick <= upperBound) || (Ystick < 512 && Ystick >= lowerBound)) {
      Ystick = 512;
    }

    Joystick.X(Xstick);
    Joystick.Y(Ystick);
    Joystick.button(1, isCalibrationButtonPressed);
    Joystick.send_now();
  }
  else {
    persistBounds();
  }
   button0.update();
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.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()) {
    Joystick.button(4, 1);
  }
  if (button4.fallingEdge()) {
    Joystick.button(5, 1);
  }
  if (button5.fallingEdge()) {
    Joystick.button(6, 1);
  }
  if (button6.fallingEdge()) {
    Joystick.button(7, 1);
  }
  if (button7.fallingEdge()) {
    Joystick.button(8, 1);
  }
  if (button8.fallingEdge()) {
    Joystick.button(9, 1);
  }
  if (button9.fallingEdge()) {
    Joystick.button(10, 1);
  }
  if (button10.fallingEdge()) {
    Joystick.button(11, 1);
  }
  if (button11.fallingEdge()) {
    Joystick.button(12, 1);
  }
  if (button12.fallingEdge()) {
    Joystick.button(13, 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);
  }
  if (button3.risingEdge()) {
    Joystick.button(4, 0);
  }
  if (button4.risingEdge()) {
    Joystick.button(5, 0);
  }
  if (button5.risingEdge()) {
    Joystick.button(6, 0);
  }
  if (button6.risingEdge()) {
    Joystick.button(7, 0);
  }
  if (button7.risingEdge()) {
    Joystick.button(8, 0);
  }
  if (button8.risingEdge()) {
    Joystick.button(9, 0);
  }
  if (button9.risingEdge()) {
    Joystick.button(10, 0);
  }
  if (button10.risingEdge()) {
    Joystick.button(11, 0);
  }
  if (button11.risingEdge()) {
    Joystick.button(12, 0);
  }
  if (button12.risingEdge()) {
    Joystick.button(13, 0);
  }
}

void setDeadzone() {
  deadzone = 0;
  deadzone = EEPROM.read(0) << 8 | EEPROM.read(1);
}

void setBounds() {
  deadzone = deadzone - 512;
  upperBound = 512 + (deadzone + 10);
  lowerBound = 512 - (deadzone + 10);
}

void checkCalibrationTrigger() {
  unsigned long now = millis();
  
  if (isCalibrationButtonPressed) {
    if (calibrationButtonLastPressedTimeStamp == 0) {
      calibrationButtonLastPressedTimeStamp = now;
    }
    
    calibrationButtonPressedDuration = calibrationButtonPressedDuration + (now - calibrationButtonLastPressedTimeStamp);
    calibrationButtonLastPressedTimeStamp = now;
  }
  else {
    calibrationButtonLastPressedTimeStamp = 0;
    calibrationButtonPressedDuration = 0;
  }

  if (calibrationButtonPressedDuration >= 5000) {
    isInCalibration = true;
    digitalWrite(13, HIGH);
  }
}

void persistBounds() {
  unsigned long now = millis();
  
  if (((calibrationWriteLastTimeStamp + now) - calibrationWriteLastTimeStamp) >= 1000) {
    int highValue = Xstick;
    
    if (Ystick > Xstick) {
      highValue = Ystick;
    }

    EEPROM.write(0, highByte(highValue));
    EEPROM.write(1, lowByte(highValue));

    calibrationWriteLastTimeStamp = now;
  }
}
 
the problem may be definitely between the computer screen and the keyboard
Between screen and keyboard there is usually little room; did you mean between chair and keyboard?

On topic now: for debugging it's best to strip down the code to the bare minimum, test it and then expand with additional functionality.
I would not be surprised if the problem you see is related to to the calibration routines.
Did you try the joystick examples that came with Teensyduino? [File > Examples > Teensy > USB_Joystick > Basic etc.]

Paul
 
Allright. Did you try another joystick? What kind of joystick are you actually using?

Paul
 
Just did a quick test with a joystick and Teensy LC:

JoyLC.jpg

Ran the basic example and executed joy.cpl on Win10:

Joy.png

All looks good.
Paul
 
I own this joystick, and tried another one :
joystick.JPG

i just tried basic code but same, look at the cross , (it has micro movements)
Basic.JPG
 
It looks like you connected the 5V of the joystick to the Vin pin of the Teensy LC.
Please connect it to the 3V3 pin of the Teensy LC.
The Teensy LC pins are only 3V3 rated...hope the board and/or analog pins are not killed...

Paul
 
ok Paul, i am going to try.
However, I measured 5V in output from "Vin" Pin at top right. I can't use the "Vin" Pin as Output Voltage ?

thank you for your advice
 
Great !!! to put 3.3 v instead 5V on the Joystick solved my first issue on Joy.cpl.
I will solder and try on Retropie later and will let you know.

Thank you very much :)
 
You're welcome. Happy to hear the LC is still OK.
About the Vin pin: when you connect the Teensy LC with a USB cable to a PC, the output voltage on that Vin pin will be the USB 5V. You can pull ~350mA max.
If you don't power the Teensy LC over USB, you use the Vin pin as a DC power input [3.7 to 5.5V].

Paul
 
Status
Not open for further replies.
Back
Top