Télécommande intelligente : Différence entre versions

De Wiki LOGre
Aller à : navigation, rechercher
m (Câblage)
m
 
(8 révisions intermédiaires par le même utilisateur non affichées)
Ligne 5 : Ligne 5 :
 
'''Projet réalisé par''' [[Utilisateur:fma38|fma38]].
 
'''Projet réalisé par''' [[Utilisateur:fma38|fma38]].
  
'''En cours.'''
+
''Abandonné''
  
 
== Présentation ==
 
== Présentation ==
Ligne 14 : Ligne 14 :
  
 
La partie électronique se fait via une carte [https://www.pjrc.com/store/teensypp.html Teensy++] (plein d'I/O, émulation clavier/souris/joystick si besoin...)
 
La partie électronique se fait via une carte [https://www.pjrc.com/store/teensypp.html Teensy++] (plein d'I/O, émulation clavier/souris/joystick si besoin...)
 +
 +
== Cahier des charges ==
 +
 +
* 2 joysticks, chacun ayant :
 +
** 3 voies analogiques
 +
** 1 hat 4 directions
 +
** 4 boutons
 +
* autres commandes (boutons, switchs, potars...) si besoin
 +
* retour d'info :
 +
** leds
 +
** écran lcd
 +
** vibreur
 +
** visu caméra (FPV)
 +
* communication BT
 +
 +
== Réalisation ==
 +
 +
Cette télécommande est basée sur l'utilisation de 2 manches de joystick '''Saitek Cyborg Digital 3D'''. À l'origine, ce joystick se branchait sur un port joystick/midi (sub-D 15) ; une version série puis usb a été fabriquée par la suite. Pour ce projet, n'importe quelle version peut être utilisée, mais vu que l'électronique ne sera pas utilisée, autant acheter la version la moins chère. En fait, n'importe quel joystick peut être utilisé, à condition qu'il ne soit pas à lecture optique, comme les Sidewinder de Microsoft.
 +
 +
À noter que le Cyborg peut être configuré en gaucher ; c'est indispensable ici !
 +
 +
[[Fichier:Saitek_cybrog_digital.jpg|200px]]
 +
 +
Seule la partie joystick est conservée. On commence par couper les fils qui sortent du manche lui-même en les gardant les plus longs possible :
 +
 +
[[Fichier:IMG_20160301_174538.jpg|300px]]
 +
 +
Puis on coupe la base au niveau du cylindre et on fixe les 2 manches sur une planche à l'aide d'une bride imprimée :
 +
 +
[[Fichier:IMG_20160301_174654.jpg|300px]]
 +
[[Fichier:IMG_20160223_122655.jpg|300px]]
 +
 +
La connectique vers le Teensy++ :
 +
 +
[[Fichier:IMG_20160301_180827.jpg|300px]]
 +
[[Fichier:IMG_20160301_180516.jpg|300px]]
  
 
== Câblage ==
 
== Câblage ==
  
Voici le câblage retenu sur le [https://www.pjrc.com/teensy/card4b.pdf Teensy++], incluant le pilotage futur d'un écran LCD graphique type xxx :
+
Tableau de correspondance des fils du joystick :
 +
 
 +
rouge : ground potar RZ
 +
      : signal potar RZ
 +
      : ref.  potar RZ
 +
 +
noir  : button common
 +
      : hat N
 +
      : hat S
 +
      : hat E
 +
      : hat W
 +
      : button left
 +
      : button middle
 +
      : button right
 +
      : button trigger
 +
 
 +
Câblage retenu sur le [https://www.pjrc.com/teensy/card4b.pdf Teensy++], incluant le pilotage futur d'un écran LCD graphique type xxx :
  
 
  A0 :  X 0
 
  A0 :  X 0
Ligne 70 : Ligne 122 :
  
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
const uint8_t REFRESH_RATE = 100; // Hz
+
#include <Bounce2.h>
 +
 
 +
const uint8_t DEBOUNCE_DELAY = 10; // 10ms is appropriate for most mechanical pushbuttons
  
 
const uint8_t AXIS[] = {
 
const uint8_t AXIS[] = {
Ligne 82 : Ligne 136 :
  
 
const uint8_t BUTTONS[] = {
 
const uint8_t BUTTONS[] = {
 
+
 
     // Joystick right  
+
     // Joystick right
 
     10,  // hat N  - mapped to BTN_JOYSTICK/BTN_TRIGGER    (0x120)
 
     10,  // hat N  - mapped to BTN_JOYSTICK/BTN_TRIGGER    (0x120)
 
     11,  // hat S  - mapped to BTN_THUMB                  (0x121)
 
     11,  // hat S  - mapped to BTN_THUMB                  (0x121)
Ligne 92 : Ligne 146 :
 
     16,  // right  - mapped to BTN_BASE                    (0x126)
 
     16,  // right  - mapped to BTN_BASE                    (0x126)
 
     17,  // trigger - mapped to BTN_BASE2                  (0x127)
 
     17,  // trigger - mapped to BTN_BASE2                  (0x127)
   
+
 
 
     // Joystick left
 
     // Joystick left
 
     20,  // hat N  - mapped to BTN_BASE3                  (0x128)
 
     20,  // hat N  - mapped to BTN_BASE3                  (0x128)
Ligne 105 : Ligne 159 :
  
 
const uint8_t SAMPLES = 10;
 
const uint8_t SAMPLES = 10;
 
 
uint8_t rawAxis[6][SAMPLES];
 
uint8_t rawAxis[6][SAMPLES];
 
uint16_t axis[6];
 
uint16_t axis[6];
Ligne 111 : Ligne 164 :
 
uint8_t buttons[32], prevButtons[32];
 
uint8_t buttons[32], prevButtons[32];
 
uint8_t index = 0;
 
uint8_t index = 0;
 +
 +
Bounce *bouncer;
  
  
Ligne 117 : Ligne 172 :
 
     // Init Joystick
 
     // Init Joystick
 
     Joystick.useManualSend(true);
 
     Joystick.useManualSend(true);
 
    // Init BT com.
 
    Serial1.begin(115200);
 
  
 
     // Init axis readings
 
     // Init axis readings
Ligne 130 : Ligne 182 :
 
     }
 
     }
  
     // Init digital inputs (buttons)
+
     bouncer = (Bounce *)malloc(sizeof(BUTTONS) * sizeof(Bounce));
 
     for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
 
     for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
 +
 +
        // Init digital inputs (buttons)
 
         pinMode(BUTTONS[i], INPUT_PULLUP);
 
         pinMode(BUTTONS[i], INPUT_PULLUP);
 +
        buttons[i] = 0;
 +
        prevButtons[i] = 0;
 +
 +
        // Create bounce objects
 +
        bouncer[i] = Bounce();
 +
        bouncer[i].attach(BUTTONS[i]);
 +
        bouncer[i].interval(DEBOUNCE_DELAY);
 
     }
 
     }
 
}
 
}
Ligne 150 : Ligne 211 :
 
                 Joystick.X(axis[i] / SAMPLES);
 
                 Joystick.X(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             case 1:
 
             case 1:
 
                 Joystick.Y(axis[i] / SAMPLES);
 
                 Joystick.Y(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             case 2:
 
             case 2:
 
                 Joystick.Z(axis[i] / SAMPLES);
 
                 Joystick.Z(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             case 3:
 
             case 3:
 
                 Joystick.sliderLeft(axis[i] / SAMPLES);
 
                 Joystick.sliderLeft(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             case 4:
 
             case 4:
 
                 Joystick.sliderRight(axis[i] / SAMPLES);
 
                 Joystick.sliderRight(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             case 5:
 
             case 5:
 
                 Joystick.Zrotate(axis[i] / SAMPLES);
 
                 Joystick.Zrotate(axis[i] / SAMPLES);
 
                 break;
 
                 break;
               
+
 
 
             default:
 
             default:
 
                 break;
 
                 break;
 
         }
 
         }
 
 
     }
 
     }
 
     index++;
 
     index++;
Ligne 180 : Ligne 240 :
 
         index = 0;
 
         index = 0;
 
     }
 
     }
 
+
 
 
     // Read up to 32 digital pins and use them as buttons
 
     // Read up to 32 digital pins and use them as buttons
 
     uint8_t index = 1;
 
     uint8_t index = 1;
 
     for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
 
     for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
         buttons[i] = digitalRead(BUTTONS[i])?0:1;
+
 
 +
         // Update buttons
 +
        bouncer[i].update();
 +
        if (bouncer[i].read()) {
 +
            buttons[i] = 0;
 +
        }
 +
        else {
 +
            buttons[i] = 1;
 +
        }
 
         Joystick.button(index++, buttons[i]);
 
         Joystick.button(index++, buttons[i]);
 
     }
 
     }
   
+
 
 
     // Complete USB joystick buttons (up to 32)
 
     // Complete USB joystick buttons (up to 32)
 
     while (index <= 32) {
 
     while (index <= 32) {
Ligne 207 : Ligne 275 :
 
         prevButtons[i] = buttons[i];
 
         prevButtons[i] = buttons[i];
 
     }
 
     }
 
+
 
 
     // If any axis/button changed, update USB/BT
 
     // If any axis/button changed, update USB/BT
 
     if (anyChange) {
 
     if (anyChange) {
     
+
 
 
         // Send datas to USB joystick channel
 
         // Send datas to USB joystick channel
 
         Joystick.send_now();
 
         Joystick.send_now();
 
 
    // Wait to match refresh rate (not very accurate)
 
    delay(1000 / REFRESH_RATE);
 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 
== Cahier des charges ==
 
 
* 2 joysticks, chacun ayant :
 
** 3 voies analogiques
 
** 1 hat 4 directions
 
** 4 boutons
 
* autres commandes (boutons, switchs, potars...) si besoin
 
* retour d'info :
 
** leds
 
** écran lcd
 
** vibreur
 
** visu caméra (FPV)
 
* communication BT
 
 
== Réalisation ==
 
 
Cette télécommande est basée sur l'utilisation de 2 manches de joystick '''Saitek Cyborg Digital 3D'''. À l'origine, ce joystick se branchait sur un port joystick/midi (sub-D 15) ; une version série puis usb a été fabriquée par la suite. Pour ce projet, n'importe quelle version peut être utilisée, mais vu que l'électronique ne sera pas utilisée, autant acheter la version la moins chère. En fait, n'importe quel joystick peut être utilisé, à condition qu'il ne soit pas à lecture optique, comme les Sidewinder de Microsoft.
 
 
À noter que le Cyborg peut être configuré en gaucher ; c'est indispensable ici !
 
 
[[Fichier:Saitek_cybrog_digital.jpg|200px]]
 
 
Seule la partie joystick est conservée. On commence par couper les fils qui sortent du manche lui-même en les gardant les plus longs possible :
 
 
[[Fichier:]]
 
 
Puis on coupe la base au niveau du cylindre et on fixe les 2 manches sur une planche à l'aide d'une bride imprimée :
 
 
[[Fichier:]]
 
 
(des boutons/voyants supplémentaires peuvent être ajoutés, ainsi qu'un écran LCD (texte ou graphique) et un vibreur).
 
 
La connectique vers le Teensy++ :
 
 
[[Fichier:]]
 

Version actuelle en date du 18 janvier 2017 à 13:51

Langue : Français  • English

Projet réalisé par fma38.

Abandonné

Présentation

Réalisation d'une télécommande intelligente pour piloter un hexapode, à base de joysticks.

L'idée est de faire un système où tout peut être fait sans enlever les mains des joysticks.

La partie électronique se fait via une carte Teensy++ (plein d'I/O, émulation clavier/souris/joystick si besoin...)

Cahier des charges

  • 2 joysticks, chacun ayant :
    • 3 voies analogiques
    • 1 hat 4 directions
    • 4 boutons
  • autres commandes (boutons, switchs, potars...) si besoin
  • retour d'info :
    • leds
    • écran lcd
    • vibreur
    • visu caméra (FPV)
  • communication BT

Réalisation

Cette télécommande est basée sur l'utilisation de 2 manches de joystick Saitek Cyborg Digital 3D. À l'origine, ce joystick se branchait sur un port joystick/midi (sub-D 15) ; une version série puis usb a été fabriquée par la suite. Pour ce projet, n'importe quelle version peut être utilisée, mais vu que l'électronique ne sera pas utilisée, autant acheter la version la moins chère. En fait, n'importe quel joystick peut être utilisé, à condition qu'il ne soit pas à lecture optique, comme les Sidewinder de Microsoft.

À noter que le Cyborg peut être configuré en gaucher ; c'est indispensable ici !

Saitek cybrog digital.jpg

Seule la partie joystick est conservée. On commence par couper les fils qui sortent du manche lui-même en les gardant les plus longs possible :

IMG 20160301 174538.jpg

Puis on coupe la base au niveau du cylindre et on fixe les 2 manches sur une planche à l'aide d'une bride imprimée :

IMG 20160301 174654.jpg IMG 20160223 122655.jpg

La connectique vers le Teensy++ :

IMG 20160301 180827.jpg IMG 20160301 180516.jpg

Câblage

Tableau de correspondance des fils du joystick :

rouge : ground potar RZ
      : signal potar RZ
      : ref.   potar RZ

noir  : button common
      : hat N
      : hat S
      : hat E
      : hat W
      : button left
      : button middle
      : button right
      : button trigger

Câblage retenu sur le Teensy++, incluant le pilotage futur d'un écran LCD graphique type xxx :

A0 :  X 0
A1 :  Y 0
A2 : RZ 0
A3 :  X 1
A4 :  Y 1
A5 : RZ 1
A6 : free
A7 : free

 0 : free
 1 : free
 2 : RX BT
 3 : TX BT
 4 : free
 5 : free
 6 : free (led)
 7 : free
 8 : CE LCD
 9 : CS LCD
10 : hat N 0
11 : hat S 0
12 : hat E 0
13 : hat W 0
14 : button left 0
15 : button middle 0
16 : button right 0
17 : button trigger 0
18 : RD LCD
19 : WR LCD
20 : hat N 1
21 : hat S 1
22 : hat E 1
23 : hat W 1
24 : button left 1
25 : button middle 1
26 : button right 1
27 : button trigger 1
28 : D0 LCD
29 : D1 LCD
30 : D2 LCD
31 : D3 LCD
32 : D4 LCD
33 : D5 LCD
34 : D6 LCD
35 : D7 LCD

Soft

Exemple de code émulant 1 joystick USB avec 6 axes analogiques et 16 boutons :

#include <Bounce2.h>
 
const uint8_t DEBOUNCE_DELAY = 10; // 10ms is appropriate for most mechanical pushbuttons
 
const uint8_t AXIS[] = {
    0,   // X,  joystick right - mapped to ABS_X        (0x00)
    1,   // Y,  joystick right - mapped to ABS_Y        (0x01)
    2,   // RZ, joystick right - mapped to ABS_Z        (0x02)
    3,   // X,  joystick left  - mapped to ABS_THROTTLE (0x06)
    4,   // Y,  joystick left  - mapped to ABS_RUDDER   (0x07)
    5    // RZ, joystick left  - mapped to ABS_RZ       (0x05)
};
 
const uint8_t BUTTONS[] = {
 
    // Joystick right
    10,   // hat N   - mapped to BTN_JOYSTICK/BTN_TRIGGER    (0x120)
    11,   // hat S   - mapped to BTN_THUMB                   (0x121)
    12,   // hat E   - mapped to BTN_THUMB2                  (0x122)
    13,   // hat W   - mapped to BTN_TOP                     (0x123)
    14,   // left    - mapped to BTN_TOP2                    (0x124)
    15,   // middle  - mapped to BTN_PINKIE                  (0x125)
    16,   // right   - mapped to BTN_BASE                    (0x126)
    17,   // trigger - mapped to BTN_BASE2                   (0x127)
 
    // Joystick left
    20,   // hat N   - mapped to BTN_BASE3                   (0x128)
    21,   // hat S   - mapped to BTN_BASE4                   (0x129)
    22,   // hat E   - mapped to BTN_BASE5                   (0x12a)
    23,   // hat W   - mapped to BTN_BASE6                   (0x12b)
    24,   // left    - mapped to BTN_DEAD                    (0x12f)
    25,   // middle  - mapped to BTN_GAMEPAD/BTN_SOUTH/BTN_A (0x130)
    26,   // right   - mapped to BTN_EAST/BTN_B              (0x131)
    27,   // trigger - mapped to BTN_C                       (0x132)
};
 
const uint8_t SAMPLES = 10;
uint8_t rawAxis[6][SAMPLES];
uint16_t axis[6];
uint8_t prevAxis[6];
uint8_t buttons[32], prevButtons[32];
uint8_t index = 0;
 
Bounce *bouncer;
 
 
void setup()
{
    // Init Joystick
    Joystick.useManualSend(true);
 
    // Init axis readings
    for (uint8_t i=0; i<sizeof(AXIS); i++) {
        axis[i] = 0;
        prevAxis[i] = 0;
        for (uint8_t j=0; j<SAMPLES; j++) {
            rawAxis[i][j] = 0;
        }
    }
 
    bouncer = (Bounce *)malloc(sizeof(BUTTONS) * sizeof(Bounce));
    for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
 
        // Init digital inputs (buttons)
        pinMode(BUTTONS[i], INPUT_PULLUP);
        buttons[i] = 0;
        prevButtons[i] = 0;
 
        // Create bounce objects
        bouncer[i] = Bounce();
        bouncer[i].attach(BUTTONS[i]);
        bouncer[i].interval(DEBOUNCE_DELAY);
    }
}
 
 
void loop()
{
 
    // Read up to 6 analog inputs and use them as axis
    for (uint8_t i=0; i<sizeof(AXIS); i++) {
        axis[i] = axis[i] - rawAxis[i][index];
        rawAxis[i][index] = analogRead(AXIS[i]) >> 2;  // remove noisy bits
        axis[i] = axis[i] + rawAxis[i][index];
 
        switch (i) {
            case 0:
                Joystick.X(axis[i] / SAMPLES);
                break;
 
            case 1:
                Joystick.Y(axis[i] / SAMPLES);
                break;
 
            case 2:
                Joystick.Z(axis[i] / SAMPLES);
                break;
 
            case 3:
                Joystick.sliderLeft(axis[i] / SAMPLES);
                break;
 
            case 4:
                Joystick.sliderRight(axis[i] / SAMPLES);
                break;
 
            case 5:
                Joystick.Zrotate(axis[i] / SAMPLES);
                break;
 
            default:
                break;
        }
    }
    index++;
    if (index >= SAMPLES) {
        index = 0;
    }
 
    // Read up to 32 digital pins and use them as buttons
    uint8_t index = 1;
    for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
 
        // Update buttons
        bouncer[i].update();
        if (bouncer[i].read()) {
            buttons[i] = 0;
        }
        else {
            buttons[i] = 1;
        }
        Joystick.button(index++, buttons[i]);
    }
 
    // Complete USB joystick buttons (up to 32)
    while (index <= 32) {
        Joystick.button(index++, 0);
    }
 
    // check to see if any axis/button changed since last time
    boolean anyChange = false;
    for (uint8_t i=0; i<sizeof(AXIS); i++) {
        if (axis[i] != prevAxis[i]) {
            anyChange = true;
        }
        prevAxis[i] = axis[i];
    }
    for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
        if (buttons[i] != prevButtons[i]) {
            anyChange = true;
        }
        prevButtons[i] = buttons[i];
    }
 
    // If any axis/button changed, update USB/BT
    if (anyChange) {
 
        // Send datas to USB joystick channel
        Joystick.send_now();
}