GSM module SIM 900 Problem to send SMS (FIXED VERSION)

Hello !

I had already created a topic on this subject a few weeks ago, but I just realized that the tutorial link I sent had nothing to do with the topic. I am so sorry, so here is the fixed version.

I would like to test the GSM SIM900 module as part of my internship project.

Here is the tutorial I followed:

https://lastminuteengineers.com/sim900-gsm-shield-arduino-tutorial/

To help me, my internship supervisor sent me the same module, and I also bought a Things.mobile SIM card which is compatible with multiple carriers for my project. I then created an account on thingsmobile.com in order to activate the package of my card.

image

In addition, I made sure to deactivate it by integrating it into my mobile phone, so that the GSM module program could reactivate it afterwards once inserted.

So, I placed it in the SIM card holder, then I turned the SIM900 up / down programmatically by making its connections with an Arduino UNO. I reproduced the assembly below with 4 wires, and supplied the module with a 5V Adapter.

image

First, I tested the "Arduino Code - Testing AT Commands" program from the tutorial in question.

Here is the program I used:

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM900
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

void setup()
{
  SIM900power();
  
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM900
  mySerial.begin(9600);

  Serial.println("Initializing...");
  delay(1000);

  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();
  mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  updateSerial();
  mySerial.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  mySerial.println("AT+CREG?"); //Check whether it has registered in the network
  updateSerial();
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

void SIM900power()
{
  pinMode(9, OUTPUT); 
  digitalWrite(9,LOW);
  delay(1000);
  digitalWrite(9,HIGH);
  delay(2000);
  digitalWrite(9,LOW);
  delay(3000);
}

First of all, we observe that in the output concerning the AT + CSQ line, the signal strength corresponds to 0dB. However, it should be equal to or greater than 5 according to the tutorial.

Then, concerning the AT + CREG line? to connect to the NETWORK, the first answer displays as the second number "2". However, it is different from 1 and 5 and this means that we would not be connected to a network even though the netlight LED flashes every 3 seconds.
However, we observe another response from CREG displaying only the number "5". Does this mean that I am connected to a foreign network (I live in France by the way)?

Now I want to realize the program to send an SMS to my cell phone. Here then is the 2nd program that I use:

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM900
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

void setup()
{
  SIM900power();
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM900
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
  delay(1000);

  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+330686920417\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("Bonjour"); //text content
  updateSerial();
  mySerial.write(26);
}

void loop()
{
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

void SIM900power()
{
  pinMode(9, OUTPUT); 
  digitalWrite(9,LOW);
  delay(1000);
  digitalWrite(9,HIGH);
  delay(2000);
  digitalWrite(9,LOW);
  delay(3000);
}

Then I uploaded it: there is indeed LED D6 which ends up finding the network by flashing every 3 seconds. But by displaying the serial monitor, I only get part of the expected results and I am not receiving text messages on my cell phone.

image

I have also tried replacing "+3306 ..." with "+336 ..." (because displaying phone number in that way is different in France), but I got the same problem.

But as we can see:
-Command "T" is displayed instead of "AT" at the start of the serial monitor
-The results of the "+ CMGS" command are missing immediately after the display of the message to be sent on the serial monitor. I think the problem would come from there.

I also suppose that the first AT commands test's results could be related to the reason why I can't send SMS to my cellphone.

Could someone help me solve the problem please? How to fix the number issues for the AT+CSQ and AT+CREG? lines ?

Thank you for responding to me quickly.

CMGS sends a reply to an SMS in memory. The argument is the index in memory of the SMS. To send to a phone number you want:
AT+CMGW="phone number"\rmessage(ESC)
That will reply with the number of the memory location where your messages is saved:
+GMGW: n
You save that 'n' and use the "AT+CMSS=n" command to send the message.

Hello, thank you for your answer.

If I have well understood, you advise me to use AT+CMGW instead of AT+CMGS for writing the phone number ?

Could you write please a code snippet of your idea so I could better understand ?

And what do you think about the results of the AT commands test ?

Oops... Nevermind. I was accidentally looking at the documentation for:
AT+CMGS=">1"
and not:
AT+CMGS="phonenumber"

I think you are using the CMGS command correctly.

So, what kind of problem I have instead ? Do you believe it might related to the result of the AT command testing ?

Here is a sketch I wrote to provide more information about what was being sent an received. Give it a try to see if any of the AT commands are failing:

#include <SoftwareSerial.h>

SoftwareSerial ATCommandStream(7, 8);
unsigned long ATComandBaudRate = 9600;

const char * DestinationNumber = "+330686920417";
const char * SMSMessage = "Bonjour";

void setup()
{
  // start th serial communication with the host computer
  Serial.begin(115200);
  while (!Serial);
  delay(200);
  Serial.println("Sketch started.");

  // Power up the SIM900
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(9, HIGH);
  delay(2000);
  digitalWrite(9, LOW);
  delay(3000);

  ATCommandStream.begin(ATComandBaudRate);
  Serial.print("ATCommandStream started at baud rate ");
  Serial.println(ATComandBaudRate);


  SendShortCommand("AT"); // Just checking that it responds with OK
  SendShortCommand("AT+CMEE"); // Turn on verbose messages

  SendShortCommand("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  SendShortCommand("AT+CCID"); //Read SIM information to confirm whether the SIM is plugge
  SendShortCommand("AT+CREG?"); //Check whether it has registered in the network

  SendShortCommand("AT+CSCS=\"GSM\""); // Set character set to GSM
  SendShortCommand("AT+CSTA?");  // Check the phone number type
  Serial.println("Note: 129=Unknown, 161=National, 145=International, 177=Network Specific");

  SendSMSMessage(DestinationNumber, SMSMessage);

  SendShortCommand("AT"); // Just checking that it still responds with OK
}

void loop() {}

bool WaitForResponse()
{
  unsigned long startTime = millis();
  while (millis() - startTime < 5000)
  {
    String reply = ATCommandStream.readStringUntil('\n');
    if (reply.length() > 0)
    {
      Serial.print("Received: \"");
      Serial.print(reply);
      Serial.println("\"");

      if (reply.startsWith("OK"))
        return true;

      if (reply.startsWith("ERROR"))
        return false;
    }
  }

  return false;
}

bool SendShortCommand(String command)
{
  Serial.print("Sending command: \"");
  Serial.print(command);
  Serial.println("\"");

  ATCommandStream.print(command);
  ATCommandStream.print("\r\n");

  if (WaitForResponse())
  {
    return true;
  }
  else
  {
    Serial.print("ERROR or timeout waiting for response to \"");
    Serial.print(command);
    Serial.println("\"");
  }
  return false;
}

void SendSMSMessage(const char *number, const char *message)
{
  Serial.println("Sending SMS text");

  if (!SendShortCommand("AT + CMGF = 1")) // Set the SMS output to text mode
  {
    Serial.println("Error in CMGF = 1 (setting to text mode)");
    return;
  }

  if (!SendShortCommand("AT + CMGS = ? ")) // Test for CMGS command support:
  {
    Serial.println("Error in CMGS = ? (testing for CMGS support)");
    return;
  }

  Serial.print("Sending : ");
  Serial.print("AT + CMGS = \"");
  Serial.print(number);
  Serial.println("\"(CR)");
  Serial.print(message); // The SMS text you want to send
  Serial.println("(EM)");

  ATCommandStream.print("AT+CMGS=\"");  // Send SMS
  ATCommandStream.print(number);
  ATCommandStream.print("\"\r"); // NOTE: Command ends with CR, not CRLF
  ATCommandStream.print(message); // The SMS text you want to send
  ATCommandStream.write(26); // ASCII EndMessage (EM) CTRL+Z character

  if (!WaitForResponse())
    Serial.println("ERROR or timeout waiting for response to CMGS command");
}

Thanks for the code.

If I have well understood, does this code, in theory, must do both the AT commands testing and the SMS sending message ?

I'm just starting to learn about AT commands, you know

Yes. It will try to do all the setup and try to send "Bonjour" to +330686920417.

Hello !

I tried the program you sent me (with and without removing the first 0 from my phone number because french telephony works differently), but it still didn't work.

I first started without the first 0, and here's the result I got:

image

And then I compiled by adding the first 0:

image

In both case when I display the serial monitor to try this program, the Netlight LED will blink every 3 secondes, but I still didn't receive any message.

I also tried again by modifying the program a little and replacing "number" by "DestinationNumber" and "message" by "SMSMessage" for the last code snippets:

#include <SoftwareSerial.h>

SoftwareSerial ATCommandStream(7, 8);
unsigned long ATComandBaudRate = 9600;

const char * DestinationNumber = "+33686920417";
const char * SMSMessage = "Bonjour";

void setup()
{
  // start th serial communication with the host computer
  Serial.begin(115200);
  while (!Serial);
  delay(200);
  Serial.println("Sketch started.");

  // Power up the SIM900
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(9, HIGH);
  delay(2000);
  digitalWrite(9, LOW);
  delay(3000);

  ATCommandStream.begin(ATComandBaudRate);
  Serial.print("ATCommandStream started at baud rate ");
  Serial.println(ATComandBaudRate);


  SendShortCommand("AT"); // Just checking that it responds with OK
  SendShortCommand("AT+CMEE"); // Turn on verbose messages

  SendShortCommand("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  SendShortCommand("AT+CCID"); //Read SIM information to confirm whether the SIM is plugge
  SendShortCommand("AT+CREG?"); //Check whether it has registered in the network

  SendShortCommand("AT+CSCS=\"GSM\""); // Set character set to GSM
  SendShortCommand("AT+CSTA?");  // Check the phone number type
  Serial.println("Note: 129=Unknown, 161=National, 145=International, 177=Network Specific");

  SendSMSMessage(DestinationNumber, SMSMessage);

  SendShortCommand("AT"); // Just checking that it still responds with OK
}

void loop() {}

bool WaitForResponse()
{
  unsigned long startTime = millis();
  while (millis() - startTime < 5000)
  {
    String reply = ATCommandStream.readStringUntil('\n');
    if (reply.length() > 0)
    {
      Serial.print("Received: \"");
      Serial.print(reply);
      Serial.println("\"");

      if (reply.startsWith("OK"))
        return true;

      if (reply.startsWith("ERROR"))
        return false;
    }
  }

  return false;
}

bool SendShortCommand(String command)
{
  Serial.print("Sending command: \"");
  Serial.print(command);
  Serial.println("\"");

  ATCommandStream.print(command);
  ATCommandStream.print("\r\n");

  if (WaitForResponse())
  {
    return true;
  }
  else
  {
    Serial.print("ERROR or timeout waiting for response to \"");
    Serial.print(command);
    Serial.println("\"");
  }
  return false;
}

void SendSMSMessage(const char *DestinationNumber, const char *SMSMessage)
{
  Serial.println("Sending SMS text");

  if (!SendShortCommand("AT + CMGF = 1")) // Set the SMS output to text mode
  {
    Serial.println("Error in CMGF = 1 (setting to text mode)");
    return;
  }

  if (!SendShortCommand("AT + CMGS = ? ")) // Test for CMGS command support:
  {
    Serial.println("Error in CMGS = ? (testing for CMGS support)");
    return;
  }

  Serial.print("Sending : ");
  Serial.print("AT + CMGS = \"");
  Serial.print(DestinationNumber);
  Serial.println("\"(CR)");
  Serial.print(SMSMessage); // The SMS text you want to send
  Serial.println("(EM)");

  ATCommandStream.print("AT+CMGS=\"");  // Send SMS
  ATCommandStream.print(DestinationNumber);
  ATCommandStream.print("\"\r"); // NOTE: Command ends with CR, not CRLF
  ATCommandStream.print(SMSMessage); // The SMS text you want to send
  ATCommandStream.write(26); // ASCII EndMessage (EM) CTRL+Z character

  if (!WaitForResponse())
    Serial.println("ERROR or timeout waiting for response to CMGS command");
}

But still the same problem and here's what I got without the first 0 of my phone number:

image

Is there a problem related to what I obtain in the serial monitor ?

Thanks in advance if you have an idea...

It looks like the data returning from the SIM900 is complete garbage. Are you sure the SIM900 is set to 9600 baud?

Well, the program is built to work with 9600 baud.

Are you telling me there is a way to guess in how many baud the sim900 GSM module work ? If yes, how do we modify it ?

The SIM900 default baud rate is 19200. Try changing the line:
unsigned long ATComandBaudRate = 9600;
to:
unsigned long ATComandBaudRate = 19200;

If that doesn't work you will have to try all the usual baud rates until you find the one that works.

Hello again.

I tried to modify the caud by changing the baud rate (without the first 0 of my phone number for each), but it still didn't work.

Here's the results I got:

ATComand Baud Rate = 14400

image

ATComand Baud Rate = 19200

image

ATComand Baud Rate = 28800

image

ATComand Baud Rate = 38400

image

ATComand Baud Rate = 57600

image

ATComand Baud Rate = 115200

image

I'm so unlucky :pensive:
I made sure the Netlight LED was blinking each 3 seconds to detect the network, but it's like I receive random results.

Is this new code okay if I remove the first 0 of my phone number by the way ?

Also, I don't understand what these code snippets do to the program:

void SendSMSMessage(const char *number, const char *message)
{
  Serial.println("Sending SMS text");

  if (!SendShortCommand("AT + CMGF = 1")) // Set the SMS output to text mode
  {
    Serial.println("Error in CMGF = 1 (setting to text mode)");
    return;
  }

  if (!SendShortCommand("AT + CMGS = ? ")) // Test for CMGS command support:
  {
    Serial.println("Error in CMGS = ? (testing for CMGS support)");
    return;
  }

  Serial.print("Sending : ");
  Serial.print("AT + CMGS = \"");
  Serial.print(number);
  Serial.println("\"(CR)");
  Serial.print(message); // The SMS text you want to send
  Serial.println("(EM)");

  ATCommandStream.print("AT+CMGS=\"");  // Send SMS
  ATCommandStream.print(number);
  ATCommandStream.print("\"\r"); // NOTE: Command ends with CR, not CRLF
  ATCommandStream.print(message); // The SMS text you want to send
  ATCommandStream.write(26); // ASCII EndMessage (EM) CTRL+Z character

  if (!WaitForResponse())
    Serial.println("ERROR or timeout waiting for response to CMGS command");
}

Why replacing "DestinationNumber" by "number" and "SMSMessage" by "message" ?

It looks like something is wrong with the serial connection from the Arduino to the PC. Serial Monitor is not receiving all of the characters the Arduino is sending. What you are SUPPOSED to see is something like:

Sketch started.
ATCommandStream started at baud rate nnnn
Sending command: "AT"
Received: "OK"
Sending command: "AT+CMEE"
Received: "OK"
Sending command: "AT+CSQ"
Received: "+CSQ=27"
Received: "OK"

The fact that some of the characters sent by the sketch are not showing up in Serial Monitor means that there is probably something wrong in the connection from the Arduino to the PC.

I tried a SIM900A module some time ago and faced the same problem - only garbage in return on the serial interface. Tried different baud rates, stop bits etc. I gave up and archived the module in the garbage bin.

Where did you buy it?

Hello, it's been a while.

Good new: I finally managed to modify the program by activiting the SIM card with the hardware trigger and it worked ! I managed to send the SMS.

Here is the code I used !

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM900
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

void setup()
{
  //SIM900power();
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM900
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
  delay(1000);

  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+33686920417\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("YO"); //text content
  updateSerial();
  mySerial.write(26);
}

void loop()
{
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

//void SIM900power()
//{
  //pinMode(9, OUTPUT); 
  //digitalWrite(9,LOW);
  //delay(1000);
  //digitalWrite(9,HIGH);
  //delay(2000);
  //digitalWrite(9,LOW);
  //delay(3000);
//}

I simply removed the SIM900power () function which would permits the program to activate the SIM card without needing to push the button.

However, I need to activate by software and without using the button, and I noticed that we needed to solder the R13 SMD jumper on the shield (look at the part named Software trigger in the tutorial).

The GSM module shield I used was originally sent by my internship tutor alongside with a lot of other stuff for my project. I took a picture about the R13 emplacement.

![image|317x393](upload://7EU0ei8BwgBc34dQHXqI6OcvlqU.jpeg

We could see a component here, but I don't know if it is well soldered as aked on the tuto or not.
If it's not, what kind of tools would you advise me to do it ?

Also, for the TX RX jumpers, should I move them for using D1 and D0 instead of D7 and D8 ?

image

I used D7 and D8 for activating the SIM card with the button, and it worked well.