Réaliser une radiocommande avec ARDUINO, manette PS2 et nRF24L01

arduino_ps2_nrf24_transmitter

L’objectif de cet article est de vous montrer comment réaliser une radiocommande à l’aide de deux ARDUINO, d’une manette PS2 et de deux transmetteurs nRF24L01. L’ergonomie et le super design d’une manette de PS2 est extrêmement plaisant, d’autant plus que le temps qu’on a passé à jouer  avec différents jeux, la rend incontournable pour un tel projet. C’est carrément une extension de la main pour certain. Sa maniabilité n’est plus à démontrer. Autre avantage de ce projet, c’est le coût. En effet, les transmetteurs coûtent moins de 4€ la paire, la manette PS2 en occasion est à moins de 10€. Cet article sera un support pour la réalisation d’un DRONE. L’objectif étant de réaliser une radiocommande DIY en 2.4GHZ afin de piloter un drone.




schema_ps2_nrf24

Liste des matériels :

  • ARDUINO x2 (Dans mon exemple, j’utilise un ARDUINO UNO et NANO)
  • nRF24L01 x2
  • Manette PS2
  • Fils
  • Platine d’essai
  • Petit moteur CC

Étape 1: Récupérer les infos de la manette

Pour cette étape, je vous redirige vers un précédent article expliquant en détail la marche à suivre. N’oubliez pas de revenir ici pour suivre l’étape 2.

Manette PS2 et Arduino || PS2 controler

Étape 2 : Mettre à jour les bornes/pin

Un problème se pose désormais, le transmetteur nRF24L01 utilise les mêmes pins que celles utilisées dans l’article/tuto que vous venez de faire.
Pour corriger ce problème, vous allez changer les pins pour la manette comme suit :

Arduino         Manette PS2

Pin 5      ==>    fil jaune
Pin 6      ==>    fil orange
Pin 3      ==>    fil marron
Pin 7      ==>    fil bleu

Maintenant les pins 13,12,11,10, 9 seront réservées aux transmetteur nRF24L01 .

Étape 3 : Câbler le nRF24L01 aux ARDUINO.

nrf24l01_photo_PS2_robot_cablage

nrf24l01       Arduino

GND       =>          GND
VCC        =>          3.3V
CE           =>          9
CSN        =>          10
SCK        =>          13
MOSI     =>          11
MISO     =>          12
IRQ      non câblé

Étape 4 : Vérifier le câblage

Ça prendra quelques minutes de votre précieux temps, mais ça peut vous en faire gagner beaucoup en recherche de panne à l’étape de test.

Manette_PS2_NRF24

Étape 5 : Télécharger les librairies

Pour cela, il faut deux librairies, l’une vous l’avez déjà en théorie. Étant donné que vous avez suivi ce Tutorial, précédemment cité.
Et la librairie concernant la communication des nRF24L01 c’est MIRF.

Télécharger le fichier zip.

Le décompresser dans le dossier « librairie » de votre IDE Arduino

Étape 6 : Transférer les programmes dans les Arduino

Lancer l’IDE et ouvrir deux fenêtres, l’une servira au code d’émission et l’autre de réception.

Copier et coller ce code dans la fenêtre Émission :

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <PS2X_lib.h>  //for v1.6
PS2X ps2x; 
int error = 0; 
byte type = 0;
byte vibrate = 0;


#define joystickPin1 0  //analog 0
#define joystickPin2 1  //analog 0
#define joystickPin3 2  //analog 0
#define joystickPin4 3  //analog 0


 float numero5=2.0;

void setup(){
  Serial.begin(9600); // pour débogage seulement.

//CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
  
 error = ps2x.config_gamepad(7,6,5,3, true, true);   //setup pins and settings:  GamePad(clock=bleu , command=orange, attention=jaune, data=b        run, Pressures?, Rumble?) check for error
 //The numbers he reported success with is as follow:

//5V = 180 ohm, voltage drop of 1.85V (3.15v to the controller)
//ATT = 5.6K ohm, voltage drop of 1.08V (3.92 to the controller)
//CLK = 5.6K ohm, voltage drop of 1.15V (3.85 to the controller)
//CMD = 860K ohm, voltage drop of 1.39V (3.61 to the controller)
//so you can give that a try as well. Though really, ignore the resistor on 5V and just connect the red power wire to 3.3V.
 if(error == 0){
   Serial.println("Found Controller, configured successful");
   Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
  Serial.println("holding L1 or R1 will print out the analog stick values.");
  Serial.println("Go to www.billporter.info for updates and to report bugs.");
 }
   
  else if(error == 1)
   Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
   
  else if(error == 2)
   Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
   
  else if(error == 3)
   Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
   
   //Serial.print(ps2x.Analog(1), HEX);
   
   type = ps2x.readType(); 
     switch(type) {
       case 0:
        Serial.println("Unknown Controller type");
       break;
       case 1:
        Serial.println("DualShock Controller Found");
       break;
       case 2:
         Serial.println("GuitarHero Controller Found");
       break;
     }




  Mirf.cePin = 9; // CE sur D9
  Mirf.csnPin = 10; // CSN sur D10
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init(); 

  Mirf.channel = 0; // On va utiliser le canal 0 pour communiquer (128 canaux disponible, de 0 Ã  127)
  Mirf.payload = 10; //  ici il faut déclarer la taille du "payload" soit du message qu'on va transmettre, au max 32 octets
  Mirf.config(); 

  Mirf.setTADDR((byte *)"nrf02"); // Le 1er module va envoyer ses info au 2eme module
  Mirf.setRADDR((byte *)"nrf01"); // On définit ici l'adresse du 1er module

  Serial.println("Le client est pret..."); 
}

void loop(){
  
  
  
  /* You must Read Gamepad to get new values
   Read GamePad and set vibration values
   ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
   if you don't enable the rumble, use ps2x.read_gamepad(); with no values
   
   you should call this at least once a second
   */
   
   
   
 if(error == 1) //skip loop if no controller found
  return; 
  
 
 else { //DualShock Controller
  
    ps2x.read_gamepad(false, vibrate);          //read controller and set large motor to spin at 'vibrate' speed
    
    if(ps2x.Button(PSB_START))                   //will be TRUE as long as button is pressed
         Serial.println("Start is being held");
    if(ps2x.Button(PSB_SELECT))
         Serial.println("Select is being held");
         
         
     if(ps2x.Button(PSB_PAD_UP)) {         //will be TRUE as long as button is pressed
       Serial.print("Up held this hard: ");
       Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
      }
      if(ps2x.Button(PSB_PAD_RIGHT)){
       Serial.print("Right held this hard: ");
        Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
      }
      if(ps2x.Button(PSB_PAD_LEFT)){
       Serial.print("LEFT held this hard: ");
        Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
      }
      if(ps2x.Button(PSB_PAD_DOWN)){
       Serial.print("DOWN held this hard: ");
     Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
      }   
  
    
      vibrate = ps2x.Analog(PSAB_BLUE);        //this will set the large motor vibrate speed based on 
                                              //how hard you press the blue (X) button    
    
    if (ps2x.NewButtonState())               //will be TRUE if any button changes state (on to off, or off to on)
    {
                   
        if(ps2x.Button(PSB_L3))
        // Serial.println("L3 pressed");
        if(ps2x.Button(PSB_R3))
        // Serial.println("R3 pressed");
        if(ps2x.Button(PSB_L2))
        // Serial.println("L2 pressed");
        if(ps2x.Button(PSB_R2))
        // Serial.println("R2 pressed");
        if(ps2x.Button(PSB_GREEN))
         //Serial.println("Triangle pressed");
         if(ps2x.Button(PSB_RED))
        // Serial.println("Rond pressed");
         if(ps2x.Button(PSB_PINK))
        // Serial.println("Carre pressed");
         if(ps2x.Button(PSB_BLUE))
         Serial.println("Croix pressed");
         
    }   
         
    if(ps2x.Button(PSB_GREEN))
        // Serial.println("Triangle just pressed");
         
    if(ps2x.ButtonPressed(PSB_RED))             //will be TRUE if button was JUST pressed
        // Serial.println("Circle just pressed");
         
    if(ps2x.ButtonReleased(PSB_PINK))             //will be TRUE if button was JUST released
        // Serial.println("Square just released");     
    
    if(ps2x.NewButtonState(PSB_BLUE))            //will be TRUE if button was JUST pressed OR released
        // Serial.println("X just changed");    
    
    
    if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) // print stick values if either is TRUE
    { 
        Serial.print("Stick Values:");
        Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX  
        Serial.print(",");
        Serial.print(ps2x.Analog(PSS_LX), DEC); 
        Serial.print(",");
        Serial.print(ps2x.Analog(PSS_RY), DEC); 
        Serial.print(",");
        Serial.println(ps2x.Analog(PSS_RX), DEC);

  delay(10);
         
    } 
    
    
 }
 
 
  int numero1 = ps2x.Analog(PSS_RX);
  int numero2 = ps2x.Analog(PSS_RY);
  int numero3 = ps2x.Analog(PSS_LX);
  int numero4 = ps2x.Analog(PSS_LY);
 
  boolean numero6=true;
  
  while(numero6 && ps2x.Button(PSB_PAD_UP) && numero5<224.0){
  numero5 = (numero5*1.25);
 
  Serial.println(numero5);
  numero6=false;

  }
  boolean numero7=true;
  while(numero7 && ps2x.Button(PSB_PAD_DOWN) && numero5>0.0){
  numero5 = (numero5/1.25);
  
  Serial.println(numero5);
  numero7=false;
 
  }

  int numero8 = int(numero5);
  
  // conversion dans un array de bytes
  byte data[Mirf.payload]; 

  data[0] = (byte )((numero1 >> 8) & 0xff);
  data[1] = (byte )(numero1 & 0xff);
  data[2] = (byte )((numero2 >> 8) & 0xff);
  data[3] = (byte )(numero2 & 0xff);
  data[4] = (byte )((numero3 >> 8) & 0xff);
  data[5] = (byte )(numero3 & 0xff);
  data[6] = (byte )((numero4 >> 8) & 0xff);
  data[7] = (byte )(numero4 & 0xff);
  data[8] = (byte )((numero8 >> 8) & 0xff);
  data[9] = (byte )(numero8 & 0xff);
  Mirf.send((byte *)&data); // On envoi les données

  while(Mirf.isSending()); 

  // pour débogage seulement:
  /*
  Serial.print("Envoye numeros ");
  Serial.print(numero1,DEC);
  Serial.print(" , ");
  Serial.println(numero2,DEC);
*/
  delay(100);
} 
Emission

Copier et coller ce code dans la fenêtre Réception :

#include <Servo.h> 
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

Servo myservo;
int ledPin = 5;  

void setup() {
  
   myservo.attach(4);
  pinMode(ledPin, OUTPUT);
  
  Serial.begin(9600);  // pour le débogage
  
  Mirf.cePin = 9; // CE sur D9
  Mirf.csnPin = 10; // CSN sur D10
  Mirf.spi = &MirfHardwareSpi; 
  Mirf.init();

  Mirf.channel = 0; 
  Mirf.payload = 10; 
  Mirf.config(); 
  
  Mirf.setTADDR((byte *)"nrf01"); // Le 2eme module va envoyer ses info au 1er module
  Mirf.setRADDR((byte *)"nrf02"); // On définit ici l'adresse du 2eme module
  
}

void loop(){
  
  

  
  int numero1=512;
  int numero2=512;
  int numero3=512;
  int numero4=512;
  int numero8=512; 
  byte numero;
  int pairimpair;
  byte data[Mirf.payload]; // Tableau de byte qui va stocker le message recu
  
  if(!Mirf.isSending() && Mirf.dataReady()){ // Si un message a été recu et qu'un autre n'est pas en cours d'emission
    
   Mirf.getData(data); // on récupére le message 
  
  // la suite de 4 bytes est convertie en 2 int   
   numero1 = ((long )data[0]) << 8;
   numero1 |= data[1];
   numero2 = ((long )data[2]) << 8;
   numero2 |= data[3];
   numero3 = ((long )data[4]) << 8;
   numero3 |= data[5];
   numero4 = ((long )data[6]) << 8;
   numero4 |= data[7];
   numero8 = ((long )data[8]) << 8;
   numero8 |= data[9]; 
    
    
     numero1 = map(numero1, 0, 255, 0, 15);
     numero2 = map(numero2, 0, 255, 0, 15);
     numero3 = map(numero3, 0, 255, 0, 15);
     numero4 = map(numero4, 0, 255, 0, 15);
       
     numero1 = sq(numero1);
     numero2 = sq(numero2);
     numero3 = sq(numero3);
     numero4 = sq(numero4);  
     
 
      analogWrite(ledPin, numero8);
myservo.write(numero8);              // tell servo to go to position in variable 'pos' 
    delay(15);  
  
  
  
   // pour débogage, on pourra enlever ensuite:
   Serial.print("Recu les numeros ");    
   Serial.print(numero1,DEC);
   Serial.print(" , ");
   Serial.print(numero2,DEC);
    Serial.print(" , ");
   Serial.print(numero3,DEC);
   Serial.print(" , ");
   Serial.print(numero4,DEC);
   Serial.print(" , ");
   Serial.println(numero8,DEC);
   
   

}}
Récéption

Maintenant que vous avez câblé, vos deux Arduino avec les deux nRF04L01 ainsi que la manette. Vous pouvez :

Câbler une led ou un petit moteur CC sur la pin 5 pour le voir varier en luminosité/vitesse lorsque vous bougerez le joystick/pad.

Aussi, vous pouvez brancher un SERVO moteur sur la pin 4 pour le voir varier d’angle, en jouant avec la manette. Sans cela, vous pouvez quand même vérifier si votre montage fonctionne en ouvrant le SERIAL MONITOR de l’Arduino récepteur et ainsi constater que les valeurs varient en fonction de la manette.

Transférer dans l’Arduino qui a la manette branchée dessus, le code Émission.

Transférer dans l’Arduino qui a uniquement le NRF24l01, le code Réception.

Brancher vos Arduino aux ports USB.

Ouvrir le Serial Monitor de l’Arduino Réception en sélectionnant le bon port.

Vidéo d’illustration de cet exemple :


Voilà, si vous avez des questions n’hésitez pas à utiliser les commentaires…

Bonne bidouille.

Electrotuto

Passionné par les nouvelles technologie, notamment l’électronique et tout ce qui se rapporte de prés ou de loin a ce domaine. Arduino et photographie son mes passe temps favoris.

42 Responses

  1. Bonjour, qu’elles sont les modifications à faire pour que le code fonctionne avec les modules xbee ?
    Car j’ai comme but de faire voler un drone avec ce systeme de commande.
    Cordialement

    • Salut,
      J’ai utilisé les xbees pour le même projet. Pour cela tu aura besoin de la librairie EASYTRANSER.
      Avec les xbees tu aura de meilleurs performances et un code plus léger et plus maniable grâce à cette librairie « EasyTranser »
      Cela dit, fait très attention aux xbees car c’est fragile et coûtent cher *_*

      Amuse toi bien

  2. Salut,

    j’aimerais savoir ce que chaque bouton fait et sur quel sortie de l’arduino, car moi je veux contrôler un petit véhicule et les moteur sont alimentés par une source externe et je dois pouvoir contrôler les mosfet avec le arduino, alors j’aimerai savoir ce que chaque bouton fait sur l’arduino de sortie
    Merci beaucoup

    • Bonjour Francis,

      Dans l’exemple que je montre toutes les touches ne sont pas exploitées. Mais tu peux faire ce que tu veux et je peux t’aider.

      Dis moi quelles touches de la manette tu souhaites utiliser et sur quelle sortie…j’essaierai de t’écrire le code.

      • Salut, moi c’est sur que j’aimerais que les joystick puisse servir pour controler un transistor pour controler un moteur qui est branché sur une source externe. Ex plus que j’avance le joystick gauche vers l’avant plus que de volt sorte d’une sortie PWN du arduino de sortie de même pour chaque mouvement des joysticks, moi je ferais mes branchement en conséquence
        merci beaucoup de ton aide !!

  3. Bonjour, j’ai utilisé2 ESC pour controller 2 brushless dc motor mais le problème qu’ils ne s’arrête pas en même temps; il y’a un décalage entre les 2 moteurs

  4. Bonjour, j’ai mal posé ma question. J’ai refais ton travail et d’après le code émetteur, lorsque j’envoie le « numéro8 », je commande mes 4 moteurs brushless pour mon quadricoptère mais j’ai pas su comment commander les 4 moteurs séparemment. Qulles modification pourrais-je ajouter aux codes svp et Merci.

    • bonjour je construit un drone que je vais controler par un capteur emg (capteur musculaire) pensez vous que je pourai adapter facilement votre programe pour que les commande vienne de ce capteur et non d une manette ?

  5. salut !
    sujet très intéressant et pourtant j’ai eu bien du mal à le trouver.
    en vue de me mettre au drone FPV, je me demandait s’il était possible (et rentable, financièrement et autonomie de batterie) de brancher une manette USB (avec les même bouton que la PS2, mais avec un port USB) du genre celle de free (fournie avec la « révolution ») ou bien genre dual trigger de thrustmaster ?

    également, est-on obligé de repasser par un arduino sur le quad ? (le récepteur branché comme avec une télécommande classique devrait fonctionner ?…)

    merci beaucoup pour le tuto et d’un éventuelle réponse … 😀

    TYT

    • Salut,

      Si on parle de rentabilité et gain de temps le mieux c’est de s’orienter vers des produit chinois.
      Si on parle de dépendance à la bidouille, je pense que c’est faisable à condition de trouver une bibliothèque arduino qui gère la manette free ou thrusmaster.

      Oui tu es obliger d’avoir deux arduino, l’un émetteur et l’autre récepteur. Deux arduinos nano font l’affaire.

      de rien c’est un plaisir

  6. bonjour

    j’ai l’impression que votre télécommande est reliée par un fil au reste, ce qui signifierait qu’elle ne peut fonctionner pour un drone (utilisation d’un fil pas très pratique !) ??
    pourra-t-on modifier le programme en cas d’expansion (gyrometre + accelerometre, gps, camera …)

  7. Salut!

    super tuto mais j’ai un souci: je pense avoir fait tous les branchements correctement, la manette est bien reconnue mais le programme émission m’affiche « select is being held » en continue, alors que je n’appuie sur aucun bouton. Je précise que ma manette est une officielle sony en bon état. Tu aurais une idée du souci?

    merci!

  8. salut !
    je reviens à la charge, mais après avoir investi dans une turnigy 9x, je vais maintenant poser la question ‘à l’envers’ :
    comment relier un joystick PC (ports DB15 ou USB) pour l’utiliser en double commande afin d’utiliser la partie émettrice de la RC 2.4Gh ?
    ahah ! elle est bonne, celle là 😉

    est-ce de l’analogique ou du numérique, pour relier la RC esclave (donc le joystsick) à la (vraie) RC maitre ? (apparemment par la prise mini-jack, la même que pour l’adaptateur USB pour RC)
    merci d’avance 😉

  9. bonjour j’aimerai savoir si je peux utiliser cette méthode avec un RF 433mhz et pas le nrf24
    svp répondez moi par e-mail
    je vous remercie d’avance pour votre aide
    salutation.

  10. Salut,
    Je suis en étudiant en Mesures Physiques et dans le cadre de mon DUT je réalise un projet tuteuré. Sur le arduino recpteur je reçois bien les commandes des joysticks, mais je n’arrive pas à modifié les programmes afin de juste recevoir les gachettes L2, R2 et les flèches droite et gauche.

    • Aurais tu quelque conseil à donner?
      Genre, est-ce qu’on ai obligé de passer par un tableau pour envoyer les données?

  11. salut à tous !

    pour ma part j’ai entré le code, et j’ai

    « No controller found, check wiring, see readme.txt to enable debug. visit http://www.billporter.info for troubleshooting tips
    Unknown Controller type found  »

    donc qu’Est-ce que ça veut dire ? je ne trouve pas le pb?

    sachant que la manette est une sony dualshock

  12. salut a tous

    je sis sur le point de construire mon quadricopter mais je rencontre un probleme au niveau du code .
    j’aimerai commander les ESC 2 a 2 pour faire les differents mouvements de mon drone
    mais il semble que il n’ya que la pin 4 et 11 qui fonctionnent . aidez moi s’il vous plait a programmer d’autre pin arduino pour effectuer different mouvement .
    jusqu’ici je decolle seulement car tous mes ESC sont relié a la pin 4.
    j’aimerais que wallid m’explique dans les details comment il a procedé si possible le code .
    merci a vous.

  13. Bonjour, moi je voudrais faire un petit chariot élévateur comme dans la vidéo de creative channel mais j’y connais pas grand chose en transmetteur avec récepteur 4 channels ou plus ;-( donc si tu pouvais me proposer un système assez simple pour pouvoir faire comme sur la vidéo ce serait vraiment cool de ta part merci d’avance 😉

  14. bonjour
    j adore votre tuto
    j ai egalement un projet RC
    pour cela je veux utiliser 2 uno
    j’ai un probléme avec la reception, je reçois pas correctement les infos.
    ce qui m’étonne c’est que sur l’emetteur le voyant rx clignote sur le récepteur il ne clignote pas, alors qu il me semble sur votre video qu’il doit clignoter
    D’ou peux venir le problème
    d’avance merci

  15. bonsoir. s’il vous plait j’ai deux préoccupation.
    première préoccupation: est-il possible de faire une simulation du fonctionnement de cette radiocommande dans protéus? parceque je n’ai pas pu trouvé la nRF24L01 dans protéus.

    2e préoccupation: dans le cas où l’on voudrait commandé un quadricopter, quel serait le code en ce moment? vu le code présenté plusi haut ne gère que quelques fonctions.

  16. bonsoir. s’il vous plait j’ai deux préoccupation.
    première préoccupation: est-il possible de faire une simulation du fonctionnement de cette radiocommande dans protéus? parceque je n’ai pas pu trouvé la nRF24L01 dans protéus.

    2e préoccupation: dans le cas où l’on voudrait commandé un quadricopter, quel serait le code en ce moment? vu le code présenté plusi haut ne gère que quelques fonctions.

  17. bonjour j aimerai connaitre les paramètres dont on tient en compte pour la commande du drone cet à les différents mouvements et les informations de commande.
    merci d’avance

    Herman

  18. Bonjour et bravo pour vos réalisations. Mon garçon est tétraplégique, possède déjà un Bebop2 dont j’ai aménagé la radiocommande, mais ça le fatigue beaucoup. Il souhaite piloter un drone avec les mouvements de sa tête. J’ai songé à réaliser un drone et sa radiocommande avec gyroscope pour capter les mouvements de sa tête. Comment puis-je faire ? Merci pour l’attention que vous porterez à ce post. Francis

  19. c’est génial . J’ai un problème de connexion, je donne le x ou un autre bouton et il me reconnaît, mais au bout d’un moment il ne me reconnaît plus rien et les LED rouges s’éteignent et seule la verte reste allumée. Je suis désolé pour mon français, je suis originaire des îles Canaries et je ne connais pas beaucoup le français, désolé

  1. Ping : Milana Travis

Répondre à lej Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Post comment