Encodeur sur controleur de jeux

Bonjour,
dans le cadre de mon projet de cockpit d'avion, je recherche comment faire fonctionner un encodeur rotatif.
Dans mon code actuel, se que je voulais c'est utilisé les broche 3 à 5 comme des boutons normaux (sa fonctionne sans pb), puis les broche 6 et 7 pour l'encodeur.
je cherche a avoir en retour, allumer le bouton 6 quant je tourne d'un coté, et allumer le bouton 7 quand c'est de l'autre.
Si j'ai bien compris le fonctionnement d'un encodeur, ce dernier connais le sens de rotation en fonction du delta entre les 2 broches. j'ai donc voulu controler le changement d'état via la broche 6, et le choix de bouton à allumer suivant la broche 7.
Mais sa ne fonctionne absolument pas. sa allume les broche 6 ou 7 pas comme il faut.

Merci d'avance de votre aide.

le code arduino :

#include <Joystick.h>

void setup() {
  // Initialize Button Pins
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  Joystick.begin();
}
// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 1;

// Last state of the button
int lastButtonState[101] = {0,0,0,0};

void loop() {
  // Read pin values
  for (int index = 0; index < 7; index++)  {
    int currentButtonState = !digitalRead(index + pinToButtonMap);
    int encodeur = !digitalRead(7 + pinToButtonMap);
    if (index == 7){
    }
    else if (index == 6){
      if (encodeur == 1){
        if (currentButtonState != lastButtonState[5]){
          Joystick.setButton(5, currentButtonState);
          lastButtonState[5]  = currentButtonState;
        }
      }
      else{
        if (currentButtonState != lastButtonState[6]){
          Joystick.setButton(6, currentButtonState);
          lastButtonState[5]  = currentButtonState;
        }  
      }
    }
    else{
      if (currentButtonState != lastButtonState[index]){
        Joystick.setButton(index, currentButtonState);
        lastButtonState[index] = currentButtonState;
      }
    }
  }
  delay(10);
}

Si tu regardes la forme des signaux, tu vois que:

  • lorsque tu tournes dans le sens horaire, sur le front montant de Output1 tu lis 0 sur Output2
  • lorsque tu tournes dans le sens anti-horaire, sur le front montant de Output1 tu lis 1 sur Output2

Donc, il faut détecter un front montant sur Output1 et lire l'état de Output2.

1 Like

Exacte, merci.
Tu as raison. là je tente de détecter un changement d'état. il faut que je détecte uniquement un front montant.
tu aurais un exemple de code avec l'arduino en mode "controleur de jeu" ? j'arrive pas a faire activer le bouton que je souhaite, je suis toujours à coté. je pense que j’interprète mal les fonctions de code.
merci.

Non, je n'ai jamais trempé là-dedans. Il n'y a pas des exemples avec la librairie?

le plus simple est sans doute de prendre la bibliothèque encoder et lors de la détection d'un mouvement regarder si c'est vers la droite ou la gauche et envoyer les commandes adéquates.

C'est quand même un peu bizarre de prendre un encodeur rotatif pour cela cependant

un exemple de la gestion de l'encodeur pour faire plus ou moins et aussi du bouton intégré dans l'encodeur

le code
/* ============================================
  code is placed under the MIT license
  Copyright (c) 2024 J-M-L
  For the Arduino Forum : https://forum.arduino.cc/u/j-m-l

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  ===============================================
*/

#include <Encoder.h>        // https://www.arduinolibraries.info/libraries/encodeur$0
#include <Toggle.h>         // https://www.arduinolibraries.info/libraries/toggle$0

const byte encodeurCLKPin = 2;
const byte encodeurDTPin  = 3;
const byte encodeurSWPin  = 4;

Encoder encodeur(encodeurDTPin, encodeurCLKPin);
Toggle encodeurBouton;

enum EncodeurMouvement {IDENTIQUE, PLUS, MOINS};

EncodeurMouvement detection() {
  static long prevPosition;
  long newPosition = encodeur.read() >> 2; // divide by 4 as the rotary sends 4 ticks per click
  long delta = newPosition - prevPosition;
  prevPosition = newPosition;
  if (delta > 0) return PLUS;
  else if (delta < 0) return MOINS;
  return IDENTIQUE;
}

void testBouton() {
  encodeurBouton.poll();
  if (encodeurBouton.onPress())   Serial.println("APPUI");
  if (encodeurBouton.onRelease()) Serial.println("RELÂCHE");
}

void testEncodeur() {
  switch (detection()) {
    case PLUS:  Serial.println("PLUS");  break;
    case MOINS: Serial.println("MOINS"); break;
    default: break;
  }
}

void setup() {
  Serial.begin(115200);
  encodeurBouton.begin(encodeurSWPin);
  Serial.println("PRÊT");
}

void loop() {
  testEncodeur();
  testBouton();
}

1 Like

Merci,
le code à l'air de fonctionner. comme celà :

#include <Joystick.h>
#include <Encoder.h>
#include <Toggle.h> 
#include <Keypad.h>

// déclaration des variables pour les boutons
const int pinToButtonMap = 4; // Constant that maps the phyical pin to the joystick button.
int lastButtonState[4] = {0,0,0,0}; // Last state of the button

// déclaration des variable pour l'encodeur
const byte encodeurCLKPin = 8; // signale de mouvement
const byte encodeurDTPin  = 9; // signale sens de rotation
Encoder encodeur(encodeurDTPin, encodeurCLKPin);
Toggle encodeurBouton;
enum EncodeurMouvement {IDENTIQUE, PLUS, MOINS};

void setup() {
  // Initialize Button Pins
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);

  Joystick.begin();  // Initialize Joystick Library
}
void loop() {

  butons();
  Encodeur();
}

void butons(void) {
  for (int index = 0; index < 4; index++)  // Read pin values
  {
    int currentButtonState = !digitalRead(index + pinToButtonMap);
    if (currentButtonState != lastButtonState[index])
    {
      Joystick.setButton(index, currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }
  delay(10);
}

EncodeurMouvement detection() {
  static long prevPosition;
  long newPosition = encodeur.read() >> 0; // divise par 4 as the rotary sends 4 ticks per click
  long delta = newPosition - prevPosition;
  prevPosition = newPosition;
  if (delta > 0) return PLUS;
  else if (delta < 0) return MOINS;
  return IDENTIQUE;
}

void Encodeur() {
  switch (detection()) {
    case PLUS:  Joystick.setButton(10,1); delay(50); break;
    case MOINS: Joystick.setButton(11,1); delay(50); break;
    default: break;
  }
  Joystick.setButton(10,0);
  Joystick.setButton(11,0);
}

plus qu'a l'intégré dans le code avec le module 32 boutons ainsi que les axes de rotations et tout fonctionne pour le module de commande UFC du simulateur d'avion.

Pour répondre à ta question sur pourquoi prendre un encodeur rotatif : C'est simplement que le panneau que je cherche à faire est le UFC du F18. Sur ce module, les choix des canaux radio se fait par 2 encodeur rotatif qui permettent de changer de canal à chaque clic (pas de fréquence, juste le canal pré-enregistré).
Je doit donc faire comprendre à DCS (ou autre simulateur) que quand je tourne dans un sens, je veux incrémenter à chaque clic, et dans l'autre je décrémente de canal.

Ok compris
Bravo
On attend les photos :wink:

Vous pourriez utiliser aussi la bibliothèque Toggle pour vos boutons, ça rend le code plus facile

Les photos arriveront quant j'aurais reçu les boutons... c'est en cours. en attendant, voici mon code qui m'a tout l'air de fonctionner. Je suis preneur d'amélioration et de remarques. Entre autre, je n'ai pas réussi à augmenter ma capacité de boutons au-dela de 32.

en commande de contrôleur de jeu j'ai donc :

  • 28 boutons poussoir
  • 3 axes de rotation
  • 2 encodeurs rotatif (utilisant les activations de boutons 29 à 32).
#include <Keypad.h>
#include <Joystick.h>
#include <Encoder.h>
#include <Toggle.h> 

#define ENABLE_PULLUPS
#define NUMROWS 6 // nombre de colones de la matrice bouton
#define NUMCOLS 5 // nombre de ligne de la matrice bouton
const unsigned long gcCycleDelta = 1000;
const unsigned long gcAnalogDelta = 25;
const unsigned long gcButtonDelta = 500;
unsigned long gNextTime = 0;
unsigned int gCurrentStep = 0;

byte buttons[NUMROWS][NUMCOLS] = { // numéro bouton controleur -1
  {0,1,2,3,4},
  {5,6,7,8,9},
  {10,11,12,13,14},
  {15,16,17,18,19},
  {20,21,22,23,24},
  {25,26,27,28,29},
};
byte rowPins[NUMROWS] = {0,1,2,3,4,5}; // numéro des broche ligne
byte colPins[NUMCOLS] = {6,7,8,9,10}; // numéro des broche colone
Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); 

// déclaration des variable pour l'encodeur 1
const byte encodeurCLKPin1 = 12; // signale de mouvement encodeur 1
const byte encodeurDTPin1  = 13; // signale sens de rotation encodeur 1
Encoder encodeur1(encodeurDTPin1, encodeurCLKPin1);
Toggle encodeurBouton1;
enum EncodeurMouvement1 {IDENTIQUE1, PLUS1, MOINS1};

// déclaration des variable pour l'encodeur 2
const byte encodeurCLKPin2 = A4; // signale de mouvement encodeur 2
const byte encodeurDTPin2  = A5; // signale sens de rotation encodeur 2
Encoder encodeur2(encodeurDTPin2, encodeurCLKPin2);
Toggle encodeurBouton2;
enum EncodeurMouvement2 {IDENTIQUE2, PLUS2, MOINS2};

void setup() {
  Joystick.begin();
//joystick.begin();
Joystick.setXAxis (false);
Joystick.setYAxis (false);
Joystick.setZAxis(false);
Joystick.setThrottle(false);
}

void loop() { 
  CheckAllButtons();
  CheckAxes();
  CheckEncodeur1();
  CheckEncodeur2();
  }

void CheckAllButtons(void) {
  if (buttbx.getKeys())
  {
    for (int i=0; i<LIST_MAX; i++)   
    {
      if ( buttbx.key[i].stateChanged ) 
      {
        switch (buttbx.key[i].kstate) {  
          case PRESSED:
          case HOLD:
                Joystick.setButton(buttbx.key[i].kchar, 1);
                //Fixe l'état à 1) du bouton spécifié (si le numéro est 0 : la valeur est 1 si l'on appuie sur le bouton et 0 si le bouton est relâché)
                break;
          case RELEASED:
          case IDLE:
                Joystick.setButton(buttbx.key[i].kchar, 0); 
                //Fixe l'état à 1 du bouton spécifié (si le numéro est 0 : la valeur est 1 lorsque l'on appuie sur le bouton et 0 si le bouton est relâché)
                break;
        }
      }
    }
  }
}

void CheckAxes(void) {
//  Joystick.setXAxis (analogRead(A4)/4.01+385); // axe X
//  Joystick.setYAxis (analogRead(A4)/4.01+385); // axe Y
//  Joystick.setZAxis(analogRead(A4)/4.01+385); // axe Z
  Joystick.setXAxisRotation(analogRead(A0)/2.845); // axe X rota
  Joystick.setYAxisRotation(analogRead(A1)/2.845); // axe Y rota
  Joystick.setRudder(analogRead(A2)/4.01); // Palonnier
//  Joystick.setThrottle(analogRead (A3)/4.01); // Manette de gaz
  delay (5);
}

EncodeurMouvement1 detection() {
  static long prevPosition1;
  long newPosition1 = encodeur1.read() >> 0; // divise par 4 as the rotary sends 4 ticks per click
  long delta = newPosition1 - prevPosition1;
  prevPosition1 = newPosition1;
  if (delta > 0) return PLUS1;
  else if (delta < 0) return MOINS1;
  return IDENTIQUE1;
}
void CheckEncodeur1() {
  switch (detection()) {
    case PLUS1:  Joystick.setButton(28,1); delay(40); break;
    case MOINS1: Joystick.setButton(29,1); delay(40); break;
    default: break;
  }
  Joystick.setButton(28,0);
  Joystick.setButton(29,0);
}

EncodeurMouvement2 detection2() {
  static long prevPosition2;
  long newPosition2 = encodeur2.read() >> 0; // divise par 4 as the rotary sends 4 ticks per click
  long delta = newPosition2 - prevPosition2;
  prevPosition2 = newPosition2;
  if (delta > 0) return PLUS2;
  else if (delta < 0) return MOINS2;
  return IDENTIQUE2;
}
void CheckEncodeur2() {
  switch (detection2()) {
    case PLUS2:  Joystick.setButton(30,1); delay(40); break;
    case MOINS2: Joystick.setButton(31,1); delay(40); break;
    default: break;
  }
  Joystick.setButton(30,0);
  Joystick.setButton(31,0);
}

si vous regardez la bibliothèque ils disent

The joystick or gamepad can have the following features:

  • Buttons (default: 32)

donc c'est normal que vous soyez limité à 32. Si vous en voulez plus je pense qu'il faut modifier la constante dans la bibliothèque à cet endroit :

1 Like

voici les photos du module :

je me suis aussi attaqué au second qui est en cours de finalisation sur le code.

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