blocage communications avec NRF24L01+

Bonjour,

J'ai un programme d'essai qui fait dialoguer 2 cartes Mega 2560 branchées sur 2 PC dans la même pièce. Les transceivers sont alimentés en 3 volts régulé. Sur le 1er PC : 1 carte avec NRF24L01+ J'entre un code dans le moniteur série, le programme envoie un payload de 8 octets incluant ce code qui va être exécuté sur le second (éclairage/extinction de led) Le code envoyé est affiché sur le moniteur, ainsi que les messages reçus. Sur le second PC : 1 carte avec NFR24L01+ , des led, un bouton poussoir. Le moniteur affiche les commandes reçues. Si j'appuye sur un bouton, il en informe le 1er PC.

Au départ, ça fonctionne. Plusieurs messages successifs partent du 1er et sont exécutés sur le second.

Après appui sur le bouton, le 1er reçoit bien l'information mais ensuite ce qu'il envoie n'est pas reçu par le second. Les appuis sur le bouton du second continuent à être annoncés.

Après reset de la seconde platine, ça remarche...ou pas.

Il semble donc qu'après un envoi, la seconde platine ne sait plus recevoir.

Merci à ceux qui ont une idée

Sans code pas de solution possible.

#include <BouleDeCristal.h>

Ç’aurait pu être un problène connu. Voici le code .

programme du 1er PC :

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
byte messageAller[]  = "12345678";
byte messageRetour[] = "98765432";
char recu[12];
String reponse;
void litConsigne(void);
byte  i  ;

void setup(){
  Serial.begin(9600); 
  Mirf.cePin  = 48;
  Mirf.csnPin = 49;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();

  //  canal et payload doivent être identiques aux 2 modules
  Mirf.channel = 12; 
  Mirf.payload = 8 ; 
  Mirf.setTADDR((byte *)"serv1");
  Mirf.setRADDR((byte *)"clie1");
  Mirf.config();
 // Mirf.configRegister(RF_SETUP, 0x26);
  Serial.println("Programme Dec13_Client_Mega du 7/12/2013."); 
  Serial.println("Init Ok...");
}

void loop(){
  //  regarder si une consigne vient du moniteur
  if (Serial.available())
    litConsigne();
  
  //  regarder si on a reçu un message d'un client
  if (Mirf.dataReady() ) {
    Mirf.getData((byte *) &messageRetour); 
    Serial.print("On a recu : ");
    for ( int i = 0 ; i<8 ; i++) {
      Serial.write(messageRetour[i]);  
    } 
    Serial.println();
    Serial.println("----------------------------------");
  }
}

void litConsigne()  {
  reponse = "Consigne : " ;
  i = 0 ;
  while ( Serial.available()>0 )   {
     recu[i] = Serial.read();
     reponse += recu[i];
     i++;
     delay(100);
  }
  if (i>0) {
     Serial.println(reponse + ".");
     /*  format du message à envoyer : 
     -  numero du plot concerné (6 = tous)
     -  J pour allumer led jaune, K pour l'éteindre  */
    messageAller[0] = recu[0] ;
    messageAller[1] = toupper(recu[1]) ;
    messageAller[2] = recu[2] ; 
    messageAller[3] = '\0' ; 
         
    Mirf.send((byte *)&messageAller);    // valeur que l'on veut envoyer
    Serial.print("On envoie : " );
    for ( int i = 0 ; i<8 ; i++) {
      Serial.write(messageAller[i]);  
    } 
    Serial.println();
    while(Mirf.isSending()){ 
      //  on attend la fin de l'envoi
    }  
    Serial.println("Envoi Ok");
  }
}

et voici le second :

void loop(){
  // attend en permanence un message du client ou une interruption hard
  if (Mirf.dataReady() ) {
    Mirf.getData((byte *) &messageClient); 
    Serial.print("On a recu : ");
    for ( int i = 0 ; i<8 ; i++) {
      Serial.write(messageClient[i]);  
    } 
    Serial.println();
    Serial.println("----------------------------------");
    // est-on concerné ?
    if ((messageClient[0]== '1') || (messageClient[1]=='6')){
       traiteMessage();
    }
  }  
}
  
void traiteMessage()  {
  Serial.print("On a recu : ");
  Serial.write(messageClient[1]);
  if ( !enabled && (messageClient[1] != 'E') )
    return;
  switch (messageClient[1])  {
    case 'J' :
      digitalWrite(ledJaune, HIGH);
      break;
    case 'K' :
      digitalWrite(ledJaune, LOW);
      break;
    case 'V' :
      digitalWrite(ledVerte, HIGH);
      break;
    case 'W' :
      digitalWrite(ledVerte, LOW);
      break;
    case 'E' :
      enabled = true ;
      break;
    case 'D' :
      enabled = false ;
      break;
    case '0' :
      afficheNombre();
  }
}  
  
void afficheNombre()  {
  //  on affichera le nombre sur les 7-seg
  byte nbre = messageClient[2];
  messageRetourAffich[7] = nbre;
  
  Mirf.send((byte *)&messageRetourAffich);    
}

void bouton()  {
  // on alerte immédiatement le client
  if ( ! enabled) return;
  Mirf.send((byte *)&messageRetourAppui);    
  digitalWrite(ledJaune, LOW);
  digitalWrite(ledVerte, HIGH);
}

Déjà le deuxième code n'est pas complet ...

Dans le premier : toupper(recu[1]) ==> ???

Sur le pc n°2 il serait interessant de voir s'il y a bien quelque chose de reçu :

if ((messageClient[0]== '1') || (messageClient[1]=='6')){
Serial.println("Message correct");
       traiteMessage();
    } else Serial.println("Message incorrect");

Déjà on saurait plus précisément où se situe le problème

Bonjour,

Pas de code, pas de chocolat :wink:

B@tto:
#include <BouleDeCristal.h>

// Black magic here

skywodd:

B@tto:
#include <BouleDeCristal.h>

// Black magic here

En argument à l’instanciation :wink:

[quote author=B@tto link=topic=204269.msg1504260#msg1504260 date=1386853600]
Déjà le deuxième code n'est pas complet ...

Dans le premier : toupper(recu[1]) ==> ???

le deuxième attend une lettre majuscule pour le switch

B@tto:
Sur le pc n°2 il serait interessant de voir s’il y a bien quelque chose de reçu :

if ((messageClient[0]== '1') || (messageClient[1]=='6')){

Serial.println(“Message correct”);
       traiteMessage();
    } else Serial.println(“Message incorrect”);




Déjà on saurait plus précisément où se situe le problème

Entre temps, j’avais mis un else mais c’est pareil. Et ça ne servira que plus tard. Actuellement j’envoie “1” en début de presque tous mes envois.

voici la nouvelle moûture du deuxième.
pour info, à terme il existera en plusieurs exemplaires. “1” sera celui-ci., “2” à “5” les autres et “6” une consigne globale pour tous. Mais d’ici là ce sera sans moniteur, sur alim, et avec des ProMini.

/*              DEC13_PLOT1
      gère le plot n°1 en liaison avec DEC13_client_mega

* Pour le MEGA2560
* Pins:
* Hardware SPI:
* MISO -> 50      * MOSI -> 51    * SCK -> 52
* CE -> 48        * CSN -> 49
* GND -> GND      * VCC -> 3.3v        */

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
byte messageRetourAffich[] = "nbre :  ";
byte messageRetourAppui[]  = "Bouton 1";
byte messageClient[] = "98765432";
//char recu[12];
String reponse;
const byte ledJaune=4;
const byte ledVerte=5;
boolean enabled = true ;
boolean moi = false;
void litConsigne(void);
void bouton(void);
void traiteMessage(void) ;


void setup(){
  pinMode(ledJaune, OUTPUT);
  pinMode(ledVerte, OUTPUT);
  Serial.begin(9600); 
  attachInterrupt(0, bouton, RISING);
  Mirf.cePin  = 48;
  Mirf.csnPin = 49;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();

  //  canal et payload doivent être identiques aux 2 modules
  Mirf.channel = 12; 
  Mirf.payload = 8 ; 
  Mirf.setTADDR((byte *)"serv1");
  Mirf.setRADDR((byte *)"clie1");
  Mirf.config();
 // Mirf.configRegister(RF_SETUP, 0x26);
  Serial.println("Programme Dec13_Client_Mega du 7/12/2013."); 
  Serial.println("Init Ok...");
}

void loop(){
  // attend en permanence un message du client ou une interruption hard
  if (Mirf.dataReady() ) {
    Mirf.getData((byte *) &messageClient); 
    Serial.print("On a recu : ");
    for ( int i = 0 ; i<8 ; i++) {
      Serial.write(messageClient[i]);  
    } 
    Serial.println();
    // est-on concerné ?
    if ((messageClient[0]== '1') || (messageClient[0]=='6')){
      moi = true;
      traiteMessage();
    }
    else
      Serial.println("Ce n'est pas pour moi.");
  }  
}
  
void traiteMessage()  {
  if ( !enabled && (messageClient[1] != 'E') )  {
    Serial.println("On ne traite pas");
    Serial.write(messageClient[1]);
    Serial.println("");
    Serial.println("----------------------------------");
    return;
  }
  Serial.print("On traite : ");
  Serial.write(messageClient[1]);
  Serial.println("");
  Serial.println("----------------------------------");
  switch (messageClient[1])  {
    case 'J' :
      digitalWrite(ledJaune, HIGH);
      break;
    case 'K' :
      digitalWrite(ledJaune, LOW);
      break;
    case 'V' :
      digitalWrite(ledVerte, HIGH);
      break;
    case 'W' :
      digitalWrite(ledVerte, LOW);
      break;
    case 'E' :
      enabled = true ;
      break;
    case 'D' :
      enabled = false ;
      break;
    case '0' :
      afficheNombre();
  }
  moi = false;
}  
  
void afficheNombre()  {
  //  on affichera plus tard le nombre sur des 7-seg
  byte nbre = messageClient[2];
  messageRetourAffich[7] = nbre;
  
  Mirf.send((byte *)&messageRetourAffich);    
}

void bouton()  {
  // on alerte immédiatement le client
  if ( ! enabled) return;
  Mirf.send((byte *)&messageRetourAppui);    
  digitalWrite(ledJaune, LOW);
  digitalWrite(ledVerte, HIGH);
}

Bonsoir,

B@tto:
#include <BouleDeCristal.h>

J’aimerai bien tester cette librairie où peut-on la télécharger ?
]:smiley:

micol:
Entre temps, j’avais mis un else mais c’est pareil. Et ça ne servira que plus tard. Actuellement j’envoie “1” en début de presque tous mes envois.

Oui mais ça ne nous dit pas si tu as bien “Ce n’est pas pour moi.” dans ton moniteur série ou bien si traiteMessage() est bien lancé …

icare:
Bonsoir,

B@tto:
#include <BouleDeCristal.h>

J’aimerai bien tester cette librairie où peut-on la télécharger ?
]:smiley:

www.666deviliscoming.org

B@tto: Oui mais ça ne nous dit pas si tu as bien "Ce n'est pas pour moi." dans ton moniteur série ou bien si traiteMessage() est bien lancé

Tant que ça fonctionne, j'ai bien l'un ou l'autre.

Mais je n'ai plus ni l'un ni l'autre après qu'un message soit parti du second vers le premier. Ce message pouvant être l'annonce de l'appui sur le bouton ou bien l'accusé de réception d'un nombre à afficher.

ok donc déjà on cible un peu plus où est l'erreur. Je suppose que ça a été corrigé mais entre le programme du PC n°1 que tu as donné et et le dernier du n°2, les adresses ne correspondent pas, c'est les même pour les deux :

Mirf.setTADDR((byte *)"serv1"); Mirf.setRADDR((byte *)"clie1");

Sinon je vois que la variable enabled qui pourrait poser problème, vire la des conditions pour voir

Il y avait bien cette erreur d'adresse mais elle est sans conséquence : deux NRF24L01 qui ont la même R adresse discutent entre eux. J'ai rectifié sans que cela ne change le résultat. J'ai aussi viré la condition enable.

Le bug est bien net, non aléatoire : - La carte 1 envoie autant de message qu'elle veut et ils sont bien reçus et traités par la carte 2. - La carte 2 peut à son tour en envoyer autant qu'elle veut (le 1er peut être la réception d'un nombre ou l'appui sur le bouton, les suivants forcément des appuis) et la carte 1 les reçoit et les traite. - à partir du moment où la carte 2 a envoyé un message, elle ne reçoit plus ceux de la carte 1.

micol: Il y avait bien cette erreur d'adresse mais elle est sans conséquence : deux NRF24L01 qui ont la même R adresse discutent entre eux. J'ai rectifié sans que cela ne change le résultat.

On est bien d'accord, sauf que si tu t'adresses à clie1 alors que son adresse de réception programmée est serv1 ... D'ailleurs ça ne devrait pas fonctionner, en fait ça doit marcher simplement parce la lib mirf utilise 2 channels : le 0 pour l'émission, dont l'adresse est celle du destinataire pour permettre de recevoir l'acquittement de réception, et le 1 pour la réception pure (ou c'est l'inverse je sais plus). Mais bon si la remise en place correctes des adresses n'a rien changé je vois pas ce qui posé problème.

Évite autant que possible les variables globales, ici tu te rendrais compte de suite que "moi" ne sert à rien ... de même que "reponse". De plus les prototypes de fonction en début de fichier sont inutiles, l'ide arduino les ajoutent de lui même.

Par hasard est-ce que ton problème ne se produirait pas après l'appui sur le bouton ? Interruption et librairie Mirf ... j'ai comme un doute là dessus.

Sinon rajoute des Serial.println("xxx") un peu partout, en mettant un chiffre unique par exemple à la place de xxx. Ça te permettra de tracer l'origine du problème et nous de comprendre où ça bloque plus rapidement.

Ah punaise j'avais pas vu l'interruption ! Et oui y'a des delay() dans la lib ... Donc ça reste collé dedans :s

Bonjour,

J'y ai passé pas mal d'heures depuis la semaine dernière.

skywodd: Évite autant que possible les variables globales, ici tu te rendrais compte de suite que "moi" ne sert à rien ... de même que "reponse".

Les variables qui semblent inutiles ne le sont que parce que j'ai raccourci le programme pour cerner le bug. Elles étaient utiles dans le programme entier.

skywodd: De plus les prototypes de fonction en début de fichier sont inutiles, l'ide arduino les ajoutent de lui même.

J'ai l'habitude depuis mon apprentissage du C en 1992 de mettre les routines [u]après[/u] la loop (ou après le main() ). Le compilateur n'accepte pas si je ne les annonce pas par des prototypes et je ne l'ai jamais vu les ajouter lui-même.

skywodd: Par hasard est-ce que ton problème ne se produirait pas après l'appui sur le bouton ? Interruption et librairie Mirf ... j'ai comme un doute là dessus.

Oui ça se produit après l'appui sur le bouton. Mais il arrive que ça se produise après l'envoi d'un nombre ( = l'autre cas où le serveur répond au client)

skywodd: Sinon rajoute des Serial.println("xxx") un peu partout, en mettant un chiffre unique par exemple à la place de xxx. Ça te permettra de tracer l'origine du problème et nous de comprendre où ça bloque plus rapidement.

Je l'ai fait samedi. J'étais dans un club où j'ai pu essayer avec d'autres Mega et d'autres PC et hier j'ai remplacé le transceiver, ce qui me permet d'éliminer toute cause hard. Quand la panne se produit, le client envoit des messages ou croit les envoyer, et le serveur ne reçoit rien. Un Serial.print juste après "if Mirf.dataReady" reste muet.

J'ai effectivement des doutes sur la bibliothèque Mirf et j'ai commencé hier à regarder celle de MikeMcCauley (Mikem). Il me reste à comprendre son fonctionnement et modifier mes branchements pour coller à cette bibli.

nan mais du coup t'as testé en te passant de l'interruption ?

B@tto: Ah punaise j'avais pas vu l'interruption ! Et oui y'a des delay() dans la lib ... Donc ça reste collé dedans :s

Et ouai j'ai l’œil :P

J’évite d’utiliser les interruptions à cause de ça justement et du fait qu’un bon programme bien optimisé fait en général tout aussi bien, du coup j’ai pas le reflexe xD