Recevoir et dissocier les données de deux nrf24

Bonjour,

Je rencontre un nouveau soucis : j'utilise deux nrf24 qui émettent des données : l'un une structure, et l'autre une trame (chaine de caractère).

Malgré un grand nombre d'essais, je n'arrive à savoir si le message reçu provient de l'un ou de l'autre nrf24.

J'ai vu le sujet : https://forum.arduino.cc/t/nrf24-lire-deux-adresses-de-transmetteurs-en-meme-temps/498190/6
mais j'ai du rater quelque chose car impossible de reproduire ce qui à été proposé.

Voici le code qui fonctionne pour l'émetteur 1 seul:


#include <SPI.h>
#include <RF24.h>
#include <Wire.h>
#include "rgb_lcd.h"
#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit le "nom de tunnel" (5 caractères) à travers lequel on va recevoir les données de l'émetteur

rgb_lcd lcd;

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;       // Mise au format "byte array" du nom du tunnel
char message[32];
char AncienMessage[32];     // Avec cette librairie, on est "limité" à 32 caractères par message
const int buttonPin = 2;
int buttonState = 0;
bool etat =  false; 
long heure1 = 0;
long ancienneHeure1 = 0;
long heure2 = 0;
long ancienneHeure2 = 0;
struct mesures {
    int CO2;
    long COV;
    float TEMPERATURE;
    int HUMIDITE;    
    byte hh;
    byte mm;
    byte ss;
    int PERIODE;
    byte STRUCTURE;
    byte POLBOX;
}mesures;
String conca = "";
byte complete = 0;

#include <ChainableLED.h>

#define NUM_LEDS  1

ChainableLED leds(4, 5, NUM_LEDS); //conecter sur D2 et D3

void setup() {
  // Initialisation du port série (pour afficher les infos reçues, sur le "Moniteur Série" de l'IDE Arduino)
  Serial.begin(9600);

  lcd.begin(16, 2);
  // Partie NRF24
  radio.begin();                      // Initialisation du module NRF24
  radio.openReadingPipe(0, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MAX);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.startListening();             // Démarrage de l'écoute du NRF24 (signifiant qu'on va recevoir, et non émettre quoi que ce soit, ici)
  pinMode(buttonPin, INPUT);
  leds.setColorRGB(0, 255, 0, 0);

}

void loop() {
  
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH){
    etat = !etat;
    if (etat == false){
       leds.setColorRGB(0, 255, 0, 0);
       Serial.println("stop");
       }
    else{
      leds.setColorRGB(0, 0, 255, 0);
       Serial.println("start");
    }
  delay(300);
  }
  if (etat == false) return;


  // On vérifie à chaque boucle si un message est arrivé
  if (radio.available()) {
    radio.read(&mesures, sizeof(mesures)); 
    // Si un message vient d'arriver, on le charge dans la variable "message"
    //if(sizeof(mesures) != mesures.STRUCTURE) return;
    
    
    conca = "P";
    conca.concat(mesures.POLBOX);
    conca.concat(" ");
    conca.concat(mesures.hh);
    conca.concat(":");
    conca.concat(mesures.mm);
    conca.concat(":");
    conca.concat(mesures.ss);
    conca.concat(" ");
    conca.concat(mesures.TEMPERATURE);
    conca.concat(" ");
    conca.concat(mesures.HUMIDITE);
    conca.concat(" ");
    conca.concat(mesures.CO2);
    conca.concat(" ");
    conca.concat(mesures.COV);
    conca.concat(" ");
    int length = conca.length();
    conca.concat(length);
    Serial.println(conca);     // … et on l'affiche sur le port série !
  }

}

et je récupère sur le moniteur série :

start
P2 2:34:38 25.70 43 933 29 27

et le second code pour l'émetteur 2 seul:

#include <SPI.h>
#include <RF24.h>

#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel2  "PIPE2"       // On définit le "nom de tunnel" (5 caractères) à travers lequel on va recevoir les données de l'émetteur

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse2[6] = tunnel2;       // Mise au format "byte array" du nom du tunnel
char message[32];                     // Avec cette librairie, on est "limité" à 32 caractères par message

void setup() {
  // Initialisation du port série (pour afficher les infos reçues, sur le "Moniteur Série" de l'IDE Arduino)
  Serial.begin(9600);
  Serial.println("Récepteur NRF24L01");
  Serial.println("");

  // Partie NRF24
  radio.begin();                      // Initialisation du module NRF24
  radio.openReadingPipe(0, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MAX);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.startListening();             // Démarrage de l'écoute du NRF24 (signifiant qu'on va recevoir, et non émettre quoi que ce soit, ici)
}

void loop() {
  // On vérifie à chaque boucle si un message est arrivé
  if (radio.available()) {
    radio.read(&message, sizeof(message));                        // Si un message vient d'arriver, on le charge dans la variable "message"
    Serial.print("Message reçu : "); Serial.println(message);     // … et on l'affiche sur le port série !
  }
}

avec le retour suivant sur le moniteur série :

Récepteur NRF24L01

Message reçu : P1 2:40:7 297 35 596 53 24

Ce que je voudrai faire donc : c'est traiter dans un seul et même programme le message en structure (programme1) s'il provient de l'émetteur 1 et le traiter en chaine de caractère (programme2), s'il provient de l'émetteur 2.

Merci d'avance pour votre aide.

Vous allez recevoir un "payload" sous format binaire. stockez le de manière indifférenciée dans un tableau d'octets. Ensuite à vous de vous débrouiller pour analyser ce payload pour décider si c'est une structure ou si c'est une chaîne. le premier octet envoyé pourrait être un indicateur par exemple (si vous avez le contrôle des 2 émetteurs).

Si c'est une chaîne, vous pouvez directement traiter le payload et l'analyser, si c'est la structure, vous faites un memcpy() dans une variable de type de la structure pour initialiser correctement chaque attribut. (il serait bon de définir votre structure avec l'attribut ((packed)) pour éviter des optimisations du compilateur.

Sinon pourquoi ne pas envoyer dans les 2 cas sous forme de chaîne de texte ?

il y a des exemples d'envoi de structure dans la Liste de tutos divers

Merci pour votre réponse.
En effet, un indicateur sur le premier octet serait une solution simple et efficace.
Je me demandais: on défini un "pipe" pour la communication entre deux modules.
Un module peux avoir plusieurs "pipe" ouverts en même temps.
Donc comment peut-on alors effectuer l'analyse de la structure si on reconnait le "pipe1" et l'analyse de la trame si on reconnait le "pipe2".

Pouvez-vous m'expliquer un peu plus en détail la définition attribut? (je ne connais pas)

oui vous pourriez différencier la communication aussi en fonction de l'émetteur . au lieu de juste appeler available() sur la radio (ce qui écoute tous les pipes ouverts), vous pourriez tester quel pipe est en réception en passant un pointeur qui contiendra le N° du pipe à la fonction available()

bool RF24::available ( uint8_t * pipe_num )
Test whether there are bytes available to be read.
Use this version to discover on which pipe the message arrived.
Parameters:
[out] pipe_num Which pipe has the payload available
Returns:
True if there is a payload available, false if none is

https://maniacbug.github.io/RF24/classRF24.html#ace7dd139fabc16b77cb8325faa07620f

J'ai fais plusieurs essais, toujours sans succès, je n'arrive pas à déterminer de quel émetteur il s'agit :
PB1:

  radio.openReadingPipe(xxx, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.openReadingPipe(xxx, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné

je n’ai pas compris ce qu'attendais le compilateur à la place des xxx. En mettant 0 et 1 je ne reçois que l'émetteur 2 en faisant le contraire, je ne reçois que l'émetteur 1 et en mettant 0 pour les deux c'est à nouveau l'émetteur 2.

PB2:

  if (radio.available(pipe_num)) {
    Serial.println(pipe_num);
    }

retourne sur le moniteur série systématiquement 0.

Si vous pouvez m'éclairer. je remets les trois codes complets:

émetteur 1 :

#include <SPI.h>
#include <RF24.h>

#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;               // Mise au format "byte array" du nom du tunnel
const char message[] = "Hello World !!!";     // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

void setup() {
  radio.begin();                      // Initialisation du module NRF24
  radio.openWritingPipe(adresse);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.stopListening();              // Arrêt de l'écoute du NRF24 (signifiant qu'on va émettre, et non recevoir, ici)
}

void loop() {
  radio.write(&message, sizeof(message));     // Envoi de notre message
  delay(1000);                                // … toutes les secondes !
}

émetteur 2 :

#include <SPI.h>
#include <RF24.h>

#define pinCE   D7             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  D8             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel2  "PIPE2"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse2[6] = tunnel2;               // Mise au format "byte array" du nom du tunnel
const char message[] = "Hello  !!!";     // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

void setup() {
  radio.begin();                      // Initialisation du module NRF24
  radio.openWritingPipe(adresse2);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.stopListening();              // Arrêt de l'écoute du NRF24 (signifiant qu'on va émettre, et non recevoir, ici)
}

void loop() {
  radio.write(&message, sizeof(message));     // Envoi de notre message
  delay(1000);                                // … toutes les secondes !
}

récepteur:

#include <SPI.h>
#include <RF24.h>
uint8_t  pipe_num;
#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit le "nom de tunnel" (5 caractères) à travers lequel on va recevoir les données de l'émetteur
#define tunnel2  "PIPE2"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;       // Mise au format "byte array" du nom du tunnel
const byte adresse2[6] = tunnel2;               // Mise au format "byte array" du nom du tunnel
char message[32];                     // Avec cette librairie, on est "limité" à 32 caractères par message

void setup() {
  // Initialisation du port série (pour afficher les infos reçues, sur le "Moniteur Série" de l'IDE Arduino)
  Serial.begin(9600);
  Serial.println("Récepteur NRF24L01");
  Serial.println("");

  // Partie NRF24
  radio.begin();                      // Initialisation du module NRF24
  radio.openReadingPipe(0, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.openReadingPipe(0, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.startListening();             // Démarrage de l'écoute du NRF24 (signifiant qu'on va recevoir, et non émettre quoi que ce soit, ici)
}

void loop() {
  // On vérifie à chaque boucle si un message est arrivé
  if (radio.available(pipe_num)) {
    Serial.println(pipe_num);
    radio.read(&message, sizeof(message));                        // Si un message vient d'arriver, on le charge dans la variable "message"
    Serial.print("Message reçu : "); Serial.println(message);     // … et on l'affiche sur le port série !
  }
}

Le N° que l'on désire attribuer au pipe : 1 à 5.

La méthode attend une adresse :

bool RF24::available	(	uint8_t * 	pipe_num	)

donc :

  if (radio.available(&pipe_num)) {

Merci pour votre réponse, il y a du progrès!

  if (radio.available(&pipe_num)) {
    Serial.println(pipe_num);

retourne bien le numéro correspondant (1 ou 2).

Mais en mettant:

  radio.openReadingPipe(1, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.openReadingPipe(2, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné

le moniteur série affiche :

2
Message reçu : Hello World !!!

et en mettant:

  radio.openReadingPipe(1, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  //radio.openReadingPipe(2, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné

le moniteur série affiche :

1
Message reçu : Hello World !!!

Je n'arrive donc pas à recevoir les deux en même temps.

Le code des deux émetteurs est-il bien différent ?
C'est facile de se tromper dans ce genre de manip.

Essayer d'abord d'envoyer alternativement, un émetteur après l'autre, dans le but de vérifier que le principe est OK.
Augmenter fortement le delay(1000), brancher le premier, puis le deuxième.

vous avez raison, en faite on ne reçoit pas ce qui provient de l'émetteur2.
en émettant sur le même pipe, ça fonctionne:

2
Message reçu : Hello  !!!
2
Message reçu : Hello World !!!
2
Message reçu : Hello  !!!
2
Message reçu : Hello World !!!

pourriez vous m'indiquer comment modifier mon code pour émettre sur deux pipe différent (1 pour l'émetteur 1 et 1 autre pour l'émetteur 2 bien sûr) et recevoir le tout sur le même récepteur.
émetteur 1:

#include <SPI.h>
#include <RF24.h>

#define pinCE   26             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  31             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;               // Mise au format "byte array" du nom du tunnel
const char message[] = "Hello World !!!";     // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

void setup() {
  radio.begin();                      // Initialisation du module NRF24
  radio.openWritingPipe(adresse);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.stopListening();              // Arrêt de l'écoute du NRF24 (signifiant qu'on va émettre, et non recevoir, ici)
}

void loop() {
  radio.write(&message, sizeof(message));     // Envoi de notre message
  delay(1000);                                // … toutes les secondes !
}

émetteur2:

#include <SPI.h>
#include <RF24.h>

#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D9 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D10 de l'arduino
#define tunnel  "PIPE1"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;               // Mise au format "byte array" du nom du tunnel
const char message[] = "Hello  !!!";     // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

void setup() {
  radio.begin();                      // Initialisation du module NRF24
  radio.openWritingPipe(adresse);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.stopListening();              // Arrêt de l'écoute du NRF24 (signifiant qu'on va émettre, et non recevoir, ici)
}

void loop() {
  radio.write(&message, sizeof(message));     // Envoi de notre message
  delay(1000);                                // … toutes les secondes !
}

récepteur:

#include <SPI.h>
#include <RF24.h>
uint8_t  pipe_num;
#define pinCE   9             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  10             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit le "nom de tunnel" (5 caractères) à travers lequel on va recevoir les données de l'émetteur
#define tunnel2  "PIPE2"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;       // Mise au format "byte array" du nom du tunnel
const byte adresse2[6] = tunnel2;               // Mise au format "byte array" du nom du tunnel
char message[32];                     // Avec cette librairie, on est "limité" à 32 caractères par message

void setup() {
  // Initialisation du port série (pour afficher les infos reçues, sur le "Moniteur Série" de l'IDE Arduino)
  Serial.begin(9600);
  Serial.println("Récepteur NRF24L01");
  Serial.println("");

  // Partie NRF24
  radio.begin();                      // Initialisation du module NRF24
  radio.openReadingPipe(1, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.openReadingPipe(2, adresse2);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.startListening();             // Démarrage de l'écoute du NRF24 (signifiant qu'on va recevoir, et non émettre quoi que ce soit, ici)
}

void loop() {
  // On vérifie à chaque boucle si un message est arrivé
  if (radio.available(&pipe_num)) {
    Serial.println(pipe_num);
    radio.read(&message, sizeof(message));                        // Si un message vient d'arriver, on le charge dans la variable "message"
    Serial.print("Message reçu : "); Serial.println(message);     // … et on l'affiche sur le port série !
  }
}

C'est un retour en arrière. Si l'on appelle les deux émetteurs PIPE1, on ne saura pas les différencier.

En effet, mais au moins le message est reçu. avec ce code, pour l'émetteur2, le récepteur n'affiche rien.

#include <SPI.h>
#include <RF24.h>

#define pinCE   26             // On associe la broche "CE" du NRF24L01 à la sortie digitale D7 de l'arduino
#define pinCSN  31             // On associe la broche "CSN" du NRF24L01 à la sortie digitale D8 de l'arduino
#define tunnel2  "PIPE2"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse2[6] = tunnel2;               // Mise au format "byte array" du nom du tunnel
const char message[] = "Hello World !!!";     // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

void setup() {
  radio.begin();                      // Initialisation du module NRF24
  radio.openWritingPipe(adresse2);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // Sélection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.stopListening();              // Arrêt de l'écoute du NRF24 (signifiant qu'on va émettre, et non recevoir, ici)
}

void loop() {
  radio.write(&message, sizeof(message));     // Envoi de notre message
  delay(1000);                                // … toutes les secondes !
}

Il faut essayer de creuser un peu. Un émetteur à la fois.

je referais des essais prochainement

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.