Création d'un joystick pour SWTOR : Galactic Starfighter avec un LEONARDO

Bonjour à tous,

Je me lance dans la création d'un joystick pour jouer à SWTOR : Galactic Starfighter avec un LEONARDO.
Ce jeu est prévu pour être joué à la souris et au clavier.

Code actuel (mouvement du manche + les boutons) édit du 17/01/2016

// Clavier Matrix 4x4
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','4'},
  {'5','6','7','8'},
  {'9','a','b','c'},
  {'d','e','f','g'}
};
byte rowPins[ROWS] = {7, 6, 5, 4}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {3, 2, 1, 0}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// Axes X et Y
const int xAxis = A0;
const int yAxis = A1;
//const int bouton = A5;

int responseDelay = 2;
int axis[] = { xAxis, yAxis};
int curseur_position[] = {0, 0};
int calibrage[] = {0, 0};
int check[] = {0, 0};
int coef = 3;

void setup() {
  Mouse.begin();
//  Serial.begin(9600);
}

void loop() {
// Les 5 boutons sur le manche
  if (digitalRead(8) == HIGH) {
    Mouse.press();
  }
  else {
    Mouse.release();
  }
  if (digitalRead(9) == HIGH) {
    Mouse.press(MOUSE_RIGHT);
  }
  else {
    Mouse.release(MOUSE_RIGHT);
  }
  if (digitalRead(10) == HIGH) {
    Keyboard.press(KEY_BACKSPACE);
    Keyboard.releaseAll();
    delay(50);
  }
  if (digitalRead(11) == HIGH) {
    Keyboard.press('v');
    Keyboard.releaseAll();
    delay(50);
  }

// Matrix 4x4
  char key = keypad.getKey();

  if (key != NO_KEY){
    if (key == '1') {
      centrage();
    }
    else if (key == '2') {
      Keyboard.press(KEY_TAB);
      Keyboard.releaseAll();
    }
    else if (key == '3') {
      Keyboard.press('8');
      Keyboard.releaseAll();  
    }
    else if (key == '4') {
      Keyboard.press('2');
      Keyboard.releaseAll();
    }
    else if (key == '5') {
      Keyboard.press('r');
      Keyboard.releaseAll();
    }
    else if (key == '6') {
      Keyboard.press('4');
      Keyboard.releaseAll();
    }
    else if (key == '7') {
      Keyboard.press('5');
      Keyboard.releaseAll();
    }
    else if (key == '8') {
      Keyboard.press('6');
      Keyboard.releaseAll();
    }
    else if (key == '9') {
      Keyboard.press(KEY_F1);
      Keyboard.releaseAll();
    }
    else if (key == 'a') {
      Keyboard.press(KEY_F2);
      Keyboard.releaseAll();
    }
    else if (key == 'b') {
      Keyboard.press(KEY_F3);
      Keyboard.releaseAll();
    }
    else if (key == 'c') {
      Keyboard.press(KEY_F4);
      Keyboard.releaseAll();
    }
    else if (key == 'd') {
      Keyboard.press('&');
      Keyboard.releaseAll();
    }
    else if (key == 'e') {
      Keyboard.press('\'');
      Keyboard.releaseAll();
    }
    else if (key == 'f') {
      Keyboard.press('(');
      Keyboard.releaseAll();
    }
    else if (key == 'g') {
      Keyboard.press('-');
      Keyboard.releaseAll();
    }
  }

// mouvements de la souris  
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}

// Les fonctions
int readAxis(int axisNumber) {
   if (check[axisNumber] == 0) {
      calibrage[axisNumber] = 517 - analogRead(axis[axisNumber]);
      check[axisNumber] = 1;
   }

  int distance = 0;

  int reading = (analogRead(axis[axisNumber]) + calibrage[axisNumber]) * coef;

  if (reading > (519 * coef + curseur_position[axisNumber])) {
    distance = 5;
  }
  else if (reading > (515 * coef + curseur_position[axisNumber])) {
    distance = 0;
  }
  else if (reading > (404 * coef + curseur_position[axisNumber])) {   
    distance = -5;
  }

// correction des erreurs du retour au centre du manche
// pas de correction pour les valeur 5 et -5, ca évite de donner la bougeotte au curseur ;)
  if (reading >= 1540 && reading <= 1570 && abs(curseur_position[axisNumber]) > 5) {
    distance = - curseur_position[axisNumber];
    curseur_position[axisNumber] = 0;
  }
  else {
// les coordonnées 0,0 sont tjs la dernière possition
    curseur_position[axisNumber] = distance + curseur_position[axisNumber];
  }
  
// inverse le sens de y
//  if (axisNumber == 1) {
//    distance = -distance;
//  }

  return distance; 
}

// fonction de centrage du curseur (683, 384) ecran 1366, 768
int centrage() {
  // Val max pour Mouse.move() vive les variables char....
  int x = 127;
  int y = 127;

  for (int i=0; i<10; i++) {
    Mouse.move(x, y, 0);
  }
  
  for (int i=0; i<5; i++) {
    Mouse.move(-x, 0, 0);
  }
  Mouse.move(-48, 0, 0);
  
  for (int i=0; i<3; i++) {
    Mouse.move(0, -y, 0);
  }
    Mouse.move(0, -3, 0);
}

Post d'origine :

Titre : Leonardo sensibilité du curseur souris commandé par un joystick.

Bonjour à tous,

Je cherche a faire un joystick pour un jeu qui se joue à la souris et au clavier.
Pour le moment, je teste avec un petite joystick comme celui là :

Par la suite avec ça :

Je teste avec le code d'exemple (Mouse.move() - Arduino Reference) que j'ai tenté de modifier sans succès...
J'aimerai exploité des valeurs avec décimales pour avoir plus grande précision car avec le code d’origine je n'ai que des entiers.

Code après mes modifs qui n'ont rien changé

const int xAxis = A3;         //analog sensor for X axis  

const int yAxis = A4; // analog sensor for Y axis

float range = 12; // output range of X or Y movement
float responseDelay = 2; // response delay of the mouse, in ms
//int threshold = range/4; // resting threshold
float threshold = range/10000;
float center = range/2; // resting position value
int minima[] = { 0, 0}; // actual analogRead minima for {x, y}
int maxima[] = { 1023, 1023}; // actual analogRead maxima for {x, y}
int axis[] = { xAxis, yAxis}; // pin numbers for {x, y}
float mouseReading[2]; // final mouse readings for {x, y}

void setup() {
Mouse.begin();
Serial.begin(9600);
}

void loop() {

// read and scale the two axes:
float xReading = readAxis(0);
float yReading = readAxis(1);

// move the mouse:
Serial.print("x : ");
Serial.print(xReading);
Serial.print(" y : ");
Serial.println(yReading);
Mouse.move(xReading, yReading, 0);
delay(responseDelay);
}

/*
reads an axis (0 or 1 for x or y) and scales the
analog input range to a range from 0 to
*/

float readAxis(int axisNumber) {
float distance = 0; // distance from center of the output range

// read the analog input:
float reading = analogRead(axis[axisNumber]);

// of the current reading exceeds the max or min for this axis,
// reset the max or min:
if (reading < minima[axisNumber]) {
minima[axisNumber] = reading;
}
if (reading > maxima[axisNumber]) {
maxima[axisNumber] = reading;
}

// map the reading from the analog input range to the output range:
reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);

// if the output reading is outside from the
// rest position threshold, use it:
if (abs(reading - center) > threshold) {
distance = (reading - center);
}

// the Y axis needs to be inverted in order to
// map the movemment correctly:
if (axisNumber == 1) {
distance = -distance;
}

// return the distance for this axis:
return distance;
}




Merci par avance pour votre aide.

Amicalement

Jyp

Je me suis bien cassé la tête mais j'ai fini par trouver une solution :

const int xAxis = A3;         //analog sensor for X axis  
const int yAxis = A4;         // analog sensor for Y axis

int range = 4;               // output range of X or Y movement
int responseDelay = 2;
int center = range/2;         // resting position value
int minima[] = { 0, 0};          // actual analogRead minima for {x, y}
int maxima[] = { 1023, 1023};    // actual analogRead maxima for {x, y}
int axis[] = { xAxis, yAxis};    // pin numbers for {x, y}

void setup() {
  Mouse.begin();
}

void loop() {

// read and scale the two axes:
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}

int readAxis(int axisNumber) {
  int distance = 0;

  int reading = analogRead(axis[axisNumber]);
  
  if (reading < minima[axisNumber]) {
    minima[axisNumber] = reading;
  }
  if (reading > maxima[axisNumber]) {
    maxima[axisNumber] = reading;
  }

  if (reading != 517) {
    if (reading >= 834) {
      reading = 4; 
    }
    else if (reading > 517) {
      reading = 3;
    }
    else if (reading == 517) {
      reading = 2;
    }
    else if (reading >= 170) {
      reading = 1;
    }
    else if (reading >= 0) {
      reading = 0;
    }
  }
  else {
    reading = 2;
  }

  if (abs(reading - center) > 0) {
    distance = (reading - center);
  }

  if (axisNumber == 1) {
    distance = -distance;
  }

  return distance;
}

Vous en pensez quoi?

Salut,

Vous en pensez quoi?

Qu'il doit y avoir un souci dans la description de ton problème :

J'aimerai exploité des valeurs avec décimales pour avoir plus grande précision car avec le code d'origine je n'ai que des entiers.

Alors que le premier tenvoi des float et le deuxième des valeurs de 0 à 4 ...

AnalogRead() retourne au mieux une valeur comprise entre 0 et 1023 quoi que tu fasses tu n'auras jamais plus de 1024 valeurs différentes.

Salut Batto,

Mon problème de départ était :

  • soit un déclenchement de la souris avec "beaucoup" d’inclinaison du joystick mais une curseur contrôlable,
  • soit un déclenchement de la souris avec "peu" d’inclinaison joystick mais une curseur incontrôlable.

Donc je pensai que si je mettais des variables avec décimale ça allait tout arranger (dont les float dans le 1er code)

Puis finalement j'ai trouve une solution (2ème code).
Je voulais savoir si on pouvait optimiser le code.

Amicalement

J'ai supprimé tout ce que je n'avais pas besoin :slight_smile:
Et rajouté une fonction de centrage du curseur

const int xAxis = A3;
const int yAxis = A4;
const int bouton = A5;

int responseDelay = 2;
int axis[] = { xAxis, yAxis};

void setup() {
  Mouse.begin();
//  Serial.begin(9600);
}

void loop() {
  
  if (digitalRead(bouton) == LOW) {
    centrage();
  }
  
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}

int readAxis(int axisNumber) {
  int distance = 0;
  
  int reading = analogRead(axis[axisNumber]);

  if (reading > 520 or reading < 515 ) {
    if (reading >= 834) {
      distance = 2;
    }
    else if (reading > 520) {
      distance = 1;
    }
    else if (reading >= 170) {
      distance = -1;
    }
    else if (reading >= 0) {
      distance = -2;
    }
  }

  if (axisNumber == 1) {
    distance = -distance;
  }

  return distance;
}

// fonction de centrage du curseur (683, 384) ecran 1366, 768
int centrage() {
  // Val max pour Mouse.move() vive les variables char....
  int x = 127;
  int y = 127;

  for (int i=0; i<10; i++) {
    Mouse.move(x, y, 0);
  }
  for (int i=0; i<5; i++) {
    Mouse.move(-x, 0, 0);
  }
  Mouse.move(-48, 0, 0);
  for (int i=0; i<3; i++) {
    Mouse.move(0, -y, 0);
  }
    Mouse.move(0, -3, 0);
}

Première étape franchie!
Le curseur se place au centre de l’écran quand on le relache.

const int xAxis = A3;
const int yAxis = A4;
const int bouton = A5;

int responseDelay = 2;
int axis[] = { xAxis, yAxis};
int echelle[] = {0, 0};

void setup() {
  Mouse.begin();
}

void loop() {
// centrage curseur  
  if (digitalRead(bouton) == LOW) {
    centrage();
  }
  
// mouvements de la souris  
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}

int readAxis(int axisNumber) {
  int distance = 0;

// Division par 2 pour éviter un problème sur l'axe y :
// quand le curseur ce "bloque" sur le bas ou le haut 
// de lécran il ne revient pas au centre
  int reading = (analogRead(axis[axisNumber])) / 2;

  if (reading > (260 + echelle[axisNumber]) or reading < (258 + echelle[axisNumber]) ) {
    if (reading >= (417 + echelle[axisNumber])) {
      distance = 2;
    }
    else if (reading > (260 + echelle[axisNumber])) {
      distance = 1;
    }
    else if (reading >= (85 + echelle[axisNumber])) {
      distance = -1;
    }
    else if (reading >= (0 + echelle[axisNumber])) {   
      distance = -2;
    }
  }

// les coordonnées 0,0 sont tjs la dernière possition
  echelle[axisNumber] = distance + echelle[axisNumber];
  
// inverse le sens de y
  if (axisNumber == 1) {
    distance = -distance;
  }

  Serial.println(echelle[1]);

  return distance;
  
}

// fonction de centrage du curseur (683, 384) ecran 1366, 768
int centrage() {
  // Val max pour Mouse.move() vive les variables char....
  int x = 127;
  int y = 127;

  for (int i=0; i<10; i++) {
    Mouse.move(x, y, 0);
  }
  
  for (int i=0; i<5; i++) {
    Mouse.move(-x, 0, 0);
  }
  Mouse.move(-48, 0, 0);
  
  for (int i=0; i<3; i++) {
    Mouse.move(0, -y, 0);
  }
    Mouse.move(0, -3, 0);
}

Étape 2 : tester avec les potentiomètres du joystick final.

Bonjour à tous,

Je sèche sur l'étape 2.
Le curseur ne revient pas toujours au centre quand le joystick est relaché.
J'ai testé plusieurs trucs mais rien n'a fonctionné.

// Axes X et Y
const int xAxis = A0;
const int yAxis = A1;

int responseDelay = 2;
int axis[] = { xAxis, yAxis};
int echelle[] = {0, 0};
int calibrage[] = {0, 0};
int initial[] = {0, 0};
int check[] = {0, 0};
int coef = 3;

void setup() {
  Mouse.begin();
  Serial.begin(9600);
}

void loop() {
// centre le curseur au milieu de l'écran  
  if (digitalRead(8) == HIGH) {
   centrage();
  }
  
// mouvements de la souris  
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}



// Les fonctions
int readAxis(int axisNumber) {
   if (check[axisNumber] == 0) {
      initial[axisNumber] = analogRead(axis[axisNumber]);
      calibrage[axisNumber] = 517 - analogRead(axis[axisNumber]);
      check[axisNumber] = 1;
    }

  int distance = 0;

  int reading = (analogRead(axis[axisNumber]) + calibrage[axisNumber]) * coef;

// correction
  if (initial[axisNumber] <= analogRead(axis[axisNumber]) + 3 and initial[axisNumber] >= analogRead(axis[axisNumber]) - 3) {
    distance = - echelle[axisNumber];
    echelle[axisNumber] = 0;
    Serial.print("correction de ");
    Serial.println(distance);
    return distance; 
  }

  if (reading > (519 * coef + echelle[axisNumber])) {
    distance = 5;
  }
  else if (reading > (515 * coef + echelle[axisNumber])) {
    distance = 0;
  }
  else if (reading > (404 * coef + echelle[axisNumber])) {   
    distance = -5;
  }

// les coordonnées 0,0 sont tjs la dernière possition
  echelle[axisNumber] = distance + echelle[axisNumber];
  
// inverse le sens de y
//  if (axisNumber == 1) {
//    distance = -distance;
//  }
  Serial.print(analogRead(axis[axisNumber]));
  Serial.print(" : ");
  Serial.print(axisNumber);
  Serial.print(" : ");
  Serial.println(echelle[axisNumber]);
  return distance; 
}

// fonction de centrage du curseur (683, 384) ecran 1366, 768
int centrage() {
  // Val max pour Mouse.move() vive les variables char....
  int x = 127;
  int y = 127;

  for (int i=0; i<10; i++) {
    Mouse.move(x, y, 0);
  }
  
  for (int i=0; i<5; i++) {
    Mouse.move(-x, 0, 0);
  }
  Mouse.move(-48, 0, 0);
  
  for (int i=0; i<3; i++) {
    Mouse.move(0, -y, 0);
  }
    Mouse.move(0, -3, 0);
}

Ça marche pour le moment :slight_smile:
avec ce bout de code :

if (reading >= 1540 && reading <= 1570 && abs(curseur_position[axisNumber]) > 5) {
    distance = - curseur_position[axisNumber];
    curseur_position[axisNumber] = 0;
  }

Code complet

// Axes X et Y
const int xAxis = A0;
const int yAxis = A1;

int responseDelay = 2;
int axis[] = { xAxis, yAxis};
int curseur_position[] = {0, 0};
int calibrage[] = {0, 0};
int check[] = {0, 0};
int coef = 3;

void setup() {
  Mouse.begin();
//  Serial.begin(9600);
}

void loop() {
// mouvements de la souris  
  int xReading = readAxis(0);
  int yReading = readAxis(1);
  Mouse.move(xReading, yReading, 0);
  delay(responseDelay);
}


// Les fonctions
int readAxis(int axisNumber) {
   if (check[axisNumber] == 0) {
      calibrage[axisNumber] = 517 - analogRead(axis[axisNumber]);
      check[axisNumber] = 1;
   }

  int distance = 0;

  int reading = (analogRead(axis[axisNumber]) + calibrage[axisNumber]) * coef;

  if (reading > (519 * coef + curseur_position[axisNumber])) {
    distance = 5;
  }
  else if (reading > (515 * coef + curseur_position[axisNumber])) {
    distance = 0;
  }
  else if (reading > (404 * coef + curseur_position[axisNumber])) {   
    distance = -5;
  }

// correction des erreurs du retour au centre du manche
// pas de correction pour les valeur 5 et -5, ca évite de donner la bougeotte au curseur ;)
  if (reading >= 1540 && reading <= 1570 && abs(curseur_position[axisNumber]) > 5) {
    distance = - curseur_position[axisNumber];
    curseur_position[axisNumber] = 0;
  }
  else {
// les coordonnées 0,0 sont tjs la dernière possition
    curseur_position[axisNumber] = distance + curseur_position[axisNumber];
  }
  
// inverse le sens de y
//  if (axisNumber == 1) {
//    distance = -distance;
//  }

  return distance; 
}

// fonction de centrage du curseur (683, 384) ecran 1366, 768
int centrage() {
  // Val max pour Mouse.move() vive les variables char....
  int x = 127;
  int y = 127;

  for (int i=0; i<10; i++) {
    Mouse.move(x, y, 0);
  }
  
  for (int i=0; i<5; i++) {
    Mouse.move(-x, 0, 0);
  }
  Mouse.move(-48, 0, 0);
  
  for (int i=0; i<3; i++) {
    Mouse.move(0, -y, 0);
  }
    Mouse.move(0, -3, 0);
}

Vous en penser quoi?
On peut l’améliorer?