Télécommande intelligente
| Langue : | Français • English |
|---|
Projet réalisé par fma38.
Abandonné -> cf ma nouvelle télécommande intelligente
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 !
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 :
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 :
La connectique vers le Teensy++ :
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();
}