Incompatibilité RCSwitch et NeoSWSerial => problème d'interruption ?

Bonjour,

J'ai un montage à base de Nano, transeivers 433 MHz (émetteur FS1000a / récepteur RXB6) avec la librairie RCSwitch. Tout se passait bien jusqu'à ce que j'ajoute un lecteur RFID géré au travers d'un MAX3232 et la librairie NeoSWSerial.

Les deux marchent bien indépendamment l'un de l'autre, mais si j'active les 2 en même temps, l'arduino fait n'importe quoi voire reboote quand je scanne un tag RFID.

Ca me fait penser à un problème de perturbation/interaction au niveau des interruptions mais ma connaissance s'arrête là. Le lecteur RFID est alimenté indépendamment, donc pas d'incidence à priori sur le montage.

Extrait de la boucle loop qui plante :

Si j'active ce bloc :

  // Actions à exécuter tout le temps => réception et traitement de msg 433MHz => commande poulailler
  if (receiver_433.available()) {
      
    unsigned long value = receiver_433.getReceivedValue();
    
    if (value == 0) {
      Serial.print(F("Unknown encoding"));
    } else {
      Serial.print(F("Received "));
      Serial.print( value );
      Serial.print(F(" / "));
      Serial.print( receiver_433.getReceivedBitlength() );
      Serial.print(F("bit "));
      Serial.print(F("Protocol: "));
      Serial.println( receiver_433.getReceivedProtocol() );

      // Réception signal d'ouverture de porte de Jeedom
      if (value == COMMANDE_433_OUVRIR_PORTE) {
        if (statutPorte == 2){ // Porte déjà ouverte => renvoie le signal à Jeedom
          porteOuverte();        
        } else { // Porte fermée => ouvre la porte
          ouvrePorte();
        }
      }
       
      // Réception signal de fermeture de porte de Jeedom
      if (value == COMMANDE_433_FERMER_PORTE) {
        if (statutPorte == 4){ // Porte déjà fermée => renvoie le signal à Jeedom
          porteFermee(1);        
        } else { // Porte fermée => ouvre la porte
          fermePorte();
        }
      }

      // Réception autres signals
      if (value == COMMANDE_433_ECLAIRAGE_ON) {
        digitalWrite(RELAIS_ECLAIRAGE_EXTERIEUR, LOW);
        statutEclairage = LOW;
      }
      if (value == COMMANDE_433_ECLAIRAGE_OFF) {
        digitalWrite(RELAIS_ECLAIRAGE_EXTERIEUR, HIGH);
        statutEclairage = HIGH;
      }
      if (value == COMMANDE_433_DETECTEUR_MOUVEMENT_ON)  {digitalWrite(RELAIS_DETECTEUR_MOUVEMENT, LOW);}
      if (value == COMMANDE_433_DETECTEUR_MOUVEMENT_OFF) {digitalWrite(RELAIS_DETECTEUR_MOUVEMENT, HIGH);}
      if (value == COMMANDE_433_LECTEUR_RFID_ON)         {RFID_init();}
      if (value == COMMANDE_433_LECTEUR_RFID_OFF)        {RFID_off();}
    }
    
    receiver_433.resetAvailable();
  }

Ce bloc là ne fonctionne pas et fait n'importe quoi :

  // Traitement communication MAX3232 / RFID
  while (RFID.available()) {
    delay(1);
    byte c = RFID.read();
    char buffer[2];
    sprintf(buffer,"%.2X", c); // Conversion HEX to string with leading 0
    readString += buffer;
  }

  if (readString != ""){
    readString.toUpperCase();
    Serial.println(readString);

    
    readString = "";
  }
<= Fin du bloc =>

Extrait de la configuration :

/* RF 433MHz Receiver config */
RCSwitch receiver_433 = RCSwitch();

/* MAX3232 RS232 <=> TTL driver pour RFID */
#define RFID_TXD A3
#define RFID_RXD A2
NeoSWSerial RFID(RFID_TXD, RFID_RXD); // MAX3232 TX PIN, MAX3232 RX PIN
//AltSoftSerial RFID(RFID_TXD, RFID_RXD); // MAX3232 TX PIN, MAX3232 RX PIN

Extrait de la void setup :

  // Attache l'interruption 0 (pin d2) au recepteur 433MHz
  receiver_433.enableReceive(RECEIVER_433);

  // Initialisation MAX3232 liaison RFID
  RFID_init();

La void RFID_init :

/* Initialisation lecteur RFID */
void RFID_init(){
  // Allumage lecteur RFID (switch relais ON)
  digitalWrite(RELAIS_LECTEUR_RFID, LOW);
  delay(250);
  
  // Initialisation MAX3232 liaison RFID
  RFID.begin(9600);
  delay(250);
  RFID.write(getBasicInfo, sizeof(getBasicInfo));
//  RFID.write(set_Close_BuzzerOff_1s, sizeof(set_Close_BuzzerOff_1s));
  delay(180);

  while (RFID.available()) {
    delay(1);
    byte c = RFID.read();
    char buffer[2];
    sprintf(buffer,"%.2X", c); // Conversion HEX to string with leading 0
    readString += buffer;
  }

  if (readString != ""){
    readString.toUpperCase();
    Serial.println(readString);
    if (readString == "CCFFFF8200220A207777772E416F7369642E636F6D200A205056332E36384E6F2E3A0036353533358C"){
      Serial.println(F("Lecteur RFID prêt"));
      statutLecteurRFID.send(1, 1);
    } else {
      Serial.println(F("ERREUR !! Lecteur RFID non prêt ! Contrôlez SVP"));
      statutLecteurRFID.send(0, 1);
    }
    
    readString = "";
  }
}

Voici ce que je reçois de la partie NeoSWSerial du lecteur RFID si les deux blocs sont activés :

⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮  |⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2      |⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2⸮⸮    |⸮⸮⸮2⸮⸮⸮⸮⸮⸮|⸮⸮⸮2
⸮⸮

Alors que si je désactive la partie RCSwitch je reçois des données valides du MAX3232 venant du lecteur RFID (valeurs HEX exploitables) :

CCFFFF8200220A207777772E416F7369642E636F6D200A205056332E36384E6F2E3A0036353533358C

Merci du coup de main
JF

La pin DATA du RXB6 piloté par RCSwitch est attachée à la PIN D2 (interrupt 0).

Salut

  receiver_433.enableReceive(RECEIVER_433);

Combien vaut RECEIVER_433 ?
Il semblerait qu'il doive valoir 0 (interrupt 0) si tu es connecté sur PIN 2.

Oui c’est ça

l’émission/réception RF433 fonctionne bien

La lecture de badge rfid fonctionne bien si je désactive le premier bloc qui traite la réception de msg RF433.

Le problème produit un genre d’interférence lorsque je badge un tag rfid alors que le premier bloc est activé.

Pourrais-tu poster le résultat de ta compilation ?
Ce qui m'intéresse est l'espace disponible en RAM.

Je suis en déplacement là. J’ai effectivement eu un avertissement de mémoire presque remplie quand ça a commencé ces problèmes.

Du coup j’ai basculé mes serial.print sur PROGMEM et je suis à moins 45% d’utilisation maintenant.

Le problème de mémoire a pu abîmer le Nano définitivement ?

Merci de la réponse

Le problème de mémoire a pu abîmer le Nano définitivement ?

Non.

Ce qui m'intéresse est la place disponible en mémoire dynamique.

@+

Sketch uses 13372 bytes (43%) of program storage space. Maximum is 30720 bytes.
Global variables use 771 bytes (37%) of dynamic memory, leaving 1277 bytes for local variables. Maximum is 2048 bytes.

Ca m'a l'air bien large quand même, non ?

Plutôt large mais tout dépend de la lourdeur des librairies utilisées, en particulier de la quantité de variables déclarées sur la pile.

Le problème est-il provoqué simplement par l'ajout du code 433Mhz ou faut-il qu'il s'exécute ?

As-tu essayé en supprimant cette ligne ?

  receiver_433.enableReceive(RECEIVER_433);

@+

C'est qui active l'interruption de la librairie RCSwitch.
Si je la désactive, il n'y aucune interruption activée, et je ne reçois donc aucun message RF433.

Avec la librairie RCSwitch, il faut activer la partie interruption avec le .enableReceive et faire un .available à chaque boucle pour tester s'il y a des données reçues.

JF

Je comprends bien mais j'aimerais savoir comment se comporte la partie RFID dans le cas où il n'y a pas de réception RF433.
Je suppose quand même que ce n'est pas la place occupée par le code RF433 qui pose problème ?

Le RFID est-il testable sans qu'il y ait de réception RF433 au préalable ?
Dans ton code je ne vois rien qui s'y oppose.

Ce que j'aimerais c'est connaître le scénario exact de reproduction du problème.

@+

La partie RFID fonctionne si le bloc "réception 433" est désactivé et est pertubée si le bloc est activé, qu'il y ait ou non réception de msg de 433.
La réception de msg 433, elle, n'est pas pertubée.

J'ai passé la variable locale "char buffer[2]" du bloc suivant en globale, et le problème s'arrête ! Je ne comprends pas !?

// Traitement communication MAX3232 / RFID
  while (RFID.available()) {
    delay(1);
    byte c = RFID.read();
//    char buffer[2]; // => remontée en globale
    sprintf(buffer,"%.2X", c); // Conversion HEX to string with leading 0
    readString += buffer;
  }

  if (readString != ""){
    readString.toUpperCase();
    Serial.println(readString);

    
    readString = "";
  }
<= Fin du bloc =>

Mais la suite de mon bloc plante toujours, si j'essaie de faire un substring quelconque sur la variable readString à la suite de ce bloc, ça part en sucette et l'arduino reboote.

J'ai l'impression en parcourant les forums, que le problème viendrait que j'utilise String plutôt que char[], ce qui engendrerait un problème de mémoire, du coup ce qui valide le diagnostic de départ ?

Comment remplacer "readString += buffer;" avec un array de char ? Ou comment concaténer avec des char ?

Merci
JF

J'ai l'impression en parcourant les forums, que le problème viendrait que j'utilise String plutôt que char[], ce qui engendrerait un problème de mémoire, du coup ce qui valide le diagnostic de départ ?

Oups ... je n'avais pas remarqué.

readString += buffer;
équivalent :
strcat()

@+

    byte c = RFID.read();
    char buffer[2];
    //
    // à mon avis la ligne suivante pourrit forcément la variable située immédiatement
    // après buffer sur la pile
    //
    sprintf(buffer,"%.2X", c); // Conversion HEX to string with leading 0
    readString += buffer;

Ton buffer devrait avoir une taille de 3, et non pas de 2, car il n'y aura pas de place pour le "leading 0".
Pas étonnant qu'il y ait des problèmes en fonction du déplacement de cette variable en mémoire.
En la passant en global c'est pareil, le sprintf écrase la variable suivante en mémoire.

@+

Merci !

Pas essayé 3, mais j'avais essayé 4 sans plus de succès.

Mon Nano vient de griller :-/ Il ne boote plus, je ne peux plus uploader de code, le bouton reset reste inactif.
Je vois bien l'interface COM sur mon PC et il est allumé (diode POW allumée) via l'alimentation USB du PC. Il fournit bien du courant sur sa pin 5V.

Peut-on le griller uniquement par le code ? Je n'ai rien touché à l'électronique depuis des jours. Par contre je cherche à débugger ce code....

Pas essayé 3, mais j'avais essayé 4 sans plus de succès.

En tous cas, surtout pas 2.

Je vois bien l'interface COM sur mon PC et il est allumé (diode POW allumée) via l'alimentation USB du PC. Il fournit bien du courant sur sa pin 5V.

L'interface USB est fournie par le convertisseur USB / série.
Le 5V est fourni directement par l'USB du PC. La LED est aussi alimentée par le 5V directement.

Peut-on le griller uniquement par le code ?

Je ne pense pas. Griller une sortie je veux bien, mais le processeur, non.
Y a-il eu de la fumée ou une odeur ?

Ne jamais commander à l'unité, toujours avoir un peu de stock.

J'ai quatre NANO + une PRO MINI HS sous mon écran, en trois ans.

Je commande ICI (20 pièces) ou ICI (10 pièces).

Par contre il faut compter 2 à 3 semaines et je suppose que tu es pressé.

@+

Aucune odeur ou fumée, il n'a jamais rebooté après un énième essai. Ca part en vrille, j'appuie sur le bouton reset, et là il ne reboote plus...

J'en ai un autre sous la main, j'ai quelques heures de boulot pour tout dessouder / ressouder...

Mais j'avoue que je reste dubitatif sur la façon dont ça s'est passé.

Bon ça ne change rien en passant le buffer à une taille de 3 ou même 4 :-/
J'en suis toujours là :

"Mais la suite de mon bloc plante toujours, si j'essaie de faire un substring quelconque sur la variable readString à la suite de ce bloc, ça part en sucette et l'arduino reboote."