Trois nodes NRF24L01 + arduino

Bonjour à tous,

Il y a quelques semaines que je rame avec la bibliothèque RF24 (fork amélioré), je connais "presque par coeur les différentes Doc, je lu des centaines de pages sur différents forums, pourtant je n'arrive pas au but !
Je souhaite juste faire une communication entre 3 noeuds dont un maitre qui envoie alternativement aux deux esclaves une demande qui répondent dans la foulé. Chaque esclave travaille sur des pipes differents. Pourtant je perds énormément de message (seul 60% réussissent ) voici le code du maitre :

#include <Arduino.h>
#include <SPI.h>
#include "nRF24L01.h"    //Définition des registres et espace adresse du nrf24l01
#include "RF24.h"        //Définition des fonctions utiles au nrf24l01
#include "printf.h"      //Définition du printf façon C
#ifndef CONFIG_H
#define CONFIG_H
#pragma once
#include "config.h"           //Définition des constantes pour le projet DomoFab
#endif

RF24 radio(CE, CSN);

const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL };
const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL };

byte nbSlave = 2;
uint8_t value[2] = {0, 0};
uint32_t timeRead; 
uint16_t nbAnswer[2];
uint16_t nbAsk[2];
boolean valueChange = false;
byte askMess[][6]={{6, 0, 100, 0, 0, 19},{6, 1, 100, 0, 0, 19}};
byte answerMess[32];

// the setup routine runs once when you press reset:
void setup() {                
  Serial.begin(57600);
  printf_begin();
  printf("DomoFab rRF24 MASTER start\n\n\r");  
// Setup and configure rf radio
  radio.begin();                          // Start up the radio
  radio.setCRCLength(RF24_CRC_8);
  radio.setAutoAck(true);                    // Ensure autoACK is enabled
  radio.setRetries(15,15);                // Max delay between retries & number of retries
  radio.startListening();                 // Start listening
  radio.printDetails();                   // Dump the configuration of the rf unit for debugging
  //radio.enableDynamicAck();

  printf ("\nConfiguration : MASTER\n\r");
  radio.openReadingPipe(1,talking_pipes[0]);
  radio.openReadingPipe(2,talking_pipes[1]);
  radio.openReadingPipe(3,talking_pipes[2]);
  radio.openReadingPipe(4,talking_pipes[3]);
  radio.openReadingPipe(5,talking_pipes[4]);
  timeRead = millis();
}

// the loop routine runs over and over again forever:
void loop() {
  
/****************** MASTER Role ***************************/
  if (abs(millis()-timeRead) > 500){
    timeRead = millis();
    for (byte slave = 0; slave < 2; slave++){           // Je scrutte tous les esclaves

      radio.openWritingPipe(listening_pipes[slave]);
      radio.stopListening();                                    // First, stop listening so we can talk.

      if (!radio.write(askMess[slave], 32)){
        printf("fail to send.\n\r");
      }
      nbAsk[slave]++;
      radio.startListening();                                    // Now, continue listening
   
      unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
      boolean timeout = false;                                   // Set up a variable to indicate if a response was received or not
      
      uint8_t pipe_num;      
      while ( ! radio.available(&pipe_num) ){                    // While nothing is received
        if (micros() - started_waiting_at > 200000 ){            // If waited longer than 200ms, indicate timeout and exit while loop
          timeout = true;
          break;
        }     
      }
        
      if ( timeout ){                                             // Describe the results
        printf("Failed, response timed out Slave %u\n", slave);
      }else{
        radio.read(answerMess, 32 );
        nbAnswer[slave]++;
      }
    }
    printf("slave 1 : %u/%u   slave 2 : %u/%u\n", nbAnswer[0], nbAsk[0], nbAnswer[1], nbAsk[1]);
  }
}

et celui des esclaves

#include <Arduino.h>
#include <SPI.h>
#include "nRF24L01.h"    //Définition des registres et espace adresse du nrf24l01
#include "RF24.h"        //Définition des fonctions utiles au nrf24l01
#include "printf.h"      //Définition du printf façon C
#ifndef CONFIG_H
#define CONFIG_H
#pragma once
#include "config.h"           //Définition des constantes pour le projet DomoFab
#endif

RF24 radio(CE, CSN);

const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL };
const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL };
byte askMess[32];
byte answerMess[][24]= {{24, 100, 0, 0, 19, 255, 255, 255, 255, 255, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},{24, 100, 1, 0, 19, 255, 255, 255, 255, 255, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};

// ???????????????????????????  Who am I ?????????????????????????????????????????????????????????????????????????????????????????????????????????????
//byte role = 0;
byte role = 1;
// ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(57600);
  printf_begin();
  printf("DomoFab rRF24 Slave n°: %u start\n\n\r", role);

  // initialize the digital pin as an output.
  radio.begin();                          // Start up the radio
  radio.setCRCLength(RF24_CRC_8);
  radio.setAutoAck(1);                    // Ensure autoACK is enabled
  radio.setRetries(15, 15);               // Max delay between retries & number of retries
  radio.printDetails();                   // Dump the configuration of the rf unit for debugging

  printf ("\nConfiguration : SLAVE\n\r");
  radio.openWritingPipe(talking_pipes[role]);
  radio.openReadingPipe(1, listening_pipes[role]);
  
  radio.startListening();                 // Start listening
}

// the loop routine runs over and over again forever:
void loop() {

/****************** Slave Role ***************************/
  if ( radio.available()) {
    while (radio.available()) {                                   // While there is data ready
      radio.read(askMess, 32);                     // Get the payload
    }
    //printf("Message reçu : ");
    //printMess(askMess);
    radio.stopListening();                                             // First, stop listening so we can talk
    while (!radio.write( answerMess[role], 32)){                         // Send NBMAXVALUE + HEAD + CRC.
      printf("fail to send.\n\r");
    }
    radio.startListening();                                            // Now, resume listening so we catch the next packets.
  }
}

Finalement rien de bien compliqué !

mais j'obtiens ce résultat :

DomoFab rRF24 MASTER start


STATUS		 = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	 = 0x3a3a3a3ad2 0xf0f0f0f0d2
RX_ADDR_P2-5	 = 0xc3 0xb4 0xa5 0x96
TX_ADDR		 = 0x3a3a3a3ad2
RX_PW_P0-6	 = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		 = 0x3f
EN_RXADDR	 = 0x3e
RF_CH		 = 0x4c
RF_SETUP	 = 0x07
CONFIG		 = 0x0b
DYNPD/FEATURE	 = 0x00 0x00
Data Rate	 = 1MBPS
Model		 = nRF24L01+
CRC Length	 = 8 bits
PA Power	 = PA_MAX

Configuration : MASTER

slave 1 : 1/1   slave 2 : 1/1
Failed, response timed out Slave 0
slave 1 : 1/2   slave 2 : 2/2
Failed, response timed out Slave 1
slave 1 : 2/3   slave 2 : 2/3
slave 1 : 3/4   slave 2 : 3/4
Failed, response timed out Slave 0
slave 1 : 3/5   slave 2 : 4/5
Failed, response timed out Slave 1
slave 1 : 4/6   slave 2 : 4/6
slave 1 : 5/7   slave 2 : 5/7
slave 1 : 6/8   slave 2 : 6/8
Failed, response timed out Slave 0
slave 1 : 6/9   slave 2 : 7/9
Failed, response timed out Slave 1
slave 1 : 7/10   slave 2 : 7/10
slave 1 : 8/11   slave 2 : 8/11
Failed, response timed out Slave 0
slave 1 : 8/12   slave 2 : 9/12
Failed, response timed out Slave 0
Failed, response timed out Slave 1
slave 1 : 8/13   slave 2 : 9/13
Failed, response timed out Slave 0
slave 1 : 8/14   slave 2 : 10/14
Failed, response timed out Slave 0
slave 1 : 8/15   slave 2 : 11/15
Failed, response timed out Slave 1
slave 1 : 9/16   slave 2 : 11/16
Failed, response timed out Slave 1
slave 1 : 10/17   slave 2 : 11/17
Failed, response timed out Slave 0
slave 1 : 10/18   slave 2 : 12/18
Failed, response timed out Slave 1
slave 1 : 11/19   slave 2 : 12/19
slave 1 : 12/20   slave 2 : 13/20
Failed, response timed out Slave 0

Avez vous une idée ?

Bonne journée

J'oubliais,

J'ai bien évidemment mis un condensateur pour éviter les problèmes d'alim du NRF24L01.

Personne n'a rencontré ce problème ?

code maitre: comment peux tu sortir de while ?

while ( ! radio.available(&pipe_num) )               // While nothing is received
      {                    
        if (micros() - started_waiting_at > 200000 )       // If waited longer than 200ms, indicate timeout and exit while loop
        {            
          timeout = true;
          break;
        }     
      }

il faudrait plutôt ceci

while ( ! radio.available(&pipe_num) && ! timeout )

dès que tu reçois qqchose, tu sors du while et tu tombes dans le if time out
alors que pour sortir du while, tu as bien reçu qqchose.

200ms est peut etre trop court

Bonjour,

Merci pour la réponse.

Pour sortir du while il y a "break", non ?

effectivement, je t'ai peut être dis une conn..ie, ce sont les accolades qui me perturbent

peux tu malgré tout faire un test en virant le break et en mettant la condition du time_out.

et peut etre en mettant 400ms pour voir

A vrai dire je suis déjà aller jusqu'à mettre une seconde !!

Et je suis sur que le while n'est pas bloquant, car comme tu peux le voir, dans les traces, il y a des échanges qui fonctionnent !!

Je ne sais pas ???

Personne n'a déjà eu ce problème ?

Bonjour

Lors de mes tests, je devais mettre au minimum la puissance d’émission, car les modules étaient trop proche les uns des autres.

J'ai du aussi changer le canal car celui par défaut était en plein dans la bande du WIFI. Dans les exemples de la lib, il y a un scanner qui te dit quelles bandes sont libre ou utilisé (J'ai pris 100)

A+

N'est-ce pas simplement un problème de "radio" ou de collisions ?
A quelle distance sont tes "slaves "?

J'ai moi aussi acheté 2 modules pour faire des essais que je n'ai pas encore pu mener à bien. J'ai lu pas mal de choses pas très glorieuses sur ces modules... :frowning:

Merci pour vos réponses,

caape:
Bonjour

Lors de mes tests, je devais mettre au minimum la puissance d’émission, car les modules étaient trop proche les uns des autres.

J'ai du aussi changer le canal car celui par défaut était en plein dans la bande du WIFI. Dans les exemples de la lib, il y a un scanner qui te dit quelles bandes sont libre ou utilisé (J'ai pris 100)

A+

Quand je regarde les traces du premier message, il a prit par défaut le chanel 4c = 76. Je vais essayer ce soir de mettre la puissance au minimum. Ce qui m'étonne c'est qu'avec un seul maître et un seul esclave tout fonctionne parfaitement, du coup le canal est libre ??

je vais testé le scanner aussi. Je vous tiens au courant.

tk5ep:
N'est-ce pas simplement un problème de "radio" ou de collisions ?
A quelle distance sont tes "slaves "?

J'ai moi aussi acheté 2 modules pour faire des essais que je n'ai pas encore pu mener à bien. J'ai lu pas mal de choses pas très glorieuses sur ces modules... :frowning:

Mes slaves sont très proches, mais je les interroges à tour de role.

Merci à tous les deux

Mes slaves sont très proches, mais je les interroges à tour de role.

Au début, je devais mettre le doigt sur l'un des module, je ne sais plus lequel, mais en faisant ceci, ca fonctionné a tous les coups. J'avais ouvert un fil a cette époque pour ce problème.
Baisser la vitesse a résolu le probleme.
Quand au canal, je ne recevais simplement rien. donc, ça ne doit pas etre ton cas.

Bon test

Bonsoir,

j'ai scanner pour constater que mon canal 0x4c était ok, j'ai quand même changé pour 0x70 pour être plus loin du bruit
J'ai aussi descendu la puissance au minimum et éloigné les modules
J'ai aussi mis le doigts sur le module !!

Rien n'y fait ??

Que faire ??

Quelques trucs bêtes.

As-tu essayé de permuter les modules ?

As-tu fait des essais avec un seul slave à la fois ?

As-tu testé un autre sketch avec un autre type de liaison ?

Tout ça pour éliminer les problèmes radio.

Tant que tu n'auras pas 100% de réussite avec une liaison point à point, ce n'est pas la peine d'aller plus loin.

Désole, je ne connais pas (encore) les NRF24L01.

Bon courage,

tk5ep:
Quelques trucs bêtes.

As-tu essayé de permuter les modules ?

As-tu fait des essais avec un seul slave à la fois ?

Oui j'ai essayer, j'ai aussi essayer de programmer avec une main dans le dos et sur un pied !!

Tant que tu n'auras pas 100% de réussite avec une liaison point à point, ce n'est pas la peine d'aller plus loin.

Désole, je ne connais pas (encore) les NRF24L01.

Bon courage,

en point à point ça marche bien !!

Merci :slight_smile:

OK,
Ca élimine déjà le problème du matériel.

je reste persuadé que ton problème est un problème de collision des paquets. Je ne rien au "pipes", mais j'ai cru comprendre que tout le trafic s'effectuait sur la même fréquence ?

Pour lever le doute, j'éloignerais un des esclaves afin que le champ reçu par le + proche écrase celui du plus éloigné.
Si tu reçois tous les paquets du + proche, ça confirmera le pb de collisions.

Après, je n'ai plus d'idée...

Je n'ai pas regardé ton code, ne connaissant pas ces modules.

Bon courage,

J'ai enfin obtenu quelque chose de bien !

slave 1 : 6338/6338 slave 2 : 6336/6338 : messages ok / total messages

J'ai changé autoAck(true) par autoAck(false) dans tous les sketches
j'utilise le canal 0x70 pour rester loin des canaux "noisy"
et j'ai mis la puissance aux mini setPALevel(RF24_PA_MIN)

Merci pour vos contributions, c'est un travail d'équipe !! :slight_smile:

Tant mieux !

Je reste persuadé que ton problème est (était) un problème de collisions. Tout le monde "cause" en même temps...

Je vais sortir mes modules, je suis proche de la fin d'écriture de mes principales fonctions de la station de base.

@+

bien :slight_smile:

tk5ep:
Tant mieux !

Je reste persuadé que ton problème est (était) un problème de collisions. Tout le monde "cause" en même temps...

Je vais sortir mes modules, je suis proche de la fin d'écriture de mes principales fonctions de la station de base.

@+

Bonjour,

Je pense effectivement que le autoAck = off à bien changé les choses ! J'ai l'impression que lorsqu'on écrit même sur deux pipes différents, un Ack est quand même envoyé ! d'ou les collisions et l'incompréhension générale.
Maintenant que ça fonctionne je vais essayer de faire d'autres tests.

we stay in touch.