Go Down

Topic: contrôleur PS2 dualshock - Utilisation comme télécommande pas chère (Read 2219 times) previous topic - next topic

J-M-L

Salut à tous

je voulais rajouter une manette sans fil ergonomique de contrôle à un petit projet et ne voulais pas m'embêter à créer une manette...

J'avais dans mes tiroirs une manette (copie chinoise) d'une "Sony"  PS2 dualshock (sans moteur de vibration)



Ell a l'avantage d'être livrée avec un module sans fil fonctionnant à 2.4GHz



La manette fonctionne sur alimentation avec 2 piles batons AAA 1.5V standard que vous accédez par une trappe sous la manette, donc c'est vraiment simple et pratique pour tous les utilisateurs, petits et grands et côté arduino on alimentera (3.3V) le module sans fil.



Il y a plusieurs intérêts à explorer cette manette pour des petits projets:

1/ d'une part vous pouvez en trouver pour vraiment pas cher an Asie, par exemple sur eBay à environ 7 euros livraison comprise (sans les piles) (chercher "B58C 64F1 Black 2.4GHz Wireless Dual Vibration Button Game Controller For PS2 PC")

2/ Bill Porter a déjà étendue une librairie (en reprenant et affinant le travail de @Shutter) qui gère les détails de la communication entre la manette et un Arduino en exposant une API d'assez haut niveau.


3/ il y a de l'information sur internet (par exemple ce très bon post en anglais qui explique un peu le protocole (en gros SPI) et d'autres informations intéressantes)





Bon OK - vous êtes convaincu et voulez jouer avec pour commander votre gadget :)

Les Branchements:

Mon unité de contrôle à distance n'a pas toutes les pins documentées sur internet mais il a les pins qu'il faut pour jouer et les pins correspondent bien au blog mentionné ci dessus



Le module sans fil a la bonne idée d'exposer des pins avec un accès simple (sans même à avoir à démonter le boîtier) pour des fils Dupont femelle standards.

Prenez une nappe de fils male <--> femelle et prenez les couleurs qui vous permettent par exemple d'avoir le fil rouge de 3.3V au bon endroit (et branchez le marron sur GND)


(bien sûr vous pouvez utiliser les fils que vous voulez)

de l'autre côté connectez votre Arduino UNO ou MEGA de la façon suivante:

Data -> pin D12 (mon fil blanc)
Command --> pin D11 (mon fil noir)
GND --> GND (mon fil marron)
3.3V ---> 3.3V (mon fil rouge)
Attention --> pin D10 (mon fil orange)
Clock --> pin D13 (mon fil jaune)

Mettez des piles dans la télécommande et allumez là avant de brancher l'arduino (qui alimente le module distant)

Installer la librairie:

Vous pouvez trouver la librairie PS2X de Bill Porter sur Github. Elle s'installe "à la main"

- Téléchargement de la librairie en clickant sur "Clone or Download" --> "Download Zip"
- Vous obtenez un fichier Arduino-PS2X-master.zip que vous décompressez.
- Dans le répertoire obtenu Arduino-PS2X-master vous trouverez un dossier PS2X_lib qu'il ne vous reste plus qu'à déplacer dans le dossier standard de vos librairies Arduino.


Le code:

voilà vous êtes prêts à jouer. la librairie propose une classe PS2X, on commence par instancier un objet pour représenter la manette et dans le setup() on appelle config_gamepad() en donnant les pins utilisées

ensuite c'est simple à utiliser. Quand vous voulez lire l'état de la manette, vous appelez read_gamepad() et votre instance a ensuite des fonctions qui permettent de savoir quels sont les états de chaque bouton qui sont d&nommés par un petit nom dans un #define que vous pouvez lire dans le .h de la librairie

Voici comment ils sont associés aux boutons



Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

J-M-L

SUITE


Les fonctions intéressantes:
NewButtonState() sera vrai si quelque chose a changé
NewButtonState(refBouton) sera vrai si refBouton vient JUSTE d'être pressé ou relâché
Analog(refBouton) donne la valeur de pression sur le bouton, pour les axes du joystick c'est la valeur entre 0 et 255 (127 ou 128 au repos) pour les boutons c'est 0 si pas pressé et 255 si appuyé, mais certaines manettes gèrent aussi la pression variable sur les boutons (mais pas cette manette pas chère).
ButtonPressed(refBouton) est vrai si le bouton VIENT d'être appuyé (depuis la dernière lecture de config)
Button(refBouton) est vrai si le bouton est tenu enfoncé
ButtonReleased(refBouton) est vrai si le bouton VIENT d'être relâché (depuis la dernière lecture de config)

Voilà un exemple de code qui écoute la télécommande toutes les 20ms et imprime dans la console série (réglée à 115200 bauds) ce qu'il se passe pour chacun des boutons ou joystick.

Code: [Select]
#include <PS2X_lib.h> /* PS2 Controller Library http://www.billporter.info/2010/06/05/playstation-2-controller-arduino-library-v1-0/ */
PS2X ps2x; /* on crée l'instance du controleur */

// information http://www.rhydolabz.com/wiki/?p=12663

// Connecter de gauche à droite en regardant le connecteur
// ----------------------
// Data --> pin 12
// Command --> pin 11
// NC
// ----------------------
// GND --> GND
// Power --> 3.3V
// Attention --> Pin 10
// ----------------------
// Clock --> pin 13
// NC
// NC
// ----------------------

const byte dataPin = 12;
const byte commandPin = 11;
const byte attentionPin = 10;
const byte clockPin = 13;

void setup() {
  Serial.begin(115200);

  /* config_gamepad(clock, command, attention, data, Pressures?, Rumble?) */
  ps2x.config_gamepad(clockPin, commandPin, attentionPin, dataPin, true, true); // gardez true, true à la fin même si pas de moteurs

  if (ps2x.readType() == 1) Serial.println(F("DualShock"));
  else {
    Serial.print(F("Manette Absente - code "));
    Serial.println(ps2x.readType());
    while (true); // on meurt ici, éventuellement enlever si vous avez un autre code manette
  }

  ps2x.read_gamepad(); // initialisation des valeurs
  delay(50);
  ps2x.read_gamepad();  /* initialise les états */
}


void loop() {
  static uint32_t chrono = 0;
  const uint32_t periode = 20ul; // la manette est assez sensible, il ne faut pas lui demander les infos trop souvent. 15ms ou 20ms ça fonctionne pour moi

  if (millis() - chrono >= periode) {
    int RX = 0, RY = 0, LX = 0, LY = 0;
    static int PRX = 127, PRY = 128, PLX = 127, PLY = 128;

    chrono += periode;

    ps2x.read_gamepad();   /* on lit l'état de la manette */

    LX = ps2x.Analog(PSS_LX);          /* joystick de gauche X*/
    LY = ps2x.Analog(PSS_LY);          /* joystick de gauche Y */
    RX = ps2x.Analog(PSS_RX);          /* joystick de droite X */
    RY = ps2x.Analog(PSS_RY);          /* joystick de droite Y */

    // si une des coordonnées des joystick a changé alors on imprime les nouvelles coordonnées
    if ((LX != PLX) || (LY != PLY) || (RX != PRX) || (RY != PRY)) {
      PLX = LX;
      PLY = LY;
      PRX = RX;
      PRY = RY;
      Serial.print(LX);    Serial.print(F(" ,"));
      Serial.print(LY);    Serial.print(F(" ,"));
      Serial.print(RX);    Serial.print(F(" ,"));
      Serial.println(RY);
    }

    // if (ps2x.NewButtonState()) {}  /* vrai s'il y a un changement d'état, si on ne veut pas lire l'état à la main  */

    // ButtonPressed(unsigned int) vrai si le bouton VIENT d'être appuyé (depuis la dernière lecture de config)
    if (ps2x.ButtonPressed(PSB_START))     Serial.println(F("START APPUI"));
    if (ps2x.ButtonPressed(PSB_SELECT))    Serial.println(F("SELECT APPUI"));
    if (ps2x.ButtonPressed(PSB_PAD_UP))    Serial.println(F("HAUT APPUI"));
    if (ps2x.ButtonPressed(PSB_PAD_RIGHT)) Serial.println(F("DROIT APPUI"));
    if (ps2x.ButtonPressed(PSB_PAD_LEFT))  Serial.println(F("GAUCHE APPUI"));
    if (ps2x.ButtonPressed(PSB_PAD_DOWN))  Serial.println(F("BAS APPUI"));
    if (ps2x.ButtonPressed(PSB_L1))        Serial.println(F("GAUCHE 1 APPUI"));
    if (ps2x.ButtonPressed(PSB_R1))        Serial.println(F("DROITE 1 APPUI"));
    if (ps2x.ButtonPressed(PSB_L2))        Serial.println(F("GAUCHE 2 APPUI"));
    if (ps2x.ButtonPressed(PSB_R2))        Serial.println(F("DROITE 2 APPUI"));
    if (ps2x.ButtonPressed(PSB_GREEN))     Serial.println(F("Triangle APPUI"));
    if (ps2x.ButtonPressed(PSB_BLUE))      Serial.println(F("X APPUI"));
    if (ps2x.ButtonPressed(PSB_RED))       Serial.println(F("Cercle APPUI"));
    if (ps2x.ButtonPressed(PSB_PINK))      Serial.println(F("Carre APPUI"));

    // Button(uint16_t); vrai si le bouton est tenu enfoncé
    if (ps2x.Button(PSB_START))     Serial.println(F("START"));
    if (ps2x.Button(PSB_SELECT))    Serial.println(F("SELECT"));
    if (ps2x.Button(PSB_PAD_UP))    Serial.println(F("HAUT"));
    if (ps2x.Button(PSB_PAD_RIGHT)) Serial.println(F("DROITE"));
    if (ps2x.Button(PSB_PAD_LEFT))  Serial.println(F("GAUCHE"));
    if (ps2x.Button(PSB_PAD_DOWN))  Serial.println(F("BAS"));
    if (ps2x.Button(PSB_L1)) Serial.println(F("GAUCHE 1"));
    if (ps2x.Button(PSB_R1))Serial.println(F("DROITE 1"));
    if (ps2x.Button(PSB_L2))Serial.println(F("GAUCHE 2"));
    if (ps2x.Button(PSB_R2))Serial.println(F("DROITE 2"));
    if (ps2x.Button(PSB_GREEN))     Serial.println(F("Triangle"));
    if (ps2x.Button(PSB_BLUE))      Serial.println(F("X"));
    if (ps2x.Button(PSB_RED))       Serial.println(F("Cercle"));
    if (ps2x.Button(PSB_PINK))      Serial.println(F("Carre"));

    // ButtonReleased(unsigned int) vrai si le bouton VIENT d'être relâché (depuis la dernière lecture de config)
    if (ps2x.ButtonReleased(PSB_START))     Serial.println(F("START RELACHE"));
    if (ps2x.ButtonReleased(PSB_SELECT))    Serial.println(F("SELECT RELACHE"));
    if (ps2x.ButtonReleased(PSB_PAD_UP))    Serial.println(F("HAUT RELACHE"));
    if (ps2x.ButtonReleased(PSB_PAD_RIGHT)) Serial.println(F("DROITE RELACHE"));
    if (ps2x.ButtonReleased(PSB_PAD_LEFT))  Serial.println(F("GAUCHE RELACHE"));
    if (ps2x.ButtonReleased(PSB_PAD_DOWN))  Serial.println(F("BAS RELACHE"));
    if (ps2x.ButtonReleased(PSB_L1))        Serial.println(F("GAUCHE 1 RELACHE"));
    if (ps2x.ButtonReleased(PSB_R1))        Serial.println(F("DROITE 1 RELACHE"));
    if (ps2x.ButtonReleased(PSB_L2))        Serial.println(F("GAUCHE 2 RELACHE"));
    if (ps2x.ButtonReleased(PSB_R2))        Serial.println(F("DROITE 2 RELACHE"));
    if (ps2x.ButtonReleased(PSB_GREEN))     Serial.println(F("Triangle RELACHE"));
    if (ps2x.ButtonReleased(PSB_BLUE))      Serial.println(F("X RELACHE"));
    if (ps2x.ButtonReleased(PSB_RED))       Serial.println(F("Cercle RELACHE"));
    if (ps2x.ButtonReleased(PSB_PINK))      Serial.println(F("Carre RELACHE"));
  }
}


une fois qu'on a compris le principe, il suffit de faire une machine à état qui gère les événements sur la manette pour contrôler son objet (cf mon tuto éventuellement)


Notes:

- parfois la télécommande est capricieuse, il faut l'éteindre et la rallumer, vous assurer que le voyant vert sur l'unité de réception ne clignote plus et rebooter l'arduino. la librairie ne sait pas se reconnecter si elle perd la manette (donc ne commandez pas un avion avec ça... juste des petits truc qui roulent pas loin et pas vite ou des petits servos pour un robot etc).

- la librairie fonctionne aussi avec d'autres manettes Sony PS2 donc vous pouvez exploiter en fonction de votre propre manette.

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

hbachetti

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

J-M-L

A mon avis cela risque d'avoir un certain succès ...  :smiley-grin:
je me suis dit que ça pourrait aider :)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Artouste


MerlinPINET

Génial!! Merci pour ce post!

Il semble que celle que j'ai acheter sur Aliexpress ne fonctionne pas.
Les deux LED sur la télécommande clignote en permanence. Du coup j'ai le message suivant sur le port série.
00:11:02.846 -> No controllNo controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips
00:11:02.879 -> Unknown Controller type

J-M-L

C'est un peu capricieux - de mémoire j'avais joué avec le bouton analog ou le petit bouton derrière et ensuite le module avait été reconnu par la télécommande
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

68tjs

<mode humour>
Je ne sais pas sous d'autres système mais avec mon firefox sous Debian le titre que je vois est :


Une petite modif du titre du premier message ?
<fin mode humour>

Au passage la méthode pour mettre des images à changé avec la nouvelle version du forum
Les Shadocks : L'ignorance ne s'apprend pas.

J-M-L

LOL

J'ai changé le titre - faut acheter un écran à plus haute résolution :))
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

lesept

J'ai le même affichage sur smartphone. Mais ça a eu l'avantage d'attirer mon regard et du coup j'ai lu la discussion...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

5_cylindres

l'affichage est formaté par le forum : quels que soient les machines, OS, navigateurs, résolutions ou niveaux de zoom, on voyait bien "con..." ... et je trouvais ça marrant
"Le Maître te montrera le puits et te fournira le seau, mais il n'ira pas puiser l'eau à ta place" (Jigorō Kanō)

J-M-L

Ok je ne vois pas ça sur mon mac ou iPad (Safari)
Peut-être je ne regarde pas au même endroit
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

5_cylindres

c'est sûr : depuis que le titre est modifié, on ne le voit plus ... ça me semble normal
"Le Maître te montrera le puits et te fournira le seau, mais il n'ira pas puiser l'eau à ta place" (Jigorō Kanō)

J-M-L

Je veux dire que je ne vois pas de titres avec des « .... » quel que soit le titre que j'utilise

C'est dans quelle page ?
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

68tjs

l'affichage est formaté par le forum : quels que soient les machines, OS, navigateurs, résolutions ou niveaux de zoom, on voyait bien "con..." ... et je trouvais ça marrant
Oui mais il y a un gros soucis moi j'aurai tendance à mettre au pluriel parce que pour ce qui est des espèces en voie de disparition <censuré>
Les Shadocks : L'ignorance ne s'apprend pas.

Go Up