fiabilite nRF24l01

bonsoir a tous,
depuis plusieurs jours je m'entraine à manipuler une paire de nRF24l10
j'ai utilisé les indication Carnet du Maker
j'ai un peu tout essayé et je suis arrivé à faire fonctionner l'ensemble.

le hic c'est que j'ai l'impression que la fiabilité n'est pas au rendez vous

j'ai modifié un de mes sketch pour remplacer le RF (avec virtualwire) par le nRF24l01

en réception j'ai inclus, pour vérifier l'intégralité des réception, un compteur d’émission.

et voici le resultat:

23:09:03.051 ->                              numero de l'envoi  898
23:09:03.098 ->                              Messages recuts    418
23:09:03.145 -> Nb de msg recut depuis le dernier RAZ 624
23:09:03.191 ->                              Pertes   480
23:09:03.238 ->                            % Pertes   53

53% de pertes en 15 minutes d’Émission!

c'est normal???

jusqu’à présent je n'ai pas trouvé le moyen de vérifier si une émission à bien été réalisée par le module..

j'avais cru comprendre que ces modules avait en hardware une vérification des émissions/réceptions..

le schéma de câblage:

j'ai réalisé les câblages avec des fils dupont de manière fiable et testée, pas de breadboard.

le code de l’émetteur (le setup et la fonction d'envoi)

void setup()
{
  //        ******                    Init du       nRF24L01              ****************

  Mirf.cePin = 9; // Broche CE sur D9
  Mirf.csnPin = 10; // Broche CSN sur D10
  Mirf.spi = &MirfHardwareSpi; // On veut utiliser le port SPI hardware
  Mirf.init(); // Initialise la bibliothèque

  Mirf.channel = 1; // Choix du canal de communication (128 canaux disponibles, de 0 à 127)
//  Mirf.payload = 32; // Taille d'un message (maximum 32 octets)
   Mirf.payload = 25; // Taille d'un message (maximum 32 octets)
  Mirf.config(); // Sauvegarde la configuration dans le module radio
 

  Mirf.setTADDR((byte *) "Poule"); // Adresse de transmission
  Mirf.setRADDR((byte *) "Salon"); // Adresse de réception
}

  //********************************   LCD   ************************************

  Wire.begin();    // init de I2C
  lcd.init();                          //   pour I2C
  lcd.begin(20, 4);                       //  initialise l ecran lcd 20*4 lignes
  lcd.backlight();                      //   pour I2C
  lcd.clear();
  tempo_rafrai = millis();
  Affiche_donnees_lcd();               //  affiche données sur lcd


 

/*****************   module de transmission d'info via RF   */


void trans_nRF24L01(byte choix_envois )
{
  static unsigned long num_de_l_envoi = 0;

  typedef struct
  {
    byte Controle1;             // code le la séquence e 0 à 255 arbitraire
    int tempo;                  // temporisaion entre chaque envoi, sert pour message d'attente /perte de supervision(fréquence d'envoi
    bool trappe_levee;          // trappe ouverte ou fermee?  info de l'etat de la trappe
    byte heure ;                //   heure, courante ou lever ou coucher du soleil suivant code sequence
    byte minutes ;              //    idem
    byte secondes;              //    idem
    float tension_batt;         //    tension batterie  on fait remonter l'info
    float tension_pv;           //    tension du PhotolVoltaique  idem
    byte alarme ;               //    Code de l'alarme locale (temperature, batterie, etc: 0 = RAS
    float Temperature;          // Temperature du ds3231
    unsigned long num_envoi;    //    numero de l'enregistrement
    byte Controle2;             //    code de controle de la séquence pas indispenssable permet avec un xor d'etre presque certain qe les infos sont ok

  } MaStructure;

  byte Year  ; // ******************   pour la mise à jour ****************
  byte Month  ;
  byte Date  ;
  byte DoW  ;
  byte Hour  ;
  byte Minute  ;
  byte Second  ;


  byte i = 0;  //    pour test
  //  unsigned long tempo = 1000ul + (590000 * !Etat_trappe1); // tempo 10 secondes le jour + 9min50sec la nuit
  // unsigned long tempo = 15000ul + (59000 * !Etat_trappe1); //  pour test
  unsigned long tempo = 1000ul ;//+ (59000 * !Etat_trappe1); //  pour test
  MaStructure message;
  MaStructure  messagebis;

  DateTime now = rtc.now();
  if (reboot || ((millis() - tempo_Trans >= tempo)))  // si reboot, on envoit les donnees immediatement, sinon apres la tempo
  { //   envoie toute les "tempo" milli secondes
    for (byte choix = 0; choix < 3; choix++)  //   on envoie les 3 series d'infos.
    {
      tempo_Trans = millis();
      if (debbug)
      {
        Serial.println("   TOP!!!  " ); // delay(1000);
        Serial.println("   Choix:  " );
        Serial.print(choix );
        delay(1000);
      }
      message.tempo = (tempo / 1000) ;
      message.trappe_levee = Etat_trappe1;
      message.Controle1 = choix;
      message.Temperature =  rtc.getTemperature() ;
      message.num_envoi = num_de_l_envoi;
      switch (choix) {
        case 0:
          message. heure = now.hour();
          message. minutes = now.minute() ;
          message.secondes = now.second();
          message. alarme = i;
          message. tension_batt =  tension_Batt ;
          message. tension_pv = tension_PV;
          message.Controle2 = (message.Controle1 xor  message.secondes);  // on fait un xor entre le code controle1 et les secondes
          //                                                             // on refait la meme operation à la reception pour verifier la coherence de la transmission
          break;

        case 1:
          message. heure =  Heure_lever. heure;
          message. minutes =  Heure_lever. minutes  ;
          message.secondes = Heure_lever. secondes;
          message. tension_batt =  tension_Batt ;
          message. tension_pv = tension_PV;
          message. alarme = i;
          message.Controle2 = (message.Controle1 xor message.secondes);
          break;

        case 2:
          message. heure =  Heure_coucher. heure;
          message. minutes = Heure_coucher. minutes  ;
          message.secondes = Heure_coucher. secondes;
          message. tension_batt =  tension_Batt ;
          message. tension_pv = tension_PV;
          message. alarme = i;
          message.Controle2 = (message.Controle1 xor message.secondes);
          break;


        default:
          // if nothing else matches, do the default
          // default is optional
          break;
      }


      Serial.print( " on envoi! : ");
      Mirf.send((byte*) &message); // On envoie le message
      while (Mirf.isSending()); // On attend la fin de l'envoi
 
      Serial.print( " Taille de la structure : ");        Serial.print( sizeof(message)); // Taille d'un message (maximum 32 octets)
      Serial.print( " / ");        Serial.println(Mirf.payload  );
      Serial.print( " Numéro de l'envoi: ");        Serial.println(message.num_envoi );
      num_de_l_envoi++;

       
      }
    }
  }
}

je met le code réception dans le post suivant

le code réception (nettoyé des choses inutiles ici)

/**
   version du 22/04/2020 01h
  test avec nRF24L01
  info ici:
  https://www.carnetdumaker.net/articles/communiquer-sans-fil-avec-un-module-nrf24l01-la-bibliotheque-mirf-et-une-carte-arduino-genuino/
  Exemple de code pour la bibliothèque VirtualWire – Client reception  de structure
  / *
   pins reservées SPI
   The Switch is connected to the GND and Pin 8 on the NANO

  The NRF24L01 pins:



  Module radio    Carte Arduino
  IRQ             D8 (ou non connecté, peu importe pour ce tutoriel)
  CE              D9
  CSN             D10
  MOSI            D11
  MISO            D12
  SCK             D13

  /
*/
// include the library code:

#include <SPI.h>      // Pour la communication via le port SPI    nRF24L01
#include <Mirf.h>     // Pour la gestion de la communication      nRF24L01 
#include <nRF24L01.h> // Pour les définitions des registres du nRF24L01
#include <MirfHardwareSpiDriver.h> // Pour la communication SPI    nRF24L01



#include <Wire.h>                       //  pour I2C
#include <LiquidCrystal_I2C.h>          //  avec I2C

LiquidCrystal_I2C lcd(0x27, 16, 2);      // declaration de l'afficheur


/**********************************************************/

//const byte ledpin = 5;
// bool ledState = HIGH;
bool premier_message = true;
unsigned long  chrono;
bool trappe;

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to


/************************************************/
typedef struct
{
  byte Controle1;             // code le la séquence e 0 à 255 arbitraire
  int tempo;                  // temporisaion entre chaque envoi, sert pour message d'attente /perte de supervision(fréquence d'envoi
  bool trappe_levee;          // trappe ouverte ou fermee?  info de l'etat de la trappe
  byte heure ;                //   heure, courante ou lever ou coucher du soleil suivant code sequence
  byte minutes ;              //    idem
  byte secondes;              //    idem
  float tension_batt;         //    tension batterie  on fait remonter l'info
  float tension_pv;           //    tension du PhotolVoltaique  idem
  byte alarme ;               //    Code de l'alarme locale (temperature, batterie, etc: 0 = RAS
  float Temperature;          // Temperature du ds3231
  unsigned long num_envoi;    //    numero de l'enregistrement
  byte Controle2;             //    code de controle de la séquence pas indispenssable permet avec un xor d'etre presque certain qe les infos sont ok

} MaStructure;

 

MaStructure message;
MaStructure messagebis;


byte num_message = 0;
unsigned long num_mess_recu = 0;

unsigned long derniere_reception;
unsigned long dernier_affichage;   //  pour eviter affichage trop rapide


int a = 0;
void setup()
{
  Wire.begin();                             // init de I2C
  Serial.begin(9600);
  lcd.init();                          //   pour I2C
  lcd.begin(16, 2);                       //  initialise l ecran lcd 20*4 lignes
  lcd.backlight();                      //   pour I2C
  lcd.clear();
  chrono = millis();
  lcd.setCursor(0, 0); // top left
  lcd.print("top setup ");
  //  pinMode(ledpin, OUTPUT);

  /************************************************************************/
  Mirf.cePin = 9; // Broche CE sur D9
  Mirf.csnPin = 10; // Broche CSN sur D10
  Mirf.spi = &MirfHardwareSpi; // On veut utiliser le port SPI hardware
  Mirf.init(); // Initialise la bibliothèque

  Mirf.channel = 1; // Choix du canal de communication (128 canaux disponibles, de 0 à 127)
  Mirf.payload = 25; // Taille d'un message (maximum 32 octets)
  // Mirf.payload = 32; // Taille d'un message (maximum 32 octets)

  Mirf.config(); // Sauvegarde la configuration dans le module radio
 
  
  Mirf.setTADDR((byte *) "Poule"); // Adresse de transmission
  Mirf.setRADDR((byte *) "Salon"); // Adresse de réception

  lcd.setCursor(0, 1);
  lcd.print("top loop");
   Serial.println( " fin du setup ");
  /************************************************************************/

}

 

void loop()
{
  static unsigned long premier_recu=0;

 

  lcd.setCursor(15, 0); lcd.print(millis(), 0);
  lcd.setCursor(0, 1); lcd.print( num_message);
  if (Mirf.dataReady())
  {
    Mirf.getData((byte*) &message); // Réception du paquet
 //   if (premier_recu==1) premier_recu=message.num_envoi;
    if (message.num_envoi<num_mess_recu) num_mess_recu=message.num_envoi;
    if (num_mess_recu == 1)
    {
                    num_mess_recu = message.num_envoi; 
                    premier_recu=message.num_envoi;
    }
                    else num_mess_recu++;
   

    derniere_reception = millis();
    Serial.print("                             numero de l'envoi "); Serial.println(message.num_envoi);
    Serial.print("                             Messages recuts  "); Serial.println(num_mess_recu);
     Serial.println("Nb de msg recut depuis le dernier RAZ"); Serial.println(message.num_envoi-premier_recu);
 
    
    Serial.print("                             Pertes   "); Serial.println(message.num_envoi - num_mess_recu);
    Serial.print("                           % Pertes   ");   Serial.println( map((message.num_envoi - num_mess_recu), 0, message.num_envoi, 0, 100));
    num_message = message.Controle1;
    transfert_reception(num_message);
    affiche_donnees();
    affiche_donnees_serial();

  } num_message++;
}
/***********     affichage manque transmission   ********************/

une idée?
je précise, les deux unos sont sur ma table à 1m l’un de l’autre mon pc portable entre les 2

1m cela peut être assez défavorable en réception radio : saturation probable.

J'ai essayé de reduire la puissance comme suggéré dans l'article

Bonus : diminuer la vitesse de communication pour augmenter la portée
Pour les personnes qui voudraient sacrifier de la vitesse au profit d'une portée plus grande, voici une petite ligne de code à mettre après Mirf.config() qui permet de passer le module radio à une vitesse de 250Kbps et une puissance de sortie de 0dBm (le maximum) :

1
Mirf.configRegister(RF_SETUP, 0x26); 
Avec cette configuration et une antenne de qualité, il est normalement possible d'atteindre des distances relativement longues.

N.B. Il est nécessaire d'ajouter cette ligne côté serveur et côté client(s). Si vous ajoutez cette ligne que d'un côté, la communication ne sera pas possible.

Mise à jour importante concernant les amateurs d'eBay et autres fournisseurs chinois :

Si votre module nRF24L01+ ne répond pas avec la ligne ci-dessus, essayez avec cette variante :

1
Mirf.configRegister(RF_SETUP, 0x07);

Mais quand je met une des deux instructions, plus rien ne fonctionne (la même dans les 2 sketchs bien sur)

Peut être essayer setPALevel() pour diminuer la puissance ?

hbachetti:
1m cela peut être assez défavorable en réception radio : saturation probable.

effectivement tu as raison!!

j'ai glissé un des émetteurs dans une pochette anti-statique et là, hooo miracle ca fonctionne!!!!
plus d'erreurs!!

00:32:49.007 ->                              numero de l'envoi 1617
00:32:49.054 ->                              Messages recuts  1616
00:32:49.101 -> Nb de msg recut depuis le dernier RAZ 1445
00:32:49.148 ->                              Pertes   1
00:32:49.195 ->                            % Pertes   0

comment faire pour limiter la puissance de sortie?

hbachetti:
Peut être essayer setPALevel() pour diminuer la puissance ?

j'ai trouvé des infos..

j'ai inséré cette ligne :

  Mirf.setPALevel(POWER[0]);    // POWER[0] = RF24_PA_MIN, [1] = LOW, [2] = HIGH

mais raté!
le compilateur n'est pas content..

'class Nrf24l' has no member named 'setPALevel'

si je comprends bien, la bibliothèque Mirf ne connais pas setPALevel...

par acquis de conscience une partie du code setup :

Mirf.cePin = 9; // Broche CE sur D9
  Mirf.csnPin = 10; // Broche CSN sur D10
  Mirf.spi = &MirfHardwareSpi; // On veut utiliser le port SPI hardware
  Mirf.init(); // Initialise la bibliothèque

  Mirf.channel = 1; // Choix du canal de communication (128 canaux disponibles, de 0 à 127)
  Mirf.payload = 25; // Taille d'un message (maximum 32 octets)
   

  Mirf.setPALevel(POWER[0]);    // POWER[0] = RF24_PA_MIN, [1] = LOW, [2] = HIGH

  Mirf.config(); // Sauvegarde la configuration dans le module radio

//  Mirf.configRegister(RF_SETUP, 0x26); 
//  Mirf.configRegister(RF_SETUP, 0x07);
//  Mirf.setPALevel(POWER[0]);    // POWER[0] = RF24_PA_MIN, [1] = LOW, [2] = HIGH

  Mirf.setTADDR((byte *) "Poule"); // Adresse de transmission
  Mirf.setRADDR((byte *) "Salon"); // Adresse de réception

il y aurais une autre solution?

ou alors je n'utilise pas la bonne bibliothèque?
si c'est le cas une autre a me conseiller ou un site ?
je e sis rendu compte qu'il y avait d'autre bibli mais je n'ais pas envie de partir dans tous les sens...

merci
bonne nuit
a demain

Edit:

je viens de voir que tu a fait un tuto a ce sujet... je vais le potasser et voir la bibli RF24.

merci en tout cas

Bonjour,

Le piège de la distance trop faible durant les tests est classique, je l'ai moi aussi vécu...

J'utilise la biliothèque rf24 et il y a des options pour diminuer la puissance.

hbachetti:
Peut être essayer setPALevel() pour diminuer la puissance ?

+1 : effectivement, librairie RF24.

Bonsoir a tous.
Bon j'ai installé la librairie rf24, pas de soucis.
Installé 2 sketchs style ping pong,
Puissance a fond,ben.. portée minables, a pres de 20m il ne recevait plus rien...

J'utilise ces modules nRF24L01+

Évidemment j'utilise les modules avec l'adaptation de tension..

Les modules avec antenne sont ils meilleurs ?

J'ai 50m a franchir maxi avec une haie.en plus en contre-bas.
Le pire c'est qu'avec des modules rf433 de ce genre
Ca passe tres bien... mais dans un seul sens.

Petite question complémentaire, possible de faire fonctionner 1 couple de rf433 sur chaque uno pour faire du bi directionnel ?
Le wifi on oublie aussi
Merci

Bonsoir,

J'utilise des modules avec antenne type rubber duck ( petit cylindre noir). Cela dit, la portée reste faible dès lors qu'il y a des obstacles. Je suis quand même étonné qu'une haie te pose un problème.

Personnellement j'utilise ces modules pour des distances très courtes, environ 30 mètres presqu'à vue et là ça marche.

Pour des distances plus grandes (avec obstacles massifs) j'ai basculé sur esp32 avec le chip sx1276 travaillant à 868 MHz.

Plus tu baisses la fréquence, plus l'onde diffracte (diffuse) et donc est susceptible d'être captée (ce n'est pas le seul critère, l'absorption dans la matière joue un rôle important aussi.)

Bonjour,
J'ai récupéré un lot de nRF24L01 pa lna

nRF24L01-PA-LNA-External-Antenna-Wireless-Transceiver-Module.png

Testé et validé!!

Donc ca marche sur mes 40metres de distance, je continue donc mon projet qui avance.

Merci

nRF24L01-PA-LNA-External-Antenna-Wireless-Transceiver-Module.png