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

Manette_PS2_NRF24

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 :

É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);
}
Émission

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éception 

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.

Share

Laisser un commentaire

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

Post comment