Only one joystick axis is working

Hi again,

I am having a problem with my button box for sim racing and flight/space sim project :smiley: :

I tried to ask to gemini to create code, thats work, buuut, on my 5 pin axis stick, only one work, (x) the others are not working, tested my wiring, and serial monitor doesn't reveal any communication problems, so, maybe a code problem created by Gemini ? someone can tell to me what is wrong ?

#include <Joystick.h>

// Définition des broches pour les boutons momentanés
const int boutonPins[] = {2, 3, 4, 5, 6, 7};

// Définition des broches pour les axes du joystick principal
const int joystickXPin = A0;
const int joystickYPin = A1;

// Définition des broches pour les axes supplémentaires
const int autreAxe1Pin = A2;
const int autreAxe2Pin = A3;

// Définition des broches pour les interrupteurs toggle 1 position
const int togglePins[] = {8, 9};

// Définition des broches pour les interrupteurs momentanés On-Off-On
const int momentaryOnOffOnPins[][2] = {{10, 11}, {12, 13}};

// Création de l'objet Joystick
Joystick_ Joystick(
  JOYSTICK_DEFAULT_REPORT_ID,
  JOYSTICK_TYPE_GAMEPAD,
  12,     // Nombre de boutons (6 momentanés + 2 toggles + 2 * 2 pour les On-Off-On)
  4,      // Nombre d'axes (Joystick X, Joystick Y, Autre Axe 1, Autre Axe 2)
  false,  // Utiliser ou non les données de point de vue (hat switches)
  false,  // Utiliser ou non les boutons de direction (d-pad)
  false   // Auto-envoyer les mises à jour
);

void setup() {
  // Initialisation des boutons momentanés en entrée avec pull-up interne
  for (int pin : boutonPins) {
    pinMode(pin, INPUT_PULLUP);
  }

  // Initialisation des interrupteurs toggle en entrée avec pull-up interne
  for (int pin : togglePins) {
    pinMode(pin, INPUT_PULLUP);
  }

  // Initialisation des interrupteurs momentanés On-Off-On en entrée avec pull-up interne
  for (int i = 0; i < 2; ++i) {
    pinMode(momentaryOnOffOnPins[i][0], INPUT_PULLUP);
    pinMode(momentaryOnOffOnPins[i][1], INPUT_PULLUP);
  }

  // Initialisation de la librairie Joystick
  Joystick.begin();
}

void loop() {
  // Lecture et mise à jour des boutons momentanés
  for (int i = 0; i < 6; ++i) {
    Joystick.setButton(i + 1, digitalRead(boutonPins[i]) == LOW);
  }

  // Lecture et mise à jour des interrupteurs toggle
  for (int i = 0; i < 2; ++i) {
    Joystick.setButton(i + 7, digitalRead(togglePins[i]) == LOW);
  }

  // Lecture et mise à jour des interrupteurs momentanés On-Off-On
  for (int i = 0; i < 2; ++i) {
    Joystick.setButton(i + 9, digitalRead(momentaryOnOffOnPins[i][0]) == LOW); // Première position ON
    Joystick.setButton(i + 10, digitalRead(momentaryOnOffOnPins[i][1]) == LOW); // Seconde position ON
  }

  // Lecture des valeurs des axes analogiques et mise à jour du joystick
  Joystick.setXAxis(analogRead(joystickXPin));
  Joystick.setYAxis(analogRead(joystickYPin));
  Joystick.setZAxis(analogRead(autreAxe1Pin));   // Utilisation de l'axe Z pour l'autre axe 1
  Joystick.setRAxis(analogRead(autreAxe2Pin));   // Utilisation de l'axe R pour l'autre axe 2

  // Envoi de l'état du joystick
  Joystick.sendState();

  delay(5);
}

IF that thing in the upper center of the picture is your joystick, it has NO wires.

Not the answer to the joystick, but...

const int togglePins[] = {8, 9};

The line above uses pin 9.

const int momentaryOnOffOnPins[][2] = {{10, 11}, {12, 13}};

This (above) uses pins 10, 11, 12, 13.

  for (int i = 0; i < 2; ++i) {
    Joystick.setButton(i +  9, digitalRead(momentaryOnOffOnPins[i][0]) == LOW); // Première position ON
    Joystick.setButton(i + 10, digitalRead(momentaryOnOffOnPins[i][1]) == LOW); // Seconde position ON
  }

Line 1 above uses pins 9 and 10.
Line 2 above uses pins 10 and 11.

Could pins 9, 10 and 11 be causing confusion in the code?

Hi, @grumpindaface

Write some code that just reads the joystick and outputs it on the Arduino IDE serial monitor.
Forget your main code for the moment, check that you can receive and display signals from your controller.

What model Arduino controller are you using?

Do you have a DMM? Digital MultiMeter?

Tom.... :smiley: :+1: :coffee: :australia:

No, that is just my button box before wiring, I have an other joystick module for testing ^^

I have tested with HID project code, and that works fine, so, I don't uderstand why that is not working with joystick librairy. Maybe I'm gona use HID librairy

So, bait and switch question?

Axis are working fine with bench test monitoring tesqt and HID project librairy ..so... and my bord is an Arduino Micro Pro

Damn, I'm a total coding noob, sorry, what should I change in this case?^^

It seems your code is using the same pins (as noted) for multiple purposes. Am I missing something in your code?

This must not be normal, the axes are supposed to be between A0 and A3 and I have other switches (on OFF on momentary) etc.. on the other pins

Who wrote the code?

Google Gemini :sweat_smile:

Twins. : ( : (

Make a list, numbers 2 through 17 (or whatever you microcontroller DIO pin count is)
Beside each number, write the device name.
For example

2 - Button 1 - Ketchup
3 - Button 2 - Mustard
4 - Button 3 - Relish
5 - Button 4 - Steak sauce
.
.
nnn - fin

What does "axes" mean in French? Potentiometer?

So you might troubleshoot your buttonbox, here is my interpretation of your sketch that only produces a Serial Monitor output. Serial Monitor values will only update when a change occurs (button, joystick or potentiometer).

const int buttonPins[] = {2, 3, 4, 5, 6, 7};
const int buttonSize = sizeof(buttonPins) / sizeof(buttonPins[0]);
bool buttonRead[buttonSize], buttonReadOld[buttonSize];

const int togglePins[] = {8, 9};
const byte toggleSize = sizeof(togglePins) / sizeof(togglePins[0]);
bool toggleRead[toggleSize], toggleReadOld[toggleSize];

const int momentaryOnOffOnPins[] = {10, 11, 12, 13};
const byte momentaryOnOffOnSize = sizeof(momentaryOnOffOnPins) / sizeof(momentaryOnOffOnPins[0]);
bool momentaryOnOffOnPinsRead[momentaryOnOffOnSize], momentaryOnOffOnPinsReadOld[momentaryOnOffOnSize];

const int joystickXPin = A0;
const int joystickYPin = A1;
const int autreAxe1Pin = A2;
const int autreAxe2Pin = A3;
int joystickX, joystickY, potentiometer1, potentiometer2;
int joystickXold, joystickYold, potentiometer1old, potentiometer2old;

bool displayFlag = 0;

void setup() {
  Serial.begin(115200);

  for (int i = 0; i < buttonSize; ++i)
    pinMode(buttonPins[i], INPUT_PULLUP);

  for (int i = 0; i < toggleSize; ++i)
    pinMode(togglePins[i], INPUT_PULLUP);

  for (int i = 0; i < momentaryOnOffOnPins; ++i)
    pinMode(momentaryOnOffOnPins[i], INPUT_PULLUP);
}

void loop() {
  for (int i = 0; i < buttonSize; ++i) {
    buttonRead[i] = digitalRead(buttonPins[i]) == LOW;
    if (buttonRead[i] != buttonReadOld[i]) {
      buttonReadOld[i] = buttonRead[i];
      displayFlag = 1;
    }
  }

  for (int i = 0; i < toggleSize; ++i) {
    toggleRead[i] = digitalRead(togglePins[i]) == LOW;
    if (toggleRead[i] != toggleReadOld[i]) {
      toggleReadOld[i] = toggleRead[i];
      displayFlag = 1;
    }
  }

  for (int i = 0; i < momentaryOnOffOnSize; ++i) {
    momentaryOnOffOnPinsRead[i] = digitalRead(momentaryOnOffOnPins[i]) == LOW;
    if (momentaryOnOffOnPinsRead[i] != momentaryOnOffOnPinsReadOld[i]) {
      momentaryOnOffOnPinsReadOld[i] = momentaryOnOffOnPinsRead[i];
      displayFlag = 1;
    }
  }

  joystickX = analogRead(joystickXPin);
  joystickY = analogRead(joystickYPin);

  if (joystickX != joystickXold) {
    joystickXold = joystickX;
    displayFlag = 1;
  }

  if (joystickY != joystickYold) {
    joystickYold = joystickY;
    displayFlag = 1;
  }

  potentiometer1 = analogRead(autreAxe1Pin);
  potentiometer2 = analogRead(autreAxe2Pin);

  if (potentiometer1 != potentiometer1old) {
    potentiometer1old = potentiometer1;
    displayFlag = 1;
  }

  if (potentiometer2 != potentiometer2old) {
    potentiometer2old = potentiometer2;
    displayFlag = 1;
  }

  if (displayFlag) {
    displayFlag = 0;
    displayButtons();
  }
}

void displayButtons() {
  for (int i = 0; i < buttonSize; ++i)
    readButton("B", i, buttonRead[i]);

  for (int i = 0; i < toggleSize; ++i)
    readButton("T", i, toggleRead[i]);

  for (int i = 0; i < momentaryOnOffOnSize; ++i)
    readButton("M", i, momentaryOnOffOnPinsRead[i]);

  readPot("JX", joystickX);
  readPot("JY", joystickY);
  readPot("P1", potentiometer1);
  readPot("P2", potentiometer2);

  Serial.println();
}

void readButton(char name[], byte index, byte value) {
  Serial.print(" ");
  Serial.print(name);
  Serial.print(index);
  Serial.print(":");
  Serial.print(value);
}

void readPot(char name[], int value) {
  Serial.print(" ");
  Serial.print(name);
  zeropad(value);
}

void zeropad(int value) {
  if (value < 1000) Serial.print(" ");
  if (value < 100) Serial.print(" ");
  if (value < 10) Serial.print(" ");
  Serial.print(value);
}
diagram.json for wokwi
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": -4.8, "left": -0.5, "attrs": {} },
    { "type": "wokwi-dip-switch-8", "id": "sw1", "top": -80.1, "left": 39.9, "attrs": {} },
    {
      "type": "wokwi-slide-potentiometer",
      "id": "pot1",
      "top": -249.4,
      "left": 13.4,
      "rotate": 180,
      "attrs": { "travelLength": "20" }
    },
    {
      "type": "wokwi-slide-potentiometer",
      "id": "pot2",
      "top": -172.6,
      "left": 13.4,
      "rotate": 180,
      "attrs": { "travelLength": "20" }
    },
    {
      "type": "wokwi-analog-joystick",
      "id": "joystick1",
      "top": -67.8,
      "left": -109.8,
      "attrs": {}
    },
    { "type": "wokwi-dip-switch-8", "id": "sw2", "top": -80.1, "left": 1.5, "attrs": {} }
  ],
  "connections": [
    [ "joystick1:GND", "nano:GND.1", "black", [ "v19.2", "h201.6" ] ],
    [ "joystick1:HORZ", "nano:A0", "green", [ "v38.4", "h134.9" ] ],
    [ "joystick1:VERT", "nano:A1", "green", [ "v48", "h154.1" ] ],
    [ "joystick1:VCC", "nano:5V", "red", [ "v28.8", "h230.4" ] ],
    [ "nano:GND.2", "sw1:8b", "black", [ "v-19.2", "h38.4", "v-57.9" ] ],
    [ "sw1:8b", "sw1:7b", "green", [ "h0" ] ],
    [ "sw1:7b", "sw1:6b", "green", [ "v0" ] ],
    [ "sw1:6b", "sw1:5b", "green", [ "v0" ] ],
    [ "sw1:5b", "sw1:4b", "green", [ "v0" ] ],
    [ "sw1:4b", "sw1:3b", "green", [ "v0" ] ],
    [ "sw1:3b", "sw1:2b", "green", [ "v0" ] ],
    [ "sw1:2b", "sw1:1b", "green", [ "v0" ] ],
    [ "sw2:8b", "sw2:7b", "green", [ "h0" ] ],
    [ "sw2:7b", "sw2:6b", "green", [ "v0" ] ],
    [ "sw2:6b", "sw2:5b", "green", [ "v0" ] ],
    [ "sw2:5b", "sw2:4b", "green", [ "v0" ] ],
    [ "sw2:4b", "sw2:3b", "green", [ "v0" ] ],
    [ "sw2:3b", "sw2:2b", "green", [ "v0" ] ],
    [ "sw2:2b", "sw2:1b", "green", [ "v0" ] ],
    [ "nano:13", "sw2:1a", "green", [ "v0", "h-9.6" ] ],
    [ "nano:12", "sw2:2a", "green", [ "v0" ] ],
    [ "nano:11", "sw2:3a", "green", [ "v0" ] ],
    [ "nano:10", "sw2:4a", "green", [ "v0" ] ],
    [ "nano:5V", "pot2:VCC", "red", [ "v19.2", "h67.2", "v-182.4" ] ],
    [ "nano:5V", "pot1:VCC", "red", [ "v19.2", "h67.2", "v-259.2" ] ],
    [ "nano:A2", "pot2:SIG", "green", [ "v28.8", "h134.4", "v-211.2" ] ],
    [ "nano:A3", "pot1:SIG", "green", [ "v38.4", "h134.4", "v-278.4" ] ],
    [ "nano:GND.1", "pot2:GND", "black", [ "v9.6", "h-144", "v-172.8" ] ],
    [ "pot2:GND", "pot1:GND", "black", [ "v0", "h-14.2", "v-76.8" ] ],
    [ "nano:5", "sw1:5a", "green", [ "v0" ] ],
    [ "nano:4", "sw1:6a", "green", [ "v0" ] ],
    [ "nano:3", "sw1:7a", "green", [ "v0" ] ],
    [ "nano:2", "sw1:8a", "green", [ "v0" ] ],
    [ "sw1:1b", "sw2:8b", "green", [ "v0" ] ],
    [ "sw2:5a", "nano:9", "green", [ "v0" ] ],
    [ "sw2:6a", "nano:8", "green", [ "v0" ] ],
    [ "sw2:7a", "nano:7", "green", [ "v0" ] ],
    [ "sw2:8a", "nano:6", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}

Ho sorry, axes, in french is "axis" 2 from linear potentiometers and 2 from a stick (like PS5 stick, with 5 pins, same than the joystick on the picture )

That is not the definitive version but and my project have changed since the last screenshot above :
2 - Button 1 - blue led momentary button 1
3 - Button 2 - blue led momentary button 2
4 - Button 3 - blue led momentary button 4
5 - Button 4 - blue led momentary button 5
6 - Button 5 - ENCODER 1 button 1
7 - Button 6 - ENCODER 1 button 2
8 - Button 7 - ENCODER 1 button 3
9 - Button 8 - ENCODER 2 button 1
10 - Button 9 - ENCODER 2 button 2
11 - Button 10 - ENCODER 2 button 3
12 - Button 11 - ENCODER 3 button 1
13 - Button 12 - ENCODER 3 button 2
14 - Button 13 - ENCODER 3 button 3
15 - Button 14 - Momentary SWITCH (On OFF ON) button 1
16 - Button 15 - Momentary SWITCH (On OFF ON) button 2
17 - Button 16 - Toggle button 1(ON OFF) Button 1
18 - Button 17 - Toggle button 2 (ON OFF) Button 2
A0 - AXIS X - AXIS 1
A1 - AXIS Y - AXIS 2
A2 - AXIS Z - AXIS 3
A3 - AXIS Rz - AXIS 4

But, I have a big problem : on my micro pro board I have only "2 3 4 5 6 7 8 9 10 14 15 16" and A0 A1 A2 A3 (enough Analogic pin but not classics) 12 pin for 18 physics buttons, a tutorial on the web shows a way to overcome this problem. LINK

Are encoders not used to determine CW or CCW rotation, then "count"? They use two pins, each, but also need more code to compare current states and previous states. Are you using four pins per encoder?

Be sure not to confuse "button" (a pushbutton) with "pin" (a connection point on an MCU, or mcu module).

No thats just a "classic" encoder, turning left > 1 button, Turning right > an other button, and a last button when is "pushed" so, 3 "buttons" X 3 encoders (btw I'm searching the kind of encoders your are talking about, but, i can't find it on aliexpress, maybe the wrong key words I'm using. Thx for your help BTW :slight_smile:

Do these three actions show on three different pins?

unfortunately, yes :-/