Après avoir réalisé la télécommande avec le transceiver 433MHz HC-12 dans les posts précédents, qui n'est malheureusement plus dans l'assortiment, je voudrais le remplacer par le transceiver nRF24L01. Ce module peut également être utilisé en tant que programme contrôlé comme émetteur et récepteur. Mais il est contrôlé d'une manière fondamentalement différente, à savoir via l'interface périphérique série, SPI en abrégé.
Matériel requis
Numéro | Composant |
---|---|
1 | Carte microcontrôleur avec ATmega328P, ATmega16U2, compatible avec Arduino UNO R3 |
ou Nano V3.0 avec Atmega328 CH340 ! 100% compatible Arduino avec Nano V3 ou Nano V3.0 avec puce FT232RL et ATmega328 ! 100% compatible avec Arduino Nano V3 |
|
2 | NRF24L01 avec module sans fil 2,4 GHz pour Arduino, ESP8266, Raspberry Pi |
si applicable | Adaptateur pour NRF24L01 (voir note dans le texte) |
1 | PS2 Joystick Shield Game Pad Keypad V2.0 pour Arduino |
ou KY-023 Module Joystick pour Arduino UNO R3 et autres MCUs | |
Breadboard, câble de jumper, petit matériel | |
si applicable | Boîtier de l'imprimante 3D |
Tout d'abord, voici un aperçu du nRF24L01 avec son adaptateur optionnel.
Même si je n'utilise pas moi-même l'adaptateur pour le transceiver nRF24L01, je le présente ici, car tout d'abord vous pouvez voir les affectations des broches très bien.
Et deuxièmement, vous devez donner l'indice suivant : L'émetteur-récepteur ne tolère qu'une tension de 3,3V. Pour des tensions plus élevées, cet adaptateur est recommandé, où vous pouvez voir le régulateur de tension sur le côté gauche de l'image.
D'après la désignation des broches, vous pouvez rapidement voir qu'il n'est pas connecté à une interface série (UART), mais à l'interface périphérique série (SPI).
Voici le brochage typique:
SCE | Chip Enable (RX TX Mode Select) | Digital | D9 |
---|---|---|---|
CSN | Chip Select (Active Low) | Digital | D10 |
SCK | Serial Clock | Digital | D13 |
MOSI | Master Out Slave In | Digital | D11 |
MISO | Master In Slave Out | Digital | D12 |
VCC | 3,3V !!! | ||
GND | GND | ||
IRQ | not connected |
Vous n'avez pas besoin d'y penser lorsque vous branchez le nRF24L01 dans le blindage du joystick. Mais nous devons nous rappeler que SCE=9 et CSN=10, car nous pouvons et allons définir ces broches nous-mêmes, alors que SCK, MOSI et MISO sont fixes.
Pour notre sketch, nous avons besoin d'une nouvelle bibliothèque de programmes, qui est ajoutée via le gestionnaire de bibliothèques. Nous y entrons RF24 comme terme de recherche.
Si vous descendez un peu, vous trouverez la bibliothèque de TMRh20 que j'utilise.
Comme (presque) toujours, des exemples de programmes sont installés avec la bibliothèque. Faites donc défiler l'écran jusqu'à RF24 sous Fichier / Exemples. Un sketch appelé GettingStarted est tout simplement clair pour le premier utilisateur.
Comme c'est bien d'avoir quelque chose à utiliser au début :
/**
* Un exemple simple d'envoi de données d'un émetteur-récepteur nRF24L01 à un autre.
*
* Cet exemple a été écrit pour être utilisé sur 2 appareils faisant office de "nœuds".
* Utilisez Serial Monitor pour modifier le comportement de chaque nœud.
*/
Donc : Nous avons besoin de deux MCUs avec chacun un émetteur-récepteur. Le même sketch est téléchargé sur les deux MCUs ; le micro contrôleur qui est l'émetteur et celui qui est le récepteur est déterminé dans le Serial Monitor.
N'oubliez pas que vous devez démarrer (instancier) l'IDE Arduino deux fois sur un PC pour deux ports COM virtuels différents.
Et nous devons faire un petit changement à la ligne 18. C'est là qu'on met les broches pour CE et CSN. La valeur par défaut est :
Radio RF24 (7, 8); // en utilisant la broche 7 pour la broche CE et la broche 8 pour la broche CSN
Comme indiqué ci-dessus, nous changeons les numéros de broches en CE / SCE = 9 et CSN = 10, c'est-à-dire
Radio RF24 (9, 10); // en utilisant la broche 9 pour la broche CE et la broche 10 pour la broche CSN
Compilez, téléchargez et essayez-le.
L'avantage de ce programme est que vous obtenez un message d'erreur si l'émetteur-récepteur ne répond pas, par exemple parce qu'il a été mal connecté ou que la modification du sketch mentionnée ci-dessus n'a pas été effectuée.
Avec d'autres programmes où vous ne recevez pas ce retour d'information, le dépannage prend souvent plus de temps.
Si tout est correct, il vous sera demandé de quel appareil (nœud) il s'agit. Donc entrez 0 dans le moniteur série d'un IDE et 1 dans l'autre IDE.
Le nœud qui transmet est déterminé en entrant la lettre T ou t (pour Transmit) dans la ligne supérieure du Serial Monitor.
Je vous conseille de copier ces tentatives pour gagner en confiance dans la manipulation des émetteurs-récepteurs. Lorsque quelque chose n'a pas fonctionné dans mes tentatives, j'ai téléchargé ce sketch pour voir si j'obtiens le message "radio hardware not responding". Puis l'erreur a été rapidement trouvée.
Nous passons maintenant au circuit et à la programmation de nos télécommandes et de notre Robot Car modifié, en commençant par deux Nanos.
Le brochage est dans une large mesure prédéfini en raison de l'interface SPI. Lorsque vous utilisez le Nano, SCK est sur la broche D13, MISO sur la broche 12 et MOSI sur la broche 11. Les autres broches sont sélectionnables. Je décide d'utiliser CE à la broche D2 et CSN à la broche D3 pour éviter les broches PWM, qui sont utilisées pour les moteurs dans le second sketch. Pour le joystick, j'utilise les entrées analogiques A6 et A7 et D4 pour le bouton.
Image et croquis pour la télécommande :
/*
Joystick comme contrôleur de moteur, à l'arrêt = 505
5 pas en avant / en arrière, 5 pas à droite / à gauche chacun
*
* Bibliothèque: TMRh20 / RF24, https://github.com/tmrh20/RF24/
*/
#include
#include
#include
Radio RF24 (2, 3); // CE, CSN
adresse d'octet const [6] = "CodeR";
int x = 5; // axe x = gauche / droite
int y = 5; // axe y = avant / arrière
code int = 505;
int joybutton = 4; // bouton du joystick
facteur flottant = 1,0; // pour adaptation à différentes tensions ou ADC
void setup () {
pinMode (joybutton, INPUT_PULLUP);
Serial.begin (115200);
radio.begin ();
radio.openWritingPipe (adresse);
radio.setPALevel (RF24_PA_MIN);
radio.stopListening ();
}
void sendcode () {
radio.write (& code, sizeof (code));
retard (100); // peu de retard pour la prochaine pression sur le bouton
}
boucle void () {
float A6 = facteur * analogRead (6);
float A7 = facteur * analogRead (7);
bouton booléen = digitalRead (joybutton);
Serial.print ("axe x:");
Serial.print (A6);
Serial.print ("axe y:");
Serial.print (A7);
Serial.print ("Bouton enfoncé");
Serial.print (bouton);
x = int (A6 / 100);
y = int (A7 / 100);
code = 100 * y + x;
Serial.print ("Code =");
Serial.println (code);
envoyer le code ();
}
Et voici l'image et le croquis de la Robot Car avec deux moteurs :
#include
#include
#include
Radio RF24 (2, 3); // CE, CSN
adresse d'octet const [6] = "CodeR";
// définir des variables pour le contrôle de la vitesse
int x = 0;
int y = 0;
int gauche = 0;
int droite = 0;
code int = 505;
int speedL = 0;
facteur flottant = 0,66; // correction de speedLevel = maxValue / 255
// définir les broches du moteur
int m11 = 5; // moteur (s) gauche (s) pwr1
int m12 = 6; // moteur (s) gauche (s) pwr2
int m1e = 7; // activation du (des) moteur (s) gauche (s)
int m21 = 9; // moteur (s) droit pwr1
int m22 = 10; // moteur (s) droit pwr2
int m2e = 8; // activation du (des) moteur (s) droit (s)
void setup () {
Serial.begin (9600); // configurer Serial Monitor à 9600 bps
Serial.println ("Test moteur!");
// initialiser la radio nRF24L01
radio.begin ();
radio.openReadingPipe (0, adresse);
radio.setPALevel (RF24_PA_MIN);
radio.startListening ();
// initialise les broches numériques comme sortie pour les moteurs.
pinMode (m11, SORTIE);
pinMode (m12, SORTIE);
pinMode (m1e, SORTIE);
DigitalWrite (m1e, LOW);
pinMode (m21, SORTIE);
pinMode (m22, SORTIE);
pinMode (m2e, SORTIE);
DigitalWrite (m2e, LOW);
} // fin de l'installation
boucle void () {
if (radio.available ()) {
code = 0;
radio.read (& code, sizeof (code));
Serial.println (code);
moteur();
}
retard (20); // peu de retard pour une meilleure communication série
} // fin de boucle
moteur vide () {
int speedLevel [11] = {- 255, -210, -165, -120, -75,0,75,120,165,210,255};
y = int (code / 100);
x = code - 100 * y;
speedL = speedLevel [y];
Serial.print ("code =");
Serial.print (code);
Serial.print ("y =");
Serial.print (y);
Serial.print ("x =");
Serial.print (x);
Serial.print ("speedL =");
Serial.println (speedL);
// correction de speedLevel pour les virages
si (x == 0) {
droite = vitesseL + 60;
gauche = speedL-60;
}
sinon si (x == 1) {
droite = vitesseL + 48;
gauche = speedL-48;
}
sinon si (x == 2) {
droite = vitesseL + 36;
gauche = speedL-36;
}
sinon si (x == 3) {
droite = vitesseL + 24;
gauche = speedL-24;
}
sinon si (x == 4) {
droite = vitesseL + 12;
gauche = speedL-12;
}
sinon si (x == 6) {
droite = speedL -12;
gauche = vitesseL + 12;
}
sinon si (x == 7) {
droite = speedL-24;
gauche = vitesseL + 24;
}
sinon si (x == 8) {
droite = speedL-36;
gauche = vitesseL + 36;
}
sinon si (x == 9) {
droite = speedL-48;
gauche = vitesseL + 48;
}
sinon si (x == 10) {
droite = speedL-60;
gauche = vitesseL + 60;
}
autre {
droite = speedL;
gauche = speedL;
}
// speedLevel pour "gauche" et "droite"
Serial.print ("left =");
Serial.print (à gauche);
Serial.print ("right =");
Serial.println (à droite);
// arrêter
if (gauche <63 & gauche> -63) {
DigitalWrite (m1e, LOW);
}
if (droite <63 & droite> -63) {
DigitalWrite (m2e, LOW);
}
// effronté
if (gauche> = 63) {
si (gauche> 255) gauche = 255;
int corrl = int (gauche * facteur);
Serial.print ("corrl =");
Serial.println (corrl);
analogWrite (m11, corrl);
analogWrite (m12, 0);
DigitalWrite (m1e, HIGH);
}
if (droite> = 63) {
si (droite> 255) droite = 255;
int corrr = int (abs (droite) * facteur);
Serial.print ("corrr =");
Serial.println (corrr);
analogWrite (m21, corrr);
analogWrite (m22, 0);
DigitalWrite (m2e, HIGH);
}
// en arrière
si (gauche <= -63) {
si (gauche <-255) gauche = -255;
int corrl = int (abs (gauche) * facteur);
Serial.print ("corrl =");
Serial.println (corrl);
analogWrite (m11, corrl);
analogWrite (m11, 0);
analogWrite (m12, int (abs (gauche) * facteur));
DigitalWrite (m1e, HIGH);
}
if (droite <= -63) {
si (droite <-255) droite = -255;
int corrr = int (abs (droite) * facteur);
Serial.print ("corrr =");
Serial.println (corrr);
analogWrite (m21, 0);
analogWrite (m22, corrr);
DigitalWrite (m2e, HIGH);
}
Serial.print ("Motorsteuerung okay");
} // fin du moteur
Comme vous pouvez le voir sur la photo avec les fils volants, le nRF23L01 - et l'adaptateur d'ailleurs - n'est pas adapté pour être branché sur la breadboard.
Voici donc une photo de l'écran du joystick avec un emplacement pour le nRF24L01.
Pour rappel, ici le brochage était CE=broche 9, CSN=broche 10, axe x=A0, axe y=A1 et bouton JoyStick=D8. Avec ces changements, le Sketch Motor Controller fonctionne.
Dans l'ensemble, l'émetteur-récepteur nRF24L01 est une solution bon marché et efficace pour le contrôle radio de nos petites Robot Cars.
Dans les prochains blogposts, nous ajouterons des capteurs au contrôleur pour obtenir un régulateur de vitesse et finalement être capable de conduire de manière autonome.
3 commentaires
Wolfgang Menzel
Hallo,
bezüglich NRF24L01 habe ich ein riesen Problem, das mich schon einige Stunden gekostet hat.
Ich verwende einen ESP32 DevKit mit I2C-Display und NRF24L01 als Empfänger zur Anzeigen von Daten. Allerdings ist das Display etwas klein. Ich habe noch ein 4 inch RPI TFT LCD mit Touch. Dieses funktionier am ESP einwandfrei. Allerdings finde ich keine Möglichkeit, das 4 inch Display und den NRF-Empfanger gemeinsam zu betreiben.
Ich verwende folgende includes:
#include
#include
#include
Pinbelegung für:
RF:
SCK:18or MISO:19br MOSI:23gn CE:4sw CNS:2ge +5V:rt GND:bl
TFT:
SCK:18gn MISO:19wß MOSI:23sw CS:15or DC:5ge RST:ENvi TOUCH:26gr +5V:rt GND:bl
(die Buchstaben hinter den Pins sind die Kabelfarben, hier keine relevanz)
Eigentlich sollte es doch so sein, daß der SPI-Bus mehrfach verwendet werden kann, nur CS muss sich unterscheiden. Wo kann also das Problem liegen?
Kann mit jemand helfen?
Mit freundlichen Grüßen
Wolfgang
Walter
Mit Arduino UNO konnte ich den nRF24L01 nicht zum laufen bringen, zig Internet Beiträge zum trotz.
Da entgegen klappte es mit Arduino NANO und sogar mit ESP32 Dev Kit auf Anhieb.
Rudi Brand
Hi, klingt gut! Wäre das eine Möglichkeit, einen Dashbutton-Ersatz zu bauen? Senden direkt auf Tastendruck in einem Batteriebetriebenen Gehäuse und der Empfänger am Netzteil sendet dann per MQTT ins private Netz? Aktuell habe ich einige Buttons mit ESP8266 gebaut, die im Deepsleep sind und nach dem Drücken 3-5s brauchen, bis sie im WLAN sind und mit die Batteriespannung per MQTT liefern..