mercredi 4 avril 2012

Arduino télépathe (nRF24L01)

Il s'agit ici de mes premières incursions dans la communication sans fil entre deux Arduinos, au moyen du module NRF24L01.   En me basant sur l'exemple distribué avec la librairie mirf, j'ai réussi à faire en sorte qu'un premier Arduino (l'émetteur) muni de 6 boutons puisse contrôler 6 LEDs branchées sur un deuxième Arduino (le récepteur, qui peut être situé quelques dizaines de mètres plus loin).

Il faut deux modules NRF24L01.  J'ai pris les miens sur eBay (environ $5 pour la paire).  Comme c'est souvent   le cas avec les marchants asiatiques, le produit arrive sans la moindre documentation:  il faut fouiller un peu...

(Si vous préférez, j'ai aussi écrit un article sur l'utilisation des modules RF 433 MHz qui fonctionnent avec la bibliothèque VirtualWire).

Il faut aussi installer la librairie mirf.

Sur chaque Arduino, les branchements du NRF24L01 doivent se faire de la façon suivante:
Pin MISO du NRF24L01 sur la broche 12 de l'Arduino;
Pin MOSI du NRF24L01  sur la broche 11 de l'Arduino;
Pin SCK du NRF24L01 sur la broche 13 de l'Arduino;
Pin CE du NRF24L01 sur la broche 8 de l'Arduino;
Pin CSN du NRF24L01 sur la broche 9 de l'Arduino*;
Pin VCC du NRF24L01 sur 3,3  V;
Pin GND du NRF24L01 mis à la terre, évidemment.

(*: CE et CSN peuvent être branchées ailleurs si désiré)



Bien entendu, j'aurais pu me contenter de 2 ou 3 boutons contrôlant 2 ou 3 LEDs, mais j'en ai profité pour réaliser un module comportant 6 boutons déjà reliés à leur "pull up resistor" (comment ça s'appelle, en français, un "pull up resistor"?):  le module est muni de 6 sorties mâles qui peuvent être directement insérées dans les entrées numérique de l'Arduino (ou dans un breadboard), et de 6 sorties femelles si on préfère utiliser des fils pour les branchements.  Voilà un petit gadget qui me sauvera bien du temps à l'avenir!  Pour ce montage, les boutons sont branchées aux entrées 2, 3, 4, 5, 6 et 7 de l'Arduino émetteur.

Quand à l'Arduino récepteur, en plus de son module NRF24L01, il comporte 6 LEDs, chacune munie d'une résistance de protection, branchées aux sorties 2, 3, 4, 5, 6 et 7 de l'Arduino.

Quand vous appuyez sur le premier bouton de l'Arduino émetteur, la première LED de l'Arduino récepteur s'allume.  Lorsque vous appuyez à nouveau sur ce bouton, la LED s'éteint.


J'admet que ce n'est pas très utile, mais ça marche!  La portée est excellente:  je n'ai détecté aucun problème pendant que les deux Arduinos étaient séparés par deux étages dans la maison.

Ce que j'aimerais faire, maintenant, c'est modifier mon projet de robot contrôlé par joystick pour en faire un véritable véhicule télécommandé, sans le câble encombrant qui relie le joystick au véhicule...

Sketch de l'émetteur:

/****************************************************************
Code de l'émetteur.
Il envoie au récepteur l'état de ses 6 boutons.
4 avril 2012
https://electroniqueamateur.blogspot.com/2012/04/arduino-telepathe.html
*******************************************************************/
// les librairies nécessaires au fonctionnement du nRF24L01
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
// L'entrée où est branché le premier bouton (les autres sont adjacents)
#define BOUTON 2
int val[] = {0, 0, 0, 0, 0, 0}; // État des boutons
int old_val[] = {0, 0, 0, 0, 0, 0}; // État précédent des boutons
int state[] = {0, 0, 0, 0, 0, 0}; // État de la LED
byte message; // ce qui sera envoyé à l'autre Arduino
void setup(){
Mirf.cePin = 8; // CE branché sur 8
Mirf.csnPin = 9; // CSN branché sur 9
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.channel = 0;
Mirf.payload = sizeof(byte); // taille de ce qu'on va envoyer
Mirf.config();
Mirf.setTADDR((byte *)"nrf02"); // on baptise les deux modules
Mirf.setRADDR((byte *)"nrf01");
// configuration des entrées numériques associées aux boutons:
for (int i=0; i <= 5; i++){
pinMode(BOUTON+i, INPUT);
}
}
void loop(){
for (int i=0; i <= 5; i++){
val[i] = digitalRead(BOUTON+i);
// Y a-t-il eu un changement?
if ((val[i] == HIGH) && (old_val[i] == LOW)){
state[i] = 1 - state[i];
delay(10);
}
old_val[i] = val[i];
}
// mise à jour du message à envoyer à l'autre Arduino:
message = B00000000;
if (state[0]){
message = message + B00000001;
}
if (state[1]){
message = message + B00000010;
}
if (state[2]){
message = message + B00000100;
}
if (state[3]){
message = message + B00001000;
}
if (state[4]){
message = message + B00010000;
}
if (state[5]){
message = message + B00100000;
}
// on peut maintenant envoyer le message
Mirf.send((byte *)&message);
while(Mirf.isSending()); // On attend aussi longtemps que le message n'a pas été envoyé
}
Sketch du récepteur:

/*****************************************************************
Code du récepteur.
Allume ou éteint des LEDs à partir des informations
reçues de l'émetteur.
4 avril 2012.
https://electroniqueamateur.blogspot.com/2012/04/arduino-telepathe.html
******************************************************************/
// les librairies nécessaires au fonctionnement du nRF24L01
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
byte message;
// La sortie où est branchée la première LED (les autres sont adjacentes)
#define LED 2
void setup(){
Mirf.cePin = 8; // CE branché sur 8
Mirf.csnPin = 9; // CSN branché sur 9
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.channel = 0;
Mirf.payload = sizeof(byte); // taille de ce qu'on va recevoir
Mirf.config();
Mirf.setTADDR((byte *)"nrf01"); // on baptise les deux modules
Mirf.setRADDR((byte *)"nrf02");
// configuration des sorties (LEDs)
for (int i=0; i <= 5; i++){
pinMode(LED+i, OUTPUT);
}
}
void loop(){
byte data[Mirf.payload]; // data va contenir les donnéees reçues
if(!Mirf.isSending() && Mirf.dataReady()){
Mirf.getData(data); // réception du message
message = data[0];
// on allume ou éteint les LEDs
if (message >= B00100000){
digitalWrite(LED+5, HIGH); // LED allumée
message = message - B00100000;
}
else {
digitalWrite(LED+5, LOW); // LED éteinte
}
if (message >= B00010000){
digitalWrite(LED+4, HIGH); // LED allumée
message = message - B00010000;
}
else {
digitalWrite(LED+4, LOW); // LED éteinte
}
if (message >= B00001000){
digitalWrite(LED+3, HIGH); // LED allumée
message = message - B00001000;
}
else {
digitalWrite(LED+3, LOW); // LED éteinte
}
if (message >= B00000100){
digitalWrite(LED+2, HIGH); // LED allumée
message = message - B00000100;
}
else {
digitalWrite(LED+2, LOW); // LED éteinte
}
if (message >= B00000010){
digitalWrite(LED+1, HIGH); // LED allumée
message = message - B00000010;
}
else {
digitalWrite(LED+1, LOW); // LED éteinte
}
if (message >= B00000001){
digitalWrite(LED, HIGH); // LED allumée
message = message - B00000001;
}
else {
digitalWrite(LED, LOW); // LED éteinte
}
}
}

Remerciements au rédacteur du blog Skyduino, où j'ai puisé un peu d'inspiration.

Mise à jour (août 2012):  le projet de véhicule téléguidé est maintenant fonctionnel.
Yves Pelletier (Twitter: @ElectroAmateur)

1 commentaire:

  1. Bonjour, je sais que ce tuto à plusieurs années, donc j'espère que j'aurais droit à une réponse :)

    Avant tout, merci pour cette article, étant débutant, je voulais tester ce principe avec votre tuto, j'ai bien tout branché correctement, sur les bonne pin (j'ai le deuxième module NRF24L01, celui avec 8 broches), et avec 2 arduino uno, identique.

    Et impossible de faire fonctionner le système :( J'ai bien placer la bibliothèque, pas de souci au niveau de la compilation et du téléversement, j'utilise le code source tel quel. Et pourtant, rien ne se passe. Une petite idée ?

    Merci d'avance :)

    RépondreSupprimer