Problem when reading from a GSM-modem

Hello, this is my first post at the Arduino forums :slight_smile:

I just started using Arduino, and I’ve got myself a Mega 2560. I am interfacing with a GSM-modem, and stumbled upon a few problems when I tried to read an SMS from the modem. I’ll go ahead and post a code snippet:

void setup()
{
  Serial.begin(9600);  // PC
  Serial2.begin(9600); // GSM-modem
  initGSM();
  readSMS();
  
}

void loop()
{
}

void initGSM()
{

  Serial2.print("at+cmgf=1\r");
  delay(100);
  Serial2.print("at+cpin=5934\r");
  delay(200);
  Serial2.flush();
  Serial.flush();
}

void readSMS()
{
  char sms[200];
  Serial2.print("at+cmgr=1\r");
  if(Serial2.available())
  {
    *sms=Serial2.read();
    Serial.print(*sms);
  }
}

As you can see I call readSMS() in void setup(), that is not how it is supposed to be in the final code, but i use it for testing now. The thing is, I want to call readSMS() from anywhere in the program, but not in void loop(). When I do that(call it from anywhere else), I only get part of the output i need, actually only one character, and I don’t understand why. If i use a for-loop like this:

void setup()
{
  Serial.begin(9600);  // PC
  Serial2.begin(9600); // GSM-modem
  initGSM();
  for(int i=0;i<80;i++)
  {
    readSMS();
  }
}

… I do get all of it. Do i really have to run readSMS() in a loop to get all of the output? The size of int i decides how much of the SMS i get.

Am I doing something wrong when reading from the modem?

  char sms[200];
  Serial2.print("at+cmgr=1\r");
  if(Serial2.available())
  {
    *sms=Serial2.read();
    Serial.print(*sms);
  }

This code is garbage. You are assigning the first character in the sms array to one value read from the serial port. You are not NULL terminating the array. You are not printing it properly.

Well sorry about that, I seem to have copied the code from when I was testing.
It’s supposed to be like this:

void readSMS()
{
  char sms;
  Serial2.print("at+cmgr=1\r");
  if(Serial2.available())
  {
     sms=Serial2.read();
     Serial.print(sms);
  }
}

I think I realized what the problem was, Serial2.read() returns the first byte. So I tried this:

void readSMS()
{
  char sms;
  Serial2.print("at+cmgr=1\r");
  delay(200);
  if(Serial2.available())
  {
    for(int j=0;j<=Serial2.available();j++)
    {
     sms=Serial2.read();
     Serial.print(sms);
    }
  }
}

Now i get about half the message, but still not all of it. Serial.available is supposed to return the number of bytes ready to send, and since one letter is one byte, I thought this would work. Any ideas?

Serial.available is supposed to return the number of bytes ready to send, and since one letter is one byte, I thought this would work.

Serial.available() returns the number of bytes available to [u]read[/u]. The number that have been received, and are ready to read, bears no relationship to the number of bytes in the message, though.

Serial data transmission is like my typing. Pretty slow (although there is no use of the backspace key. Maybe if I could avoid that key more often...)

You need to figure out what the phone sends to indicate that the message has ended, and keep waiting/reading until that marker arrives.

Thank you for answering, after some more trial and error it seems like changing the if to a "while !=0" is working. I'm not sure if it'll always work, but for now it does the job nicely.

void readSMS()
{
  Serial2.print("at+cmgr=1\r");
  delay(200);
  while(Serial2.available()!=0)
  {
     Serial.print(byte(Serial2.read()));
  }
}

I'm not sure if it'll always work, but for now it does the job nicely.

It won't. What you should do is add ",DEC" to the Serial.print() statement, to see what actual characters are received. There should be some kind of end-of-message marker/value that you can read until you find.