Problème envoi SMS SHEILD SIM900 SHEILD RS232

Bonjour,
Ci-joint le code qui me pose problème.

Matériel: Arduino UNO
Shield SIM900
Shield RS232

Je dois envoyer par sms une trame de caractère que je lis sur un Shield RS232.
L’envoie fonctionne, mais caractère par caractère avec les espaces aussi.
Je voudrais envoyer le texte complet lu sur le RS232 par SMS en une seule fois.

Je débute en programmation.

Merci pour votre aide.

#include <SoftwareSerial.h>


SoftwareSerial RS232(6,7);
SoftwareSerial SIM900(2,3);
void setup()
{
 SIM900.begin(19200);
 RS232.begin(1200); 
 
 Serial.begin(9600);  
}

void loop()
{
   if(RS232.available())
   {
       char c = RS232.read();
       delay (80);
      Serial.print(c);
      delay (4000);
    
 SIM900.print("AT+CMGF=1\r"); 
 delay(200);

 SIM900.println("AT+CMGS=\"+336619xxxxx\""); 
 delay(200);

 SIM900.println(c);
 delay(400); 
 SIM900.print((char)26);
}}

Si vous voulez comprendre comment bien écouter le port série (ou gérer un flux asynchrone) vous pouvez jeter un oeil à mon petit tuto sur le sujet

En utilisant cette technique vous bâtissez votre message lors de la réception sur RS232 et quand le message est complet c’est là que vous l’émettez

Bonjour,

Après avoir lu votre tutoriel je vois bien que mon code est bien pourri.

Si j'ai bien compris il faut lire la trame avec un marqueur de début de conversation,
et un marqueur de fin de conversation.

La trame en question est de ce type.

[CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
[CR][LF]

Si j'ai bien compris le marqueur de début serai [CR][LF], et le marqueur de fin serai [CR][LF]
[CR][LF]?

Merci pour votre réponse.

oui en gros vous recevez des lignes de texte --> vous pouvez juste avoir la trame de fin qui serait la fin de ligne '\n' et vous ignorez le '\r' quand vous le recevez, pas la peine de le mettre dans le message

au pire votre première trame sera peut être incomplète si vous prenez le train en marche, donc prévoir peut-être d'ignorer le premier message reçu (à vous de voir ce que vous voulez faire avec le contenu, si c'est plusieurs champs différents à analyser alors vous pouvez voir s'ils sont tous présents)

Bonjour,

Je voudrai faire un "copier" de la trame lue sur le RS232 et le "coller" dans le texte du SMS
afin de l'envoyer via le Shield SIM900.

Cordialement.

oui ben la trame RS232 c’est une “ligne” donc vous la lisez avec la technique expliquée plus haut / dans le tuto, une fois reçue vous composez le SMS avec cette trame

Bonjour,

Après avoir réécrit mon code j'arrive effectivement à mettre la trame complète
dans un tableau de caractère, et à l'afficher dans le moniteur.

Il reste maintenant à récupérer ce tableau, et l'envoyer dans le Shield SIM900,
afin qu'il le traite pour envoi de SMS.

Pouvez vous m'orienter.
J'ai déjà réalisé des essais, mais l'envoi fonctionne mal.
Le message est tronqué, je n'ai jamais le même message.

Merci.

Bonjour,

Voici donc le code qui me permet de lire la trame sur le RS232.
Elle s’affiche bien dans le moniteur.

Maintenant je désire envoyer ce texte par sms.

Merci pour votre aide.

#include <SoftwareSerial.h>

SoftwareSerial RS232(6,7);
SoftwareSerial SIM900(2,3);

const byte nombredecarac = 100;
char receptioncarac[nombredecarac];   // tableau
boolean newData = false;

void setup() {

    Serial.begin(9600);
    delay (1000);
    Serial.println("<Arduino est pret>");
    SIM900.begin(19200);
    delay (1000);
    Serial.println("<SIM900 est pret>");  
    RS232.begin(1200);
    delay (1000);
    Serial.println("<RS232 est pret>");
    delay (2000);
}

void loop() {
    receptionmarqueurfin();
    voirNewData();
}

void receptionmarqueurfin() {
    static byte ndx = 0;
    char marqueurfin = '\n';
   unsigned char rc;
    
    while (RS232.available() > 0 && newData == false) {
        rc = RS232.read();

        if (rc != marqueurfin) {
            receptioncarac[ndx] = rc;
            ndx++;
            if (ndx >= nombredecarac) {
                ndx = nombredecarac - 1;
            }
        }
        else {
            receptioncarac[ndx] = '\0'; // termine la reception
            ndx = 0;
            newData = true;
        }
    }
}
void voirNewData() {
    if (newData == true) {
        Serial.println(receptioncarac);
        newData = false;
    }
}
void envoisms(){
 
  SIM900.print("AT+CMGF=1\r"); 
    delay(200);
  SIM900.print("AT+CMGS=\"+336619XXXXX\""); 
    delay(200);
  SIM900.write((char)26);
  delay (100);
}

Postez du code qui envoie le sms complet et montrez nous ce que vous recevez

Bonjour,

Ci-joint le code.

Premier problème, dès que le montage démarre, je reçois des SMS sans texte, en continu.

Ensuite quand la trame arrive sur le Shield RS232, je reçois des morceaux de la trame en continu,

Merci pour votre aide.

#include <SoftwareSerial.h>

SoftwareSerial RS232(6,7);
SoftwareSerial SIM900(2,3);

const byte nombredecarac = 100;
char receptioncarac[nombredecarac];   // tableau
boolean newData = false;

void setup() {

    Serial.begin(9600);
    delay (100);
    Serial.println("<Arduino est pret>");
    SIM900.begin(19200);
    delay (1000);
    Serial.println("<SIM900 est pret>");  
    RS232.begin(1200);
    delay (1000);
    Serial.println("<RS232 est pret>");
    delay (2000);
}

void loop() {
    receptionmarqueurfin();
    voirNewData();
    envoisms();
}

void receptionmarqueurfin() {
    static byte ndx = 0;
    char marqueurfin = '\n';
   unsigned char rc;
    
    while (RS232.available() > 0 && newData == false) {
        rc = RS232.read();

        if (rc != marqueurfin) {
            receptioncarac[ndx] = rc;
            ndx++;
            if (ndx >= nombredecarac) {
                ndx = nombredecarac - 1;
            }
        }
        else {
            receptioncarac[ndx] = '\0'; // termine la reception
            ndx = 0;
            newData = true;
        }
    }
}
void voirNewData() {
    if (newData == true) {
        Serial.println(receptioncarac);
        newData = false;
    }
        
}
void envoisms(){
    if (newData == true) {
        SIM900.println(receptioncarac);
  }
  
 
  SIM900.print("AT+CMGF=1\r"); 
    delay(200);
  SIM900.println("AT+CMGS=\"+33661974039\""); 
    delay(200);
  SIM900.println(receptioncarac);
   delay (200);
  SIM900.println((char)26);
  delay (100);
  SIM900.println();
}

plusieurs points:

  • il faut envoyer le SMS que lorsque vous avez reçu une ligne complète, c’est à dire quand newData == true.

  • vous y avez pensé et au début de envoisms(); vous faites un

void envoisms() {
  if (newData == true) {
    SIM900.println(receptioncarac);
  }  // <<== OOOPSS
...

mais vous avez fermé l’accolade au mauvais endroit, donc le reste du code de la fonction

  SIM900.print("AT+CMGF=1\r");
  delay(200);
  SIM900.println("AT+CMGS=\"+33661974039\"");
  delay(200);
  SIM900.println(receptioncarac);
  delay (200);
  SIM900.println((char)26);
  delay (100);
  SIM900.println();

va s’exécuter et ça balance un SMS… donc pas de surprise vous allez vous faire spammer :wink:

→ en pratique, il ne faut pas mettre envoisms(); dans la loop. vous pourriez mettre cela dans voirNewData() qui teste si vous avez reçu un message complet.

donc je partirai plus sur un truc de ce genre:

#include <SoftwareSerial.h>

SoftwareSerial RS232(6, 7);
SoftwareSerial SIM900(2, 3);

const byte nombredecarac = 100;
char receptioncarac[nombredecarac];   // tableau
boolean newData = false;

void setup() {

  Serial.begin(9600);
  delay (100);
  Serial.println("<Arduino est pret>");
  SIM900.begin(19200);
  delay (1000);
  Serial.println("<SIM900 est pret>");
  RS232.begin(1200);
  delay (1000);
  Serial.println("<RS232 est pret>");
  delay (2000);
}

void loop() {
  receptionmarqueurfin();
  voirNewData();
}

void receptionmarqueurfin() {
  static byte ndx = 0;
  char marqueurfin = '\n';
  unsigned char rc;

  while (RS232.available() > 0 && newData == false) {
    rc = RS232.read();

    if (rc != marqueurfin) {
      receptioncarac[ndx] = rc;
      ndx++;
      if (ndx >= nombredecarac) {
        ndx = nombredecarac - 1;
      }
    }
    else {
      receptioncarac[ndx] = '\0'; // termine la reception
      ndx = 0;
      newData = true;
    }
  }
}

void voirNewData() {
  if (newData == true) {
    Serial.println(receptioncarac);
    envoisms();
    newData = false;
  }
}

void envoisms() {
  SIM900.print("AT+CMGF=1\r");
  delay(200);
  SIM900.println("AT+CMGS=\"+33661974039\"");
  delay(200);
  SIM900.println(receptioncarac);
  delay (200);
  SIM900.println((char)26);
  delay (100);
  SIM900.println();
}

(tapé ici donc non testé)

PS: ici vous n’écoutez pas les réponses du SIM9000 donc ne lisez pas sur 2 SoftwareSerial en même temps. Dans l’idéal il faudrait écouter les réponses du SIM900 pour voir si tout s’est bien passé, mais SoftwareSerial ne sait pas bien gérer 2 voies de communication en même temps. il y a un exemple Two Port Receive qui montre comment jongler avec listen()

Bonjour,

Effectivement après avoir modifié le code suivant vos instructions, je ne suis plus spamé.

Le sms arrive bien à chaque solicitation du Shiel RS232, mais malheuresement pas encore dans
sa totalité.

#include <SoftwareSerial.h>

SoftwareSerial RS232(6,7);
SoftwareSerial SIM900(2,3);

const byte nombredecarac = 100;
char receptioncarac[nombredecarac];   // tableau
boolean newData = false;

void setup() {

    Serial.begin(9600);
    delay (100);
    Serial.println("<Arduino est pret>");
    SIM900.begin(19200);
    delay (1000);
    Serial.println("<SIM900 est pret>");  
    RS232.begin(1200);
    delay (1000);
    Serial.println("<RS232 est pret>");
    delay (2000);
}

void loop() {
    receptionmarqueurfin();
    voirNewData();
}

void receptionmarqueurfin() {
    static byte ndx = 0;
    char marqueurfin = '\n';
   unsigned char rc;
    RS232.listen();
    while (RS232.available() > 0 && newData == false) {
        rc = RS232.read();

        if (rc != marqueurfin) {
            receptioncarac[ndx] = rc;
            ndx++;
            if (ndx >= nombredecarac) {
                ndx = nombredecarac - 1;
            }
        }
        else {
            receptioncarac[ndx] = '\0'; // termine la reception
            ndx = 0;
            newData = true;
        }
    }
}
void voirNewData() {
    if (newData == true) {
  Serial.print (receptioncarac);
        envoisms ();
        newData = false;
    }
        
}
void envoisms(){
    if (newData == true) {
  SIM900.print("AT+CMGF=1\r"); 
    delay(200);
  SIM900.println("AT+CMGS=\"+336619XXXXX\""); 
    delay(200);
  SIM900.println(receptioncarac);
   delay (200);
  SIM900.println((char)26);
  delay (100);
  SIM900.println();
}
}

votre texte fait plus de 99 ou 160 caractères? si oui c'est la limite supportée sur le SIM900 je crois - et votre buffer const byte nombredecarac = 100; lui limite la lecture du RS232 à 100 caractères (-1 pour le '\0' de fin = 99)

Non, le texte ne dépasse pas 99 caractères.

Maintenant dans le moniteur la trame ne s'affiche plus entièrement.

Je reçois bien un seul SMS à chaque fois que le shield RS232 lit une trame. Ce qui est bien.
Le sms, n'est bien sur pas complet.

Si je supprime la fonction envoisms (); le moniteur affiche correctement la trame reçue sur le
shield RS232.

auriez vous un '\n' alors dans le texte qui vous est envoyé sur le RS232?

comme je vous l'ai dit, avoir 2 software Serial c'est vraiment mettre la pression sur le micro-processeur et ses interruptions et vous risquez de rater des caractères

idéalement il faudrait passer sur un MEGA par exemple, vous pourriez utiliser des ports Série matériel

Voici la trame reçu sur le RS232.

[CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
Caractères [CR][LF]
[CR][LF]

donc vous voudriez envoyer les 4 lignes d'un coup par SMS ?

dans ce cas il faut modifier la fonction qui reçoit le message pour qu'elle continue de rajouter dans le message tant qu'elle n'a pas reçu deux [CR][LF] consécutifs (ie une ligne blanche)

Bonjour,

Afin de régler le problème avec les softwareSerial, j’ai supprimé le RS232, et j’envoi directement
la trame sur le hardWareSerial de l’arduino.

Bon, pour le debug c’est pas pratique, ni pour le téléversement.

J’ai quand même réussi à bien lire la trame avec le code si dessous, mais je n’arrive pas à envoyer
le “recepcarac” par sms.

Il faut que j’envoi le “recepcarac” dans le Shield SIM900, et ensuite l’envoyer par sms,
et c’est là que je bloque.

Merci pour votre soutient.

#include <SoftwareSerial.h>
const byte numCarac = 64;
char recepcarac[numCarac];

boolean nouvData = false;
SoftwareSerial SIM900(2,3);
void setup() {
    Serial.begin(1200);
    SIM900.begin(9600);
    envoiSMS();
}

void loop() {
    recavecstartend();
    smstxt();
}

void recavecstartend() {
    static boolean reception = false;
    static byte ndx = 0;
    char startMarqueur = '\n';
    char endMarqueur = '\r';
    char rc;
 
    while (Serial.available() > 0 && nouvData == false) {
        rc = Serial.read();

        if (reception == true) {
            if (rc != endMarqueur) {
                recepcarac[ndx] = rc;
                ndx++;
                if (ndx >= numCarac) {
                    ndx = numCarac - 1;
                }
            }
            else {
                recepcarac[ndx] = '\0';
                reception = false;
                ndx = 0;
                nouvData = true;
            }
        }

        else if (rc == startMarqueur) {
            reception = true;
        }
    }
}

void smstxt() {
    if (nouvData == true) {
        SIM900.println(recepcarac);
        nouvData = false;
    }
}
void envoiSMS() {
  SIM900.print("AT+CMGF=1\r"); 
  delay(200);

  SIM900.println("AT+CMGS=\"+336619XXXXX\""); 
  delay(200);
  
  SIM900.println(recepcarac); 
  delay(200);
  
  SIM900.println((char)26); 
  delay(200);
  
  SIM900.println();
  delay(1000); 
}

donc vous voudriez envoyer les 4 lignes d’un coup par SMS ?

dans ce cas il faut modifier la fonction qui reçoit le message pour qu’elle continue de rajouter dans le message tant qu’elle n’a pas reçu deux [CR][LF] consécutifs (ie une ligne blanche)

Pour vous répondre, oui il faut envoyer tout par SMS.
Je pense que modifier la fonction serai mieux mais je ne sais pas comment faire.