Réception de sms sur SIM900

Bonjour à tous,

Je suis en train de fabriquer un système d’alarme qui me contacte par SMS lors d’une détection de présence.

La détection et l’envoi de SMS fonctionne (plus ou moins, mais enfin ça va ^^).

En revanche, j’aimerai pouvoir programmer l’heure d’activation du système par SMS aussi.

C’est là qu’est mon problème. La réception ne se fait pas complètement :

  • Le message que me réponds la SIM900 n’est pas complet (comme si il était limité à un nombre de caractères (voir photo)).

  • Si j’envoie la commande de lecture du message manuellement via le terminal, la SIM900 me réponds parfaitement.

Ça fait plusieurs jours que je m’arrache les cheveux sur cette affaire. Si quelqu’un a une idée à laquelle je n’ai pas pensé, je suis preneur :slight_smile:

A+

Le code:

#include <SoftwareSerial.h>    // For Arduino 1.0
 
SoftwareSerial SIM900(12, 13); // For Arduino 1.0

char RxChar;
String RxSMS = "";

void setup() 
{
  SIM900.begin(19200);
  delay(200);
  Serial.begin(19200); 
  delay(200);
  
  SIM900.print("ATZ\r"); // Reset la SIM900
  delay(200);
  SIM900.print("AT+CNMI=0,1,0,0,0\r"); // Les SMS sont sauvegardés sur la SIM
  delay(200);
  SIM900.print("AT+CMGD=1,4\r"); //Efface les messages reçus
  delay(200);
  
  Serial.println("Setup ok");
}





void loop() 
{
SIM900Rx();
delay(2000);
}


void SIM900Rx() 
{
  
  if (SIM900.available()) 
  {
    while (SIM900.available()>0) // Tant que y'a de la data sur le SIM900
    {
      RxChar = SIM900.read(); // Lis chaque caractère un par un
      //Serial.print(RxChar);
      if (RxChar == 10) // Si le caractère reçu est saut de ligne
      {
        Serial.println("Text: " + RxSMS); // Envoie la chaine de caractères
        RxSMS=""; // Et la vide
      }
      else
      {
        RxSMS = RxSMS + RxChar; // Ajoute dans la chaine les caractère 1 par 1
      }
    }
  }
  else
  {
  SIM900.println("AT+CMGR=1\r"); // Demande de lecture du premier sms
  }
}

C’est parce que votre boucle while vide le buffer plus vite que les data n’arrivent dedans.

Pour lire le message Bouclez tant que vous n’avez pas reçu le OK de fin de réponse par exemple mais n’arrêtez pas s’il n'y a rien de dispo à un moment donné (éventuellement implémentez un timeout)

Merci pour votre réponse. J’ai essayé plusieurs choses, dont ce que vous m’avez dit, sans grand résultat.

J’en suis arrivé à ça:

#include <SoftwareSerial.h>    // For Arduino 1.0
 
SoftwareSerial SIM900(12, 13); // For Arduino 1.0

char RxChar;
String RxSMS = "";

void setup() 
{
  SIM900.begin(19200);
  delay(200);
  Serial.begin(19200); 
  delay(200);
  
  SIM900.print("ATZ\r"); // Reset la SIM900
  delay(200);
  SIM900.print("AT+CNMI=0,1,0,0,0\r"); // Les SMS sont sauvegardés sur la SIM
  delay(200);
  SIM900.print("AT+CMGD=1,4\r"); //Efface les messages reçus
  delay(200);
  
  Serial.println("Setup ok");
}





void loop() 
{
SIM900Rx();
delay(3000);
}


void SIM900Rx() 
{
    RxSMS="";
    while (SIM900.available()>0 && RxSMS!="OK") // Tant que y'a de la data et le dernier message reçu est différent de "OK"
    {
      RxChar = SIM900.read(); // Lis chaque caractère un par un
      //Serial.print(RxChar);
      if (RxChar == 10 && RxSMS!="") // Si le caractère reçu est saut de ligne et que la chaine n'est pas vide
      {
        Serial.println("Text: "+RxSMS); // Envoie la chaine de caractères
        RxSMS=""; // Vide la chaine
      }
      else
      {
        if (RxChar != 10 && RxChar!= 13 && RxChar!=0) //Si RxChar est différent de \r de \n et de vide
        {
          RxSMS = RxSMS + RxChar; // Rempli la chaine du caractère reçu
        }
      }
    }

    
    if (RxSMS == "OK") // Si le dernier message reçu est "OK"
    {
      Serial.println("Text: OK");
      RxSMS="";
      SIM900.print("AT+CMGR=1\r"); // Demande de lecture du premier sms  
    }
    else
    {
      if (RxSMS.substring(0,17)=="+CMGR: \"REC READ\"") // Si le message est lu 
        {
          SIM900.print("AT+CMGD=1,4\r"); // Efface tout les mssages
          RxSMS="";
        }
         
    }
      
}

Avec ce code, le terminal se fige et il ne rentre plus dans sa boucle while, après la réception d’un SMS.

La trame incomplète est toujours là, c’est même pire. Je ne comprends pas, puisque il ne devrait pas sortir du while sans avoir reçu le “OK”.

Je n’ai pas réussi à trouver comment faire un TimeOut alors j’ai essayé avec un compteur de caractères reçus (tant qu’il n’y avait pas eu 500/1000/10000 tours dans la boucle il y restait), mais ça donnait le même résultat.

Voici ce que m’affiche le terminal:

Setup ok
Text: ATZ
Text: OK
Text: AT+CNMI=0,1,0,0,0
Text: OK
Text: AT+CMGD=1,4
Text: OK
Text: AT+CMGR=1
Text: OK
Text: AT+CMGR=1
Text: OK
Text: AT+CMGR=1
Text: OK
Text: AT+CMGR=1
Text: +CMGR: "REC UNREAAT+CMGR=1
Text: +CMGAT+CMGR=1

lisez mon petit tuto éventuellement Ecouter le Port Série ou un keypad (applicable à 1 flux de données asynchrone )

Si vous lisez l'anglais vous pouvez aussi lire Serial Input Basics pour comprendre comment gérer correctement la voie série

(et laissez tomber la classe String)