cannot get recieved sms

Hello good day everyone. I seem to be having some problems. i am using an arduino mega 2560 and connected to it i have a gsm module sm5001-B module. I am able to send text messages but recieving is a bit more tricky. I have the following code below:


char character=0;
void setup()
{

Serial.begin(9600);
Serial1.begin(9600);
delay(60000);

}

void loop()
{

int j=0;
char incoming_let=0;
char incoming_char[500]=" ";
String buff1 = String(500);
Serial1.println("AT+CMGF=1");
delay(1500);
Serial1.print("AT+CMGL=");
Serial1.write((byte)34);
Serial1.print("ALL");
Serial1.write((byte)34);
Serial1.println();
delay(1000);

while(Serial.available())
{
character = Serial.read();
Serial1.print(character);
}
while(Serial1.available())
{
character = Serial1.read();

Serial.print(character);
}

}


Output:
+SIND: 11

+SIND: 3

+SIND: 4

OK
+CMGL: 1,0,"REC READ
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+0
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+0
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+0
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+0
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+0


But following the same code on the terminal gives this output:

as you can see the actual sms body saying testing was gotten. My goal is to get the entire message and parse the entire string to get the sms body alone. Thank you in advance.

Hi, it's hard to say precisely what happens, but at least part of the problem is due to the way you (don't) read the response from the modem.

The first part of the response (+SIND messages) are setup messages that you should read before sending further commands. Otherwise they will stay in the Serial1 buffer preventing further messages to be sent by the modem. As a general rule, even if you don't care about what the modem responds, you should use Serial1.available() and Serial1.read() to empty the buffer. This also applies to the AT+CMGF=1 command.

Finally, when you arrive at the AT+CMGL command you should consider the following:

  • the modem has some old messages in the buffer and will send them before the actual response to the AT+CMGL command;
  • reading the response will free space from the buffer, allowing the modem to send some more parts of the messages, but if you read faster than the modem can refill the buffer you end up with available() returning 0, not because there are no more messages but because reading from the buffer is faster than writing into it;
  • it is also likely that the output is garbled: some modems only send a CR to end a line (instead of a CR-LF), and some terminals respond to a CR by repositioning the cursor at the beginning of the current line, so the response "testing" may be overwritten by the following +CMGL response. You may use the terminal in HEX mode (if possible) to see what characters are used to terminate a line.

I must say that I don't understand why you read from Serial and write to Serial1, then the other way round. Anyway, when Serial1.available() returns 0 the loop restarts and sends the CMGF and CMGL commands again and you never get a complete response. There are many ways to change this, but just to get you started you may add a short delay after each Serial1.read(), in the last lines of your code, so the modem can send all its messages. Then you should think of a more robust implementation that waits for the OK string.

ok i followed what you said,tried cleaning up my code a bit before i store stuff into an array and try parsing the sms body, However with the following code i get no output, so the if statement is causing a problem,on commenting the if statement, i get the same output as before, but no sms body, below is my code.

char character = 0;
char character1 = 0;
void setup()
{

Serial.begin(9600);
Serial1.begin(9600);
delay(1000);
}

void loop()
{

character1=Serial1.read();
delay(500);

if (character1=='+SIND: 4')
{

Serial1.println("AT+CMGF=1");
delay(500);
Serial1.println("AT+CMGR=1");
delay(500);

while(Serial1.available())
{
character = Serial1.read();
delay(500);
Serial.print(character);
}
}

}

The if statement

if (character1=='+SIND: 4')

doesn't work because you are comparing a character to... well it's not a string because it should go within double quotes ("+SIND: 4"), but it's not a character either. It's ok to comment it out for now.
Just to see the content of the whole response buffer, can you add an infinite loop at the end of your loop()? I mean:

  while(1)
  {
    while(Serial1.available())
    {
      character = Serial1.read();
      delay(500);
      Serial.print(character);
    }
  }

Obviously, the loop will never terminate so this is just a test, but after a while you should get the whole response buffer, so we know whether the problem is in the GSM module or in the code that interprets the response.

the code given keeps cycling until +sind 4

+SIND: 1

+SIND: 10,"SM",1,"FD",1,"LD",1,"MC",1,"RC",1,"ME",
+SIND: 11

+SIND: 3

+SIND: 4
èÐÐÐÐ
+SIND: 1

+SIND: 10,"SM",1,"FD",1,"LD",1,"MC"
+SIND: 11

+SIND: 3

+SIND: 4

Have a look at this code. It may help...

#include <SoftwareSerial.h>
 

// EN: String buffer for the GPRS shield message
String msg = String("");
// EN: Set to 1 when the next GPRS shield message will contains the SMS message
int SmsContentFlag = 0;
//control pins of relay.
int relay_a=4;
int relay_b=5;
int relay_c=6;
int relay_d=7;
int led = 13; // Interrupt monitor
int door = 12; // Door Status monitor
int button=2; // Door Sensor monitor

 // Interrupt Service Routine (ISR)
void doormonitor ()
{
  if (digitalRead (12) == HIGH && digitalRead (2)==HIGH )
   digitalWrite (led, HIGH);
  else
    digitalWrite (led, LOW);
}  // end of pinChange
void setup()
{
  Serial.begin(19200);                 // the GPRS baud rate
  // Initialize  PINs
  pinMode( 4, OUTPUT ); 
  pinMode( 5, OUTPUT ); 
  pinMode( 6, OUTPUT ); 
  pinMode( 7, OUTPUT ); 
  digitalWrite( 4, HIGH ); 
  digitalWrite( 5, LOW ); 
  digitalWrite( 6, LOW );
  digitalWrite( 7, LOW );
  Serial.println( "AT+CMGF=1" ); 
 delay(2000);
 Serial.print( "AT+CMGDA=" ); 
Serial.write(34);
Serial.print("DEL ALL");
Serial.write(34);
Serial.write(13);
Serial.write(10);
delay(6000);
Serial.println( "Let's Test..." ); 
 pinMode(13, OUTPUT); // Interrupt monitor
 pinMode(12, INPUT); // Door status monitor
 pinMode(2, INPUT); //Door sensor monitor
 digitalWrite (2, LOW);  // internal pull-up resistor
 attachInterrupt(0, doormonitor, RISING); //Interrupt 0 is Digital Pin 2
  //When the Input goes from High to Low it will trigger a function called "doormonitor"
}
 
void loop()
{
  char SerialInByte;
    if(Serial.available())
    {       
        SerialInByte = (unsigned char)Serial.read();
       delay(5);
        
        // -------------------------------------------------------------------
        // EN: Program also listen to the GPRS shield message.
        // -------------------------------------------------------------------
       // EN: If the message ends with <CR> then process the message
        if( SerialInByte == 13 ){
          // EN: Store the char into the message buffer
          ProcessGprsMsg();
         }
         if( SerialInByte == 10 ){
            // EN: Skip Line feed
         }
         else {
           // EN: store the current character in the message string buffer
           msg += String(SerialInByte);
         }
     }   
}
// EN: Make action based on the content of the SMS. 
//     Notice than SMS content is the result of the processing of several GPRS shield messages.
void ProcessSms( String sms ){
  
  if( sms.indexOf("ona") >= 0 ){
    digitalWrite( relay_a, LOW );
  }
   if( sms.indexOf("onb") >= 0 ){
    digitalWrite(  relay_b, HIGH );
  }
   if( sms.indexOf("onc") >= 0 ){
    digitalWrite(  relay_c, HIGH );
  }
  if( sms.indexOf("ond") >= 0 ){
    digitalWrite(  relay_d, HIGH );
  }
  if( sms.indexOf("offa") >= 0 ){
    digitalWrite(  relay_a, LOW );
  }
  if( sms.indexOf("offb") >= 0 ){
    digitalWrite(  relay_b, LOW );
  }
  if( sms.indexOf("offc") >= 0 ){
    digitalWrite(  relay_c, LOW );
  }
  if( sms.indexOf("offd") >= 0 ){
    digitalWrite(  relay_d, LOW );
  }
}
// EN: Request Text Mode for SMS messaging
void GprsTextModeSMS(){
  Serial.println( "AT+CMGF=1" );
}

void GprsReadSmsStore( String SmsStorePos ){
  Serial.print( "AT+CMGR=" );
  Serial.println( SmsStorePos );
}

// EN: Clear the GPRS shield message buffer
void ClearGprsMsg(){
  msg = "";
}

// EN: interpret the GPRS shield message and act appropiately
void ProcessGprsMsg() {
  if( msg.indexOf( "Call Ready" ) >= 0 ){
   //  Serial.println( "*** GPRS Shield registered on Mobile Network ***" );
     GprsTextModeSMS();
  }
  
  // EN: unsolicited message received when getting a SMS message
  if( msg.indexOf( "+CMTI" ) >= 0 ){
   //  Serial.println( "*** SMS Received ***" );
     // EN: Look for the coma in the full message (+CMTI: "SM",6)
     //     In the sample, the SMS is stored at position 6
     int iPos = msg.indexOf( "," );
     String SmsStorePos = msg.substring( iPos+1 );
   //  Serial.print( "SMS stored at " );
  //   Serial.println( SmsStorePos );     
     // EN: Ask to read the SMS store
     GprsReadSmsStore( SmsStorePos );
  }
  
  // EN: SMS store readed through UART (result of GprsReadSmsStore request)  
  if( msg.indexOf( "+CMGR:" ) >= 0 ){
    // EN: Next message will contains the BODY of SMS
    SmsContentFlag = 1;
    // EN: Following lines are essentiel to not clear the flag!
    ClearGprsMsg();
    return;
  }
  
  // EN: +CMGR message just before indicate that the following GRPS Shield message 
  //     (this message) will contains the SMS body 
  if( SmsContentFlag == 1 ){
 //   Serial.println( "*** SMS MESSAGE CONTENT ***" );
 //   Serial.println( msg );
 //   Serial.println( "*** END OF SMS MESSAGE ***" );
    ProcessSms( msg );
  }
  
  ClearGprsMsg();
  // EN: Always clear the flag
  SmsContentFlag = 0; 
}

Thanks for the code, i'll look through it and try to understand whats going on and impliment it into my program. Will let you know how it goes :).

sure...

That's the fun of arduno... "Sharing"

Hey guys whatsup. So i looked at the code and now i understand what i have to do. I plan on loading all the characters into an array and then parsing the sms body from that array. I'm having a problem though since as you can see from my code earlier i am not able to get the sms body from the program i have written but on using the same commands on the terminal i am able to recieve the sms body also. I've added delays and changed a few things(some of which had to be commented since it didn't work, see code above) and i've been fiddling with the same code but to no avail. Any help would be greatly appreciated. Thanks.

Please post your latest code, within [ code ] tags and possibly after applying Tools - Autoformat.

Heres my code,under i shall post my output.

char character = 0;
char character1=0;
void setup()
{
  
  Serial.begin(9600);
  Serial1.begin(9600);
  delay(1000);
  }

void loop()
{
  
  character1=Serial1.read();
  delay(500);
  
  // (character1 == '+SIND: 4')
  //
  
  Serial1.println("AT+CMGF=1");
     
  delay(500);
  Serial1.println("AT+CMGR=1");
  Serial1.flush();
  delay(500);
  
  while(Serial1.available())
  {
    character = Serial1.read();
    delay(500);
    Serial.print(character);
      
  }
  
  }
}

here is my output through arduino
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"
OK
+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"

My output through terminal is this

+CMGL: 1,0,"REC READ","+18687914655","13/03/21,20:39:00+00"
testing --------------------------------->this is the sms body which i am able to get from terminal but not using arduino

I'm sorry but I can't understand how you can send only AT+CMGF and AT+CMGR commands and receive an AT+CMGL response. Code and messages appear out of sync. Maybe you should reset the modem or power down the whole thing.

oh i'm terribly sorry about that. posted the wrong output. here it is.

+CMS ERROR: 313 ---->this error is due to me fiddling with the delay and not giving the module enough time to boot, same output gotten though

+SIND: 1

+SIND: 10,"SM",1,"FD",1,"LD",1,
+SIND: 11

+SIND: 3

+SIND: 4

OK
+CMGR: "REC READ",0,"+18687914655","13/03/21,20:39:00+00"
OK
+CMGR: "REC READ",0,"+18687914655","13/03/21,20:39:00+00"
OK
+CMGR: "REC READ",0,"+18687914655","13/03/21,20:39:00+00"
OK

Ok, now do this change to the final part of your code. From this:

  while(Serial1.available())
  {
    character = Serial1.read();
    delay(500);
    Serial.print(character);
      
  }
  
  } // this extra parenthesis must go away -- the problem is not this however

To this:

  while(Serial1.available())
  {
    character = Serial1.read();
    delay(500);
    if (character == '\r')
      Serial.print(" ");
    else
      Serial.print(character);      
  }

If you get different results I promise I'll explain.

same output :(, i just don't understand why :(!! yur using the carriage return to get the message basically, i tried it with carriage return, carriage return and line feed,can't understand why i can't get the bloody msg!

My last option is to go back to the idea that loop() repeats too fast, and (just as a test) it should send the commands only once. So at the end of your code I would make these changes:

while(1) // infinite loop prevents loop() from sending commands more than once
{
  while(Serial1.available())
    {
      character = Serial1.read(); // no need to delay()
      if (character == '\r')
        Serial.print(" ");
      else
        Serial.print(character);      
  }
}
char character = 0;
char character1=0;
void setup()
{
  
  Serial.begin(9600);
  Serial1.begin(9600);
  delay(60000);
  }

void loop()
{
  
  character1=Serial1.read();
  delay(500);
  
  // (character1 == '+SIND: 4')
  //
  
  Serial1.println("AT+CMGF=1");
     
  delay(500);
  Serial1.println("AT+CMGR=1");
  Serial1.flush();
  delay(500);
  
   
  while(1) // infinite loop prevents loop() from sending commands more than once
{
  while(Serial1.available())
    {
      character = Serial1.read(); // no need to delay()
      if (character == '\r')
        Serial.print(" ");
      else
        Serial.print(character);      
  }
}
}

Output

+SIND: 3

+SIND: 4

+SIND: 7

+SIND: 11

OK
+CMGR: "R

funny thing is it stops at different points, sometimes you get more of the output, sometimes less, i fiddled around but didn't get much(but never saw the sms body), any ideas? i'm all out :frowning:

instead of starting like this

  while(1) // infinite loop prevents loop() from sending commands more than once
{
  while(Serial1.available())
    {
      character = Serial1.read(); // no need to delay()
      if (character == '\r')
        Serial.print(" ");
      else
        Serial.print(character);      
  }

try this... omit the while(1) loop & put an "if" condition there..

void loop()
// serial port initilisation & other stuffs

if(Serial1.available())
      {
      character = Serial1.read(); // no need to delay()
      if (character == '\r')
        Serial.print(" ");
      else
        Serial.print(character);      
  }

Hope it helps. Go through the initial posts of this thread. I have already given you the full code. Your solution is there.
Best of luck.

My idea is still that the comm buffer is too small (64 chars) and must be read immediately after each command is sent. I didn't consider the init messages, but you can get rid of them before the AT+CMGR command with another loop:

Serial1.println("AT+CMGF=1"); // as in existing code
character = 0; // just to be sure, though it should already be 0
while (character != 'K') // Wait for the K in the OK response
{
  if (Serial1.available())
    Serial1.read();
}
Serial1.println("AT+CMGR=1"); // the rest remains as before

@nightcrawler, all these tests are just to make sure that there is nothing wrong with the modem or with the serial communication. That's the reason for the infinite loop at the end, that blocks from sending infinite AT commands in loop(). Then I agree that the resulting code would need a lot of reworking and I'd recommend something like your solution (didn't try it, though). Your code however also deletes the messages from the phone, and if I'm not mistaken this happens before it starts receiving new messages, so it may need some adjustment to work in the present case.

#include <SoftwareSerial.h>
 

// EN: String buffer for the GPRS shield message
String msg = String("");
// EN: Set to 1 when the next GPRS shield message will contains the SMS message
int SmsContentFlag = 0;
//control pins of relay.
int relay_a=4;
int relay_b=5;
int relay_c=6;
int relay_d=7;
int button=2; // Door Sensor monitor
volatile int doorlock;

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile ("  jmp 0");  
} 

void setup()
{
Serial.begin(19200);                 // the GPRS baud rate
  // Initialize  PINs
pinMode( 4, OUTPUT ); 
pinMode( 5, OUTPUT ); 
pinMode( 6, OUTPUT ); 
pinMode( 7, OUTPUT ); 
digitalWrite( 4, LOW ); 
digitalWrite( 5, LOW ); 
digitalWrite( 6, LOW );
digitalWrite( 7, LOW );
Serial.println( "AT+CMGF=1" ); 
delay(2000);
Serial.print( "AT+CMGDA=" ); 
Serial.write(34);
Serial.print("DEL ALL");
Serial.write(34);
Serial.write(13);
Serial.write(10);
delay(6000);
Serial.println( "Let's Test..." ); 
pinMode(2, INPUT); //Door sensor monitor
digitalWrite (2, HIGH);  // internal pull-up resistor
doorlock = 0;
}
 
void loop()
{
  while (doorlock==1)
     {
      if (digitalRead(2)==HIGH)
        {
         Serial.write("AT+CMGS=");
         Serial.write(34); //ASCII of “
         Serial.write("+919681108468");
         Serial.write(34);
         Serial.write(13);
         Serial.write(10);
         delay(1000);
         Serial.println("Yahoo, You are Successful...!"); //this is the message to be sent
         delay(500);
         Serial.write(26); //
         Serial.write(13);//
         Serial.write(10);//Ascii code of ctrl+z to send the message
         doorlock=0;
        }
        else if (digitalRead(2)==LOW)
                {
                  break;
                }
      }
  char SerialInByte;
    if(Serial.available())
    {       
     SerialInByte = (unsigned char)Serial.read();
     delay(5);
     if( SerialInByte == 13 )
         {
           ProcessGprsMsg(); // EN: Store the char into the message buffer
         }
            if( SerialInByte == 10 )
            {
               // EN: Skip Line feed
            }
            else 
            {
              msg += String(SerialInByte); // EN: store the current character in the message string buffer
            }
     }   
}

void ProcessSms( String sms )
{
  if( sms.indexOf("ona") >= 0 )
  {
    software_Reset();
  }
   if( sms.indexOf("onb") >= 0 )
  {
     digitalWrite(  relay_b, HIGH );
     doorlock=1;  
  }
   if( sms.indexOf("onc") >= 0 )
  {
    digitalWrite(  relay_c, HIGH );
   }
  if( sms.indexOf("ond") >= 0 )
  {
    digitalWrite(  relay_d, HIGH );
  }
  if( sms.indexOf("offa") >= 0 )
  {
    digitalWrite(  relay_a, LOW );
  }
  if( sms.indexOf("offb") >= 0 )
  {
    digitalWrite(  relay_b, LOW );
     doorlock=0;
  }
  if( sms.indexOf("offc") >= 0 ) 
  {
    digitalWrite(  relay_c, LOW );
  }
  if( sms.indexOf("offd") >= 0 )
  {
    digitalWrite(  relay_d, LOW );
  }
}

void GprsTextModeSMS()
{ 
  Serial.println( "AT+CMGF=1" ); // EN: Request Text Mode for SMS messaging
}

    void GprsReadSmsStore( String SmsStorePos )
     {
        Serial.print( "AT+CMGR=" );
        Serial.println( SmsStorePos );
     }
       
void ClearGprsMsg() // EN: Clear the GPRS shield message buffer
    {
      msg = "";
    }


void ProcessGprsMsg() // EN: interpret the GPRS shield message and act appropiately
    {
      if( msg.indexOf( "Call Ready" ) >= 0 ){
      //  Serial.println( "*** GPRS Shield registered on Mobile Network ***" );
       GprsTextModeSMS();
    }
  
 if( msg.indexOf( "+CMTI" ) >= 0 )   // EN: unsolicited message received when getting a SMS message
     {
          int iPos = msg.indexOf( "," );
          String SmsStorePos = msg.substring( iPos+1 );
          GprsReadSmsStore( SmsStorePos );
     }
  
 if( msg.indexOf( "+CMGR:" ) >= 0 )
    {
       SmsContentFlag = 1;     // EN: Next message will contains the BODY of SMS
       ClearGprsMsg();     // EN: Following lines are essentiel to not clear the flag!
       return;
    }
  
  
 if( SmsContentFlag == 1 )  // EN: +CMGR message just before indicate that the following GRPS Shield message
     {
       ProcessSms( msg );   //     (this message) will contains the SMS body 
     }
  
 ClearGprsMsg();
  SmsContentFlag = 0;    // EN: Always clear the flag
}

This is the revised code... I have made some alterations such as... you can send "ona" to reset the system & I have also added the code to delete the sms memory in void setup() function. So, every time you reset the code by sending sms, the sms memory is recycled & fully deleted. There is a flag that keeps track of new sms arrival & after the execution of the sms, the Flag resets to its initial position.

Best of luck