Comment envoyer et recevoir en même temps avec un NRF24L01, librairie Mirf

Oui, merci mais j'y avais déjà pensé :wink:

:slight_smile:

désolé, mais ça ne marche pas avec mes programmes :

//programme téléversé sur arduino nano ( partie télécommande )

#include <SPI.h>      // Pour la communication via le port SPI
#include <RF24.h>

RF24 radio(10, 9);
const byte adresses[][6] = {"0pipe", "1pipe"};


byte valeurs[9]; //donnés à envoyer

char buzzer = 6;

const byte bouton1 = 4;
const byte bouton2 = 3;
const byte bouton3 = 2;


const byte joyx = A1;
int valx = 0; // valeur de joyx
const byte joyy = A2;
int valy = 0;// valeur de joyy
const byte potentiometre = A3;
int valp = 0;// valeur ...
const byte joyx2 = A6;
int valx2;
const byte joyy2 = A7;
int valy2;
const byte boutonled = 5;
boolean  valled = 0;
boolean valled2 = 0;


////valeurs à envoyer//////////
boolean led2 = 0;
byte vitessem1 = 0;
byte vitessem2 = 0;
boolean moteur1 = 0;
boolean moteur2 = 0;
boolean onoffmoteur = 0;
byte servo1 = 0;
byte servo2 = 0;
byte servoled = 0;

void setup() {
  ///////configuration du module radio///////////////
  radio.begin();
  // pour le test on règle le niveau d'énergie à RF24_PA_LOW pour éviter les interférences
  // mettre à RF24_PA_MAX si on veut la puissance d'émission max
  radio.setPALevel(RF24_PA_LOW);

  radio.openWritingPipe(adresses[0]);
  radio.openReadingPipe(1, adresses[1]);

  /////////////////////////////////////////////////
  Serial.begin(9600);

  pinMode(joyx, INPUT);
  pinMode(joyy, INPUT);
  pinMode(potentiometre, INPUT);
  pinMode(joyx2, INPUT);
  pinMode(joyy2, INPUT);
  pinMode(boutonled, INPUT);

}

void loop() {
  /////////////////////////////////////////////////////////////////////////
  //  //  //  //  //  //corps du programme ///  //  //  //  //  //  //  //
  /////////////////////////////////////////////////////////////////////////

  valx = analogRead(joyx);
  valy = analogRead(joyy);
  valp = analogRead(potentiometre);
  valx2 = analogRead(joyx2);
  valy2 = analogRead(joyy2);
  valled = digitalRead(boutonled);

  //////////////////////////////////////////
  if (valled == 1) {
    if (valled2 == 1) {
      led2 = !led2;
      valled2 = 0;
    }
  }
  else {
    valled2 = 1;
  }

  ////////////////////////////////////////////////////////////
  //mode 1: avence
  if ((valx >= 751) && (valy <= 750) && (valy >= 251))
  {
    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 255);

    moteur1 = 1;
    moteur2 = 1;

    onoffmoteur = 1;
  }

  //mode 2:recule
  else if ((valx <= 250) && (valy <= 750) && (valy >= 251))
  {

    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 255);

    moteur1 = 0;
    moteur2 = 0;

    onoffmoteur = 1;
  }
  //mode 3:tourne à gauche
  else if ((valx <= 750) && (valx >= 251) && (valy <= 250))
  {

    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 255);
    moteur1 = 0;
    moteur2 = 1;

    onoffmoteur = 1;
  }

  //mode 4:tourne à droite
  else if ((valx <= 750) && (valx >= 251) && (valy >= 751))
  {

    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 255);
    moteur1 = 1;
    moteur2 = 0;

    onoffmoteur = 1;
  }
  //mode 5:avant gauche
  else if ((valx >= 751) && (valy <= 250))
  {

    vitessem1 = map (valp, 0, 1023, 80, 127);
    vitessem2 = map (valp, 0, 1023, 80, 255);
    moteur1 = 1;
    moteur2 = 1;

    onoffmoteur = 1;
  }

  //mode 6:avant droite
  else if ((valx >= 751) && (valy >= 751))
  {
    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 127);
    moteur1 = 1;
    moteur2 = 1;

    onoffmoteur = 1;
  }

  //mode 7:arrière gauche
  else if ((valx <= 250) && (valy <= 250))
  {
    vitessem1 = map (valp, 0, 1023, 80, 127);
    vitessem2 = map (valp, 0, 1023, 80, 255);

    moteur1 = 0;
    moteur2 = 0;

    onoffmoteur = 1;
  }

  //mode 8:arrière droite
  else if ((valx <= 250) && (valy >= 751))
  {
    vitessem1 = map (valp, 0, 1023, 80, 255);
    vitessem2 = map (valp, 0, 1023, 80, 127);

    moteur1 = 0;
    moteur2 = 0;

    onoffmoteur = 1;
  }
  else {
    moteur1 = 0;
    moteur2 = 0;

    onoffmoteur = 0;
  }

  /////////////////////////////////////////////////////////////////////////
  //  //  //  //  //  //partie envoie des donnés ///  //  //  //  //  //  /
  /////////////////////////////////////////////////////////////////////////

  valeurs[0] = led2;
  valeurs[1] = vitessem1;
  valeurs[2] = vitessem2;
  valeurs[3] = moteur1;
  valeurs[4] = moteur2;
  valeurs[5] = onoffmoteur;
  valeurs[6] = servo1;
  valeurs[7] = servo2;
  valeurs[8] = servoled;

  radio.write( &valeurs, sizeof(valeurs));
}
//programme téléversé sur arduino mega ( partie robot )

#include <SPI.h>      // Pour la communication via le port SPI
#include <RF24.h>

RF24 radio(53, 48);
const byte adresses[][6] = {"0pipe", "1pipe"};
///////////////////////////////////////

const byte moteur1a = 44;
const byte moteur1b = 46;
const byte moteur2a = 47;
const byte moteur2b = 45;
const byte pwm1 = 3;
const byte pwm2 = 2;

const byte ledpin = 22;

//////////////////////////////////////
byte valeurs[9]; //donnés à recevoir

boolean moteur1 = 0;
boolean moteur2 = 0;
boolean onoffmoteur = 0;
byte Vitessem1 = 0;
byte Vitessem2 = 0;
boolean led = 0;
byte servo1 = 0;
byte servo2 = 0;
byte servoled = 0;


void setup() {

  ////////////////////////////////////////////

  Serial.begin(9600);

  ///////configuration du module radio///////////////
  radio.begin();
  // pour le test on règle le niveau d'énergie à RF24_PA_LOW pour éviter les interférences
  // mettre à RF24_PA_MAX si on veut la puissance d'émission max
  radio.setPALevel(RF24_PA_LOW);

  radio.openWritingPipe(adresses[1]);
  radio.openReadingPipe(1, adresses[0]);

  radio.startListening();
  ////////////////////////////////////////

  pinMode(moteur1a, OUTPUT);
  pinMode(moteur1b, OUTPUT);
  pinMode(pwm1, OUTPUT);
  pinMode(moteur2a, OUTPUT);
  pinMode(moteur2b, OUTPUT);
  pinMode(pwm2, OUTPUT);

  pinMode(ledpin, OUTPUT);

  analogWrite(pwm1, 0);
  digitalWrite(moteur1a, LOW);
  digitalWrite(moteur1b, LOW);

  analogWrite(pwm2, 0);
  digitalWrite(moteur2a, LOW);
  digitalWrite(moteur2b, LOW);
}

void loop() {

  /////////////////////////////////////////////////////////////////////////
  //  //  //  //  //  //partie réception des donnés ///  //  //  //  //  //  /
  /////////////////////////////////////////////////////////////////////////

  if ( radio.available()) {
      radio.read( &valeurs, sizeof(valeurs) );  // on lit l'octet reçu (si plusieurs messages on ne conserve que le dernier)
  
   led = valeurs[0];
    Vitessem1 = valeurs[1];
    Vitessem2 = valeurs[2] ;
    moteur1 = valeurs[3] ;
    moteur2 = valeurs[4] ;
    onoffmoteur = valeurs[5] ;
    servo1 = valeurs[6] ;
    servo2 = valeurs[7]  ;
    servoled = valeurs[8]  ;

  }
  /////////////////////////////////////////////////////////////////////////
  //  //  //  //  //  //corps du programme ///  //  //  //  //  //  //  //
  /////////////////////////////////////////////////////////////////////////


  if (led == 1) {
    digitalWrite(ledpin, HIGH);
  }
  else if (led == 0){
    digitalWrite(ledpin, LOW);
  }

 ///////////////////////////////////////

  if (onoffmoteur == 1) {  //moteur

    if (moteur1 == 0) {
      digitalWrite(moteur1a, HIGH);
      digitalWrite(moteur1b, LOW);
    }
    else if (moteur1 == 1) {
      digitalWrite(moteur1a, LOW);
      digitalWrite(moteur1b, HIGH);
    }

    if (moteur2 == 0) {
      digitalWrite(moteur2a, HIGH);
      digitalWrite(moteur2b, LOW);
    }
    else if (moteur2 == 1) {
      digitalWrite(moteur2a, LOW);
      digitalWrite(moteur2b, HIGH);
    }

    analogWrite(pwm1, Vitessem1);
    analogWrite(pwm2, Vitessem2);

  }
  else if (onoffmoteur == 0) { //moteur
    analogWrite(pwm1, 0);
    digitalWrite(moteur1a, LOW);
    digitalWrite(moteur1b, LOW);

    analogWrite(pwm2, 0);
    digitalWrite(moteur2a, LOW);
    digitalWrite(moteur2b, LOW);
  }
}

J'ai essayé plusieurs choses mais cela ne fonctionne toujours pas :frowning: Pourriez-vous m'aidé en disant ce qu'il ne va pas dans les 2 programmes si-dessus ?

Merci d’avance pour votre réponse :slight_smile:

Je n'ai pas le temps de plonger dans tout votre code mais voici un exemple qui envoie une structure (donc à vous de mettre ce que vous voulez dans la structure du message)

J'ai repris le même code que dans mon tuto mais ce coup ci j'ai viré les boutons et les LEDs, tout l'affichage se fait sur le terminal

2 x Arduino UNO
2 x (NRF24L01+ avec leur support adaptateur de tension 5V)

L'idée est toute simple, on met le même code sur les 2 arduinos mais le code va se configurer dynamiquement en fonction de la valeur de la Pin A0. Si A0 est à GND vous aurez le rôle 0, si elle est à une autre valeur alors vous avez le rôle 1 . ça permet d'avoir un seul code et de définir qui parle sur quel pipe et qui écoute sur quel pipe (en inversant les rôles) --> DONC BIEN BRANCHER CES FILS sinon virer la partie du setup() qui regarde A0 et mettre role à 0 pour un arduino, uploade dans le premier arduino, puis mettre role à 1 et uploader dans le second arduino.


Connexions depuis les composants vers l'arduino

NRF24L01+ avec leur support adaptateur de tension:
VCC --> 5V
GND --> GND
CE --> D7
CSN --> D8
SCK --> D13
MOSI (MO) --> D11
MISO (MI) --> D12
IRQ --> Non connecté

Configuration du logiciel
Arduino Pin A0 --> GND sur le premier Arduino (rôle = 0)
Arduino Pin A0 --> 3.3V sur le second Arduino (rôle = 1) (j'ai pris 3.3V car la pin 5V était prise :slight_smile: )


L'idée du code de démonstration est la suivante: chaque arduino va attendre pendant un moment aléatoire puis balancer un message structuré à l'autre arduino. ici la structure contient une zone de texte et un nombre. le code fait que le texte est la représentation ASCII du nombre ce qui permet de voir à l'affichage (si on en doutait) que l'on a bien reçu le message complet.

Voici le code:

// ************* La Radio *************
#include <SPI.h>
#include <RF24.h> // voir http://tmrh20.github.io/RF24/

// Configurer vos radio nRF24L01+ sur le bus SPI et mettre  CE sur D7 et CSN sur D8
RF24 radio(7, 8);

// Le nom des "pipes" de communication, un en lecture, un en écriture
const byte adresses[][6] = {"0pipe", "1pipe"}; // les "pipes" de communication de 1 à 5 doivent partager la même adresse sauf le premier octet

// A CONFIGURER sur la pin A0
// si A0 est à GND alors rôle = 0 --> le premier Arduino
// si A0 est à  3.3V ou 5V alors rôle = 1 --> pour le second
const byte configurationPin = A0;
uint8_t role;

// on déclare un message un peu complexe
struct message_t {
  char texte[11];         // 11 octets de texte - juste assez pour un unsined long qui est au plus de 10 caractères "4294967295" plus le nul '\0' de fin
  unsigned long chrono;   // 4 octets pour un timestamp
} message;


// ----------------------------------------------------------------------------------------
// envoi d'un octet vers l'autre radio
// ----------------------------------------------------------------------------------------

void envoyerMessage(message_t &msg)
{
  radio.stopListening();   // On arrête d'écouter pour qu'on puisse émettre

  if (!radio.write( &msg, sizeof(message_t) )) {
    Serial.println(F("erreur d'envoi"));
  }
  radio.startListening(); // On se remet en mode écoute
}

// ----------------------------------------------------------------------------------------
// vérifie si on a reçu une commande de la part de l'autre radio (1 octet)
// ----------------------------------------------------------------------------------------
boolean ecouterRadio(message_t &msg)
{
  boolean messageRecu = false;
  if ( radio.available()) {
    radio.read( &msg, sizeof(message_t));  // on lit le message
    messageRecu = true;
  }
  return messageRecu;
}

// ------------------------------------------------------------------

void setup() {
  pinMode(A0, INPUT); // cette pin sert à allouber les bonne adresses à chacun des modules

  randomSeed(analogRead(A1)); // la pin A1 est flottante on s'en  sert pour générer de l'aléatoire cf https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/

  Serial.begin(115200);

  role = (digitalRead(configurationPin) == LOW) ? 0 : 1 ; // si AO est LOW alors je suis le module 0 sinon je suis le module 1
  Serial.print(F("\nMon Role = ")); Serial.println(role);

  // On configure la radio
  radio.begin();
  
  // pour le test on règle le niveau d'énergie à RF24_PA_LOW pour éviter les interférences
  // mettre à RF24_PA_MAX si on veut la puissance d'émission max
  radio.setPALevel(RF24_PA_LOW);

  // On ouvre un pipe de lecture et un d'écriture avec des noms opposés en fonction du rôle
  // comme ça un parle sur "pipe0" et l'autre écoute sur "pipe0"
  // et l'autre parle sur "pipe1" tandisque Le premier écoute sur "pipe1"

  radio.openWritingPipe(adresses[role]); // role doit être 0 ou 1
  radio.openReadingPipe(1, adresses[1 - role]); // 1 - role = l'autre adresse

  // on commence à écouter si on nous parle
  radio.startListening();
}

// ------------------------------------------------------------------

void loop() {
  static unsigned long chronoPrecedent = millis();

  // on va parler de temps en temps de manière aléatoire
  unsigned long tempsAleatoire = random(5000); // une durée d'attente aléatoire avant d'émettre

  // tant qu'on n'a pas attendu assez longtems on ne fait qu'écouter si on reçoit un message
  while (millis() - chronoPrecedent <= tempsAleatoire) {
    if (ecouterRadio(message)) { // si on a reçu un message
      Serial.println(F("---------------------------"));
      Serial.print(F("J'ai recu \"")); Serial.print(message.texte);
      Serial.print(F("\"\ntiming = ")); Serial.println(message.chrono);
    }
  }

  // on a attendu assez longtemps on balance notre message
  chronoPrecedent = millis();
  ultoa(chronoPrecedent, message.texte, 10); // ultoa convertit un unsined long en texte https://www.microchip.com/webdoc/avrlibcreferencemanual/group__avr__stdlib_1ga34f41757388f40e340f31e370ac009b5.html
  message.chrono = chronoPrecedent;
  envoyerMessage(message);

}

le code est donc vraiment tout simple. On déclare une structure, le setup() prépare la configuration et dans la boucle on génère un nombre aléatoire qui sera notre temps de pause (entre 0 et 5 secondes), on fait une petite attente active sans delay() pour pouvoir écouter si on reçoit quelque chose pendant ce temps et une fois que l'on a attendu assez longtemps on balance notre message qui consiste simplement en la valeur de millis() à ce moment là, que l'on représente à la fois en ASCII et numériquement dans le message.

L'arduino de l'autre côté fait la même chose mais avec des pipes inversés, donc il écoute aussi et dès qu'il reçoit quelque chose il l'imprime (et inversement)

DONC:

  • vous câblez correctement les 2 Arduinos en n'oubliant pas de mettre A0 à GND sur l'un et 3.3V sur l'autre
  • vous sectionnez dans l'IDE le bon type d'Arduino
  • vous sélectionnez dans l'IDE le premier port série et vous uploadez
  • vous sélectionnez dans l'IDE le second port série et vous uploadez

à partir de ce moment là vos 2 arduinos ont le bon code.

Pour tester il faut 2 ports USB sur votre ordinateur et un logiciel terminal série pour pouvoir afficher les 2 voies Séries en même temps. -> sur Mac j'utilise CoolTerm qui existe aussi pour windows et Linux mais les utilisateurs PC souvent prennent PUTTY.

ASSUREZ VOUS QUE LA CONSOLE SERIE ARDUINO NE SOIT PAS OUVERTE.

Vous lancez votre programme Terminal, ouvrez 2 fenêtres que vous configurez séparément pour être connecté sur chacun des ports séries

Puis vous vous connectez et là magie vous voyez que chaque arduino redémarre (quand on ouvre la console série) et ils affichent leur rôle puis les messages qui défilent comme prévu aléatoirement

Voilà reste plus qu'à intégrer cette approche dans votre code

Merci beaucoup de votre réponse ! Je vais essayé ça tout de suite

J'ai connecter mes NRF24L01 sur 2 arduino uno comme vous l'avez indiqué,en reliant bien les pins A0 soit sur GND ou 5V. Ensuite j'ai téléchargé CoolTerm : j'ai ouvert 2 pages avec chacun un port différent ou est connecté l'un des arduino , mais je n'obtient que cela :

Oups ! J'ai oublié de précisé que j'ai évidement téléversé votre programme dans les 2 arduinos.

Merci beaucoup de votre aide ! :smiley:

Teryx:
Oups ! J'ai oublié de précisé que j'ai évidement téléversé votre programme dans les 2 arduinos.

oui je me doute vu qu'ils affichent bien leur rôle respectif, donc cette partie du code fonctionne

avez vous bien la dernière version de l'IDE ainsi que la dernière version de RF24 ?

avez vous un adaptateur 5V de NRF comme j'ai ?

on installe la radio dessus

c'est un petit module qui permet d'utiliser tranquillement les petits composants NRF que l'on trouve communément et qui sont en 3.3V et nécessitent donc une adaptation de tension et souvent aussi un coup de boost avec un condensateur sur l'alimentation

Non je n'ai pas l'adaptateur 5V mais je l'ai branché sur le 3.3V d'une extension bread bord :


Pardon je me suis trompé de capture, j'ai obtenu ceci :

Oui donc ça fonctionne pour l’un

à l’instabilité près - L’alimentation est elle fournie par un transfo ou en usb?

Si vous échangez les composants vous en avez toujours qu’un qui reçoit (et est-ce le même). Est-ce qu’ils ont chacun leur alim? Vous avez pensé à joindre les GND de l’Arduino et de l’alim?

La majorité des soucis que j’ai vu avec ces composants c’est quand l’alim est instable ou pas assez puissante.

Oui j'ai la dernière version d'arduino 1.8.5, et j'ai bien la dernière version d'RF24 .

J'ai remarqué que quand je déconnecte le pin MISO de l'arduino (rôle 1) il commence à écrit tout cela (voir capture) mais je ne sais pas pourquoi ?

Parce que la clock fonctionne et donc il voit que des bits à 0

Et pour mes autres questions?

L'alimentation est fournie par USB, et les 2 modules radio sont alimentés par le même 3.3V et j'ai bien relié les différentes masses.

Désolé je dois attendre 5 minutes entre chaque post.

Et ça alimente aussi les arduino?

Vous n’avez pas d’autres alims qui traînent (pour alimenter de manière plus puissante votre petit transfo) ou quelques condensateurs ?

Les arduinos sont alimentés par l'USB de l'ordinateur et j'ai une alimentation 9V 2A,12V ,3.3V mais je n'ai pas de condensateurs