Need Help on My Code

Hi All ~ I've been following various sites/forums/guides and adding my own input to make my Logitech G29 Shifter display it's gear on a home built 7-segment display. Tested and confirmed the LED segments work on their own. I put the code I made into an Arduino Leonardo and I got it all to work EXCEPT that I can't get gears 1, 3, and 5 to light up their corresponding parts of the 7-segment display. The 2, 4, 6, and Reverse all light up their parts on the 7-segment display. I'm using Windows 11 Home on an Acer laptop so I opened the game controller section of Windows and confirmed that the computer is reading all of the gears (1 to 6 and reverse) so I know it's not an issue with the actual Logitech G29 Shifter. I'm BRAND new to Arduino and I'm trying to teach myself but this is going to be a gift for my son's birthday next week and I'm just stuck. Can ya'll take a look at the code and let me know. Thank you in advance! Best, Alan, RN

//Logitech Driving Force Shifter USB Adapter
//By Armandoiglesias 2018
//Based on Jason Duncan functionreturnfunction Project
//Video tutorial https://www.youtube.com/watch?v=dLpWEu8kCec
//Use Arduino Leonardo
//Install Joystick Library
//Attribution-NonCommercial-NoDerivatives 4.0 International

#include <Joystick.h>

// Create the Joystick
Joystick_ Joystick;

// H-shifter mode analog axis thresholds
#define HS_XAXIS_12 600   //default 390//400
#define HS_XAXIS_56 500   //default 680//500
#define HS_YAXIS_135 800  //default 775//800
#define HS_YAXIS_246 150  //default 425//300

// Sequential shifter mode analog axis thresholds
//#define SS_UPSHIFT_BEGIN   670
//#define SS_UPSHIFT_END     600
//#define SS_DOWNSHIFT_BEGIN 430
//#define SS_DOWNSHIFT_END   500

// Handbrake mode analog axis limits
//#define HB_MAXIMUM         530
//#define HB_MINIMUM         400
//#define HB_RANGE           (HB_MAXIMUM-HB_MINIMUM)

// Digital inputs definitions
#define DI_REVERSE 1
#define DI_MODE 3
#define DI_RED_CENTERRIGHT 4
#define DI_RED_CENTERLEFT 5
#define DI_RED_RIGHT 6
#define DI_RED_LEFT 7
#define DI_BLACK_TOP 8
#define DI_BLACK_RIGHT 9
#define DI_BLACK_LEFT 10
#define DI_BLACK_BOTTOM 11
#define DI_DPAD_RIGHT 12
#define DI_DPAD_LEFT 13
#define DI_DPAD_BOTTOM 14
#define DI_DPAD_TOP 15

// Shifter state
#define DOWN_SHIFT -1
#define NO_SHIFT 0
#define UP_SHIFT 1

// Shifter mode
#define SHIFTER_MODE 0
#define HANDBRAKE_MODE 1

// LED blink counter
int led = 0;

// Shifter state
int shift = NO_SHIFT;

// Handbrake mode
int mode = SHIFTER_MODE;

int b[16];

int gear = 0;  // Default value is neutral

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;

//AJM Code
int segA = 3;
int segB = 5;
int segC = 6;
int segD = 10;
int segE = 11;
int segF = 12;
int segG = 9;
int _gear_ = 0;


void firstgear() {
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
}

void secondgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, LOW);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, LOW);
}

void thirdgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, LOW);
}

void fourthgear() {
  digitalWrite(segA, HIGH);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
}

void fifthgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segB, HIGH);
  digitalWrite(segE, HIGH);
}

void sixthgear() {
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
}

void reverse() {
  digitalWrite(segE, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segF, HIGH);
}

void neutral() {
  if (_gear_ == 0 || gear == 0) {  //Neutral
    digitalWrite(segE, LOW);
    digitalWrite(segG, LOW);
    digitalWrite(segC, LOW);
  }
}

void setup() {
  // G29 shifter analog inputs configuration
  pinMode(A2, INPUT_PULLUP);  // was 0  // X axis
  pinMode(A4, INPUT_PULLUP);  // was 2 // Y axis

  pinMode(2, INPUT);

  //AJM Code
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  for (int i = 0; i < 16; i++) b[i] = 0;
  b[DI_MODE] = 0;

  // Initialize Joystick Library
  Joystick.begin();
}

// Last state of the button
int lastButtonState = 0;

void loop() {

  int x = analogRead(2);  //was 0                 // X axis
  int y = analogRead(4);  //was 2                 // Y axis

  int _isreverse = digitalRead(2);
  int _gear_ = 0;

  if (_isreverse == 1) {

    _gear_ = 8;
    b[DI_REVERSE] = 1;
    reverse();

  } else {


    if (b[DI_MODE] == 0)  // H-shifter mode?
    {
      if (x < HS_XAXIS_12)  // Shifter on the left?
      {
        if (y > HS_YAXIS_135) _gear_ = 1;  // 1st gear
        firstgear();
        if (y < HS_YAXIS_246) _gear_ = 2;  // 2nd gear
        secondgear();
      } else if (x > HS_XAXIS_56)  // Shifter on the right?
      {
        if (y > HS_YAXIS_135) _gear_ = 5;  // 5th gear
        fifthgear();
        if (y < HS_YAXIS_246) _gear_ = 6;  // 6th gear
        sixthgear();

      } else  // Shifter is in the middle
      {
        if (y > HS_YAXIS_135) _gear_ = 3;  // 3rd gear
        thirdgear();
        if (y < HS_YAXIS_246) _gear_ = 4;  // 4th gear
        fourthgear();
      }
    }
  }


  if (gear != 6) {
    b[DI_REVERSE] = 0;  // Reverse gear is allowed only on 6th gear position
                        //reverse();
  }
  if (_gear_ != gear) {
    gear = _gear_;
    desactivar();
    Joystick.setButton(gear - 1, HIGH);
    neutral();
  }
  delay(100);
}

void desactivar() {
  // Depress virtual button for current gear
  for (int i = 0; i <= 10; i++) Joystick.setButton(i, LOW);
}

First things first. Thanks for posting the code using code tags. Did you get a chance to read all of this?
https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/681308
You mentioned you're brand new to Arduino so what's detailed in that link is the culture here. There are gurus galore in this forum (I am not one) who have a tacit expectation it seems, that you've done this homework, shall we say, so you can give us ALL the technical details pertaining to your project which helps us help you.
Thanks!

1 Like

thank you! I did, yes.

What happens if you comment out 1, 3 and 5 like:

/*
void fifthgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segB, HIGH);
  digitalWrite(segE, HIGH);
}
*/

then make duplicates of them just below the ones you commented out (to preserve what you had)
and played with the digitalWrite values?
If you just copy in say, the values from

void sixthGear(){}

to

void fifthGear(){}

does anything show up then? If not, then I'd say your stick values are off.

1 Like

Did you read through the comments on the YouTube page? It seems some folks had to change the raw threshold values some, one individual in particular said:

The default sketch has one bug for me. Middle position of the joystick is reading incorrectly, so buttons 5 and 6 triggers instead of 3 and 4. To fix it, you need to change the value of HS_XAXIS_56 to 600 (line 18). AM-STUDIO sketch version Dec 8, 2018. MHeironimus/ArduinoJoystickLibrary version 2.0.5. Device: Logitech driving force shifter for G29 and G920

So it seems you may have to dial in the values some.

Tip: when you go to do this, take the best working sketch you have and make a copy of it, save it as somethingTestVersion or whatever and play with the values in that.
Tip Tip: change only one value at at time, test, repeat.

1 Like

I swapped out the first gear for second gear, third for fourth, and fifth for sixth to see if that’s the issue, it’s not.
I’ve played with the raw values for hours, no luck.

Is there any way to figure out what exactly the

int x = analogRead(2);
int y = analogRead(4);

int x and int y values are? I feel like if I could see what those two numbers actually are, I can fix the rest of the raw values accordingly.

I see you're not using Serial. Use it as a debugging tool, as countless others do.
In setup()
Serial.begin(115200); //remember to set serial Monitor to the same value

and

Serial.print(x);
Serial.print("  ");
Serial.println(y);

Should suffice.

Okay so I have the gears working now - thank you camsysca and hallowed31. BUT I cannot seem to get neutral to work such that I want to display neutral unless it's in a gear (1-6 & reverse). I tried using return, changing the flow, modifying if else statements, etc. Here's my current code:

//Logitech Driving Force Shifter USB Adapter
//By Armandoiglesias 2018
//Based on Jason Duncan functionreturnfunction Project
//Video tutorial https://www.youtube.com/watch?v=dLpWEu8kCec
//Use Arduino Leonardo
//Install Joystick Library
//Attribution-NonCommercial-NoDerivatives 4.0 International

#include <Joystick.h>

// Create the Joystick
Joystick_ Joystick;

// H-shifter mode analog axis thresholds
//#define HS_XAXIS_12 550
//#define HS_XAXIS_56 545
//#define HS_YAXIS_135 320
//#define HS_YAXIS_246 330

#define X_AXIS_LEFT 900
#define Y_AXIS_RIGHT 700

#define Y_AXIS_1ST_GEAR 290
#define X_AXIS_1ST_GEAR 900

#define Y_AXIS_2ND_GEAR 290
#define X_AXIS_2ND_GEAR 900

#define Y_AXIS_3RD_GEARTOP 515
#define Y_AXIS_3RD_GEARBOTTOM 500
#define X_AXIS_3RD_GEARTOP 890
#define X_AXIS_3RD_GEARBOTTOM 880

#define Y_AXIS_4TH_GEARTOP 520
#define Y_AXIS_4TH_GEARBOTTOM 505
#define X_AXIS_4TH_GEARTOP 140
#define X_AXIS_4TH_GEARBOTTOM 120

#define Y_AXIS_5TH_GEAR 700
#define X_AXIS_5TH_GEAR 800

#define Y_AXIS_6TH_GEAR 700
#define X_AXIS_6TH_GEAR 200

// Sequential shifter mode analog axis thresholds
//#define SS_UPSHIFT_BEGIN   670
//#define SS_UPSHIFT_END     600
//#define SS_DOWNSHIFT_BEGIN 430
//#define SS_DOWNSHIFT_END   500

// Digital inputs definitions
#define DI_REVERSE 1
#define DI_MODE 3
/*#define DI_RED_CENTERRIGHT 4
#define DI_RED_CENTERLEFT 5
#define DI_RED_RIGHT 6
#define DI_RED_LEFT 7
#define DI_BLACK_TOP 8
#define DI_BLACK_RIGHT 9
#define DI_BLACK_LEFT 10
#define DI_BLACK_BOTTOM 11
#define DI_DPAD_RIGHT 12
#define DI_DPAD_LEFT 13
#define DI_DPAD_BOTTOM 14
#define DI_DPAD_TOP 15
*/

// Shifter state
#define DOWN_SHIFT -1
#define NO_SHIFT 0
#define UP_SHIFT 1

// Shifter mode
#define SHIFTER_MODE 0
#define HANDBRAKE_MODE 1

// LED blink counter
int led = 0;

// Shifter state
int shift = NO_SHIFT;

// Handbrake mode
int mode = SHIFTER_MODE;

int b[16];

int gear = 0;  // Default value is neutral

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;

//AJM Code
int segA = 3;
int segB = 5;
int segC = 6;
int segD = 10;
int segE = 11;
int segF = 12;
int segG = 9;
int _gear_ = 0;

void firstgear() {
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segA, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}

void secondgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, LOW);
}

void thirdgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, LOW);
}

void fourthgear() {
  digitalWrite(segA, HIGH);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
}

void fifthgear() {
  digitalWrite(segA, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segB, HIGH);
  digitalWrite(segE, HIGH);
}

void sixthgear() {
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
}

void reverse() {
  digitalWrite(segE, LOW);
  digitalWrite(segG, LOW);
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segF, HIGH);
}

void neutral() {
   digitalWrite(segE, LOW);
   digitalWrite(segG, LOW);
   digitalWrite(segC, LOW);
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segF, HIGH);
}

void setup() {
  // G29 shifter analog inputs configuration
  pinMode(A2, INPUT_PULLUP);  // was 0  // X axis
  pinMode(A4, INPUT_PULLUP);  // was 2 // Y axis

  pinMode(2, INPUT);

  //AJM Code
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  for (int i = 0; i < 16; i++) b[i] = 0;
  b[DI_MODE] = 0;

  // Initialize Joystick Library
  Joystick.begin();
}

// Last state of the button
int lastButtonState = 0;

int A = 21;
int B = 22;
int C = 23;
int D = 24; 
int E = 25;
int F = 26;

void loop() {

  int x = analogRead(2);  //was 0                 // X axis
  int y = analogRead(4);  //was 2                 // Y axis

  int _isreverse = digitalRead(2);
  int _gear_ = 0;
  
  if (b[DI_MODE] == 0) {
       //if (x < X_AXIS_LEFT) 
       //{
        if (y > Y_AXIS_1ST_GEAR && x < X_AXIS_1ST_GEAR) 
          firstgear();
        if (y < Y_AXIS_2ND_GEAR && x < X_AXIS_2ND_GEAR) 
          secondgear();
       //}
       //if (y > Y_AXIS_RIGHT)
       //{
        if (y > Y_AXIS_5TH_GEAR && x > X_AXIS_5TH_GEAR) 
          fifthgear();
        if (y > Y_AXIS_6TH_GEAR && x < X_AXIS_6TH_GEAR) 
          sixthgear();
       //}
        if ((y > Y_AXIS_3RD_GEARBOTTOM) && (y < Y_AXIS_3RD_GEARTOP))
          {
            if ((x > X_AXIS_3RD_GEARBOTTOM) && (x < X_AXIS_3RD_GEARTOP)) 
            thirdgear();
          }
        if ((y > Y_AXIS_4TH_GEARBOTTOM) && (y < Y_AXIS_4TH_GEARTOP))
          {
            if ((x > X_AXIS_4TH_GEARBOTTOM) && (x < X_AXIS_4TH_GEARTOP)) 
            fourthgear();
          }
      }   
      
  if (_isreverse == 1) 
  {
    _gear_ = 8;
    b[DI_REVERSE] = 1;
    reverse();
  } 

  if (gear != 6) {
    b[DI_REVERSE] = 0;  // Reverse gear is allowed only on 6th gear position
    }

  if (_gear_ != gear) { // if (0 not equal to 0)
    gear = _gear_; //0=0
    desactivar(); 
    Joystick.setButton(gear - 1, HIGH);
    }

  //else if (_gear_ || gear || DI_MODE || DI_REVERSE != A, B, C, D, E, F); {
    //neutral();
    //}
  
    delay(1);
}

void desactivar() {
    // Depress virtual button for current gear
    for (int i = 0; i <= 10; i++) Joystick.setButton(i, LOW);
}
1 Like

Ok, working through this and something I noticed:

So it looks like you have the stick being input to the Arduino on A2 and A4 here to read the x and y axes, do I understand correctly?

However, you also have this:

which seem to conflict with your pin declarations in setup()

Question: did you want to analog read in on digital pins 2 and 4...and ALSO digital read in on digital pin 2? Because that's what you're doing.

Question (I don't know, I can't see your schematic or project wiring)...don't you want to be doing this instead?:

  int x = analogRead(A2);
  int y = analogRead(A4);

  int _isreverse = digitalRead(2);

You have the function for

void neutral() {
   digitalWrite(segE, LOW);
   digitalWrite(segG, LOW);
   digitalWrite(segC, LOW);
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segF, HIGH);
}

commented out at the end of void loop()


  //else if (_gear_ || gear || DI_MODE || DI_REVERSE != A, B, C, D, E, F); {
    //neutral();  
    //}
  
    delay(1);
}

Thank you SO much. I honestly didn't even know the A2 and A4 bit but now I do.
I commented out the neutral that you pointed out because I just kept trying random things to try to get neutral to work and that was a work in progress (but failed attempt). I also tried putting the below into the void loop too, but it didn't work either:

if (b[DI_MODE] != 0) {
neutral ();
}

It's so much trial and error from the builder end, sorry fix wasn't the fix.
Can you isolate each function somehow in separate sketches to at least see them work individually?

Just know that what seems "so simple" on an Arduino project, almost never is. What looks like it should take a morning to build and program might well take a week. What seems like a week's work, maybe takes a couple months. At least that's been my experience but makers gotta make so onward we grind. I only mention it so you know you're not alone in your frustration getting this awesome gift for your son to work as intended.

Keep at it.

PS: can you hand draw your actual schematic here, all the connections and voltage levels, everything involved - parts and part numbers, etc?
I'm only one helper here and FAR from one of the true gurus. Were I to estimate my own "batting average" here with suggestions for other to try, I'd like to think I'm batting maybe .150 but that may even be generous :joy: .

Might be that we're just looking in the wrong places altogether. If you could supply the details I mentioned, it might yet reveal the culprit to a more expert set of eyes.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.