Télécommande intelligente

De Wiki LOGre
Aller à : navigation, rechercher
Langue : Français  • English

Projet réalisé par fma38.

En cours.

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...)

Câblage

Voici le 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 :

const uint8_t REFRESH_RATE = 100;  // Hz
 
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;
 
 
void setup()
{
    // Init Joystick
    Joystick.useManualSend(true);
 
    // Init BT com.
    Serial1.begin(115200);
 
    // 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;
        }
    }
 
    // Init digital inputs (buttons)
    for (uint8_t i=0; i<sizeof(BUTTONS); i++) {
        pinMode(BUTTONS[i], INPUT_PULLUP);
    }
}
 
 
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++) {
        buttons[i] = digitalRead(BUTTONS[i])?0: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();
 
    // Wait to match refresh rate (not very accurate)
    delay(1000 / REFRESH_RATE);
}

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 :

[[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:]]