GSM SM5100B C M E E R R O R : 4 error

mohammad picture mohammad · Mar 23, 2013 · Viewed 10.6k times · Source

I am using Arduino to control an SM5100B GSM device, everything works except when I want to send an SMS after receiving another. I get this,

Error code:

O K > + C M G S : 2 5 O K + C M E E R R O R : 4

My code for handling the aforementioned received SMS:

     #include <SoftwareSerial.h>  //Include the NewSoftSerial library to send serial commands to the cellular module. 
        char inchar;                //Will hold the incoming character from the Serial Port. 
        SoftwareSerial cell(2,3); 
        char mobilenumber[] = "0597010129";
        void setup() { 
        //GSM
        Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
        Serial.println("Initialize GSM module serial port for communication.");                       
        cell.begin(9600); 
        delay(35000); // give time for GSM module to register on network etc. 
        Serial.println("delay off");
        cell.println("AT+CMGF=1"); // set SMS mode to text 
        delay(200); 
        cell.println("AT+CNMI=3,3,0,0"); // set module to send SMS data to serial out upon receipt 
        delay(200); 
        } 



        void loop() {   

         if(cell.available() >0)//If a character comes in, from the cellular module
         { 
         inchar=cell.read(); 
         Serial.println(inchar); 
         if (inchar=='#'){ // OK - the start of our command 

           delay(10); 
           inchar=cell.read();
           Serial.println(inchar);  

             if (inchar=='a'){ 

               delay(10); 
               Serial.println("The folowing SMS : \n");
               inchar=cell.read();
               Serial.println(inchar); 

               if (inchar=='0'){ //sequance = #a0

                 Serial.println("#a0 was received"); 

             }
             else if (inchar=='1'){//sequance = #a1

                Serial.println("#a1 was received ");
                sendSms();

             }
         }
         cell.println("AT+CMGD=1,4");// AT command to delete all msgs
         Serial.println(" delete all SMS"); 
          } 
        }//end of  if(cell.available() >0) {...}
        }

        void sendSms(){
        //cell.println("AT+CMGF=1"); // set SMS mode to text 
        cell.print("AT+CMGS=");  // now send message... 
        cell.print((char)34); // ASCII equivalent of " 
        cell.print(mobilenumber); 
        cell.println((char)34);  // ASCII equivalent of " 
        delay(500); // give the module some thinking time 
        cell.print(":D hello m3alleg :D");   // our message to send 
        cell.println((char)26);  // ASCII equivalent of Ctrl-Z 
        delay(20000);
}

Answer

hlovdal picture hlovdal · Mar 23, 2013

General note about your handling of AT commands.

No, no, no! This way of doing it will never work reliably. You MUST wait for the > character to be be received before sending "text to send". Or actually it is not just the > character, it is four characters. Quote from 3GPP specification 27.005:

  • the TA shall send a four character sequence <CR><LF><greater_than><space> (IRA 13, 10, 62, 32) after command line is terminated with <CR>; after that text can be entered from TE to ME/TA.

(TA (terminal adapter) here means modem and TE (terminal equipment) the sender of AT commands)

For any abortable AT command (and 27.005 clearly states for AT+CMGS This command should be abortable.) the sending of any character will abort the operation of the command. To quote ITU V.250:

5.6.1 Aborting commands

...

Aborting of commands is accomplished by the transmission from the DTE to the DCE of any character.

(DCE (data communication equipment) here means modem and DTE (data terminal equipment) the sender of AT commands)

This means that when you send "text to send" before "\r\n> " is sent by the modem the command will be aborted. There is no way to wait "long enough" for expecting the response be send. You MUST read and parse the response text you get back from the modem.

The same applies for the final result code after each command (e.g. OK, ERROR, CME ERROR and a few more). For instance sending "AT+CMGF=1" and then sending the next command without first waiting for OK is begging for problems. So always when sending AT commands, you MUST wait for the final result code before sending the next command.

Please never, never use delay to wait for any AT command response. It's as useful as kicking dogs that stand in your way in order to get them to move. Yes it might actually work some times, but at some point you will be sorry for taking that approach...

Answer to your question.

Based on the response you get, I can see that your problem is not command abortion (although your parsing have serious problems as described above that you should fix), and the CME ERROR is your best clue. From section "9.2.1 General errors" in 27.007 it gives operation not supported as description for value 4.

27.005 states that:

If sending fails in a network or an ME error, final result code +CMS ERROR: is returned.

Notice that this is +CMS ERROR and not +CME ERROR, but it is applicable, see below.

I guess that sequence of actions is as following:

The AT command handling part of the SM100B GSM modem accepts the sms data and formats it in an appropriate format and sends it of to the part of the modem that communicates with the GSM network. It successfully send the sms data to the network and reports this back to the AT command handling part which then prints +CMGS: 25 and final result code OK. However after a short time the network sends back a rejection message for the sms, which is then given as the +CME ERROR response.

If my guess above is correct, should the response have been delivered as +CMS ERROR instead? No, because the final response has for the AT+CMGS command has already been given (OK), and returning multiple final result codes for a command should never be done (except by mistake (note 1)). And while +CME ERROR can replace the ERROR final result code, it is not only a final result code. From the AT+CMEE command description:

Set command disables or enables the use of result code +CME ERROR: as an indication of an error relating to the functionality of the MT. When enabled, MT related errors cause +CME ERROR: final result code instead of the regular ERROR final result code. ERROR is returned normally when error is related to syntax, invalid parameters, or TA functionality.

Thus +CME ERROR can both be an final result code as well as an unsolicited result code (possibly also an intermediate result code).

But could not the AT+CMGS command have waited to receive the network rejection and returned +CMS ERROR? Probably not. Without knowing too much about the network details of sms sending, it might be the case that rejection today might occur at a much later time than before. Such changes are sometimes a problem with GSM related AT commands which have an old heritage that was originally tightly tied to GSM behaviour which some times becomes less and less true as the technology moves to GPRS, UMTS, LTE, etc.

Note 1:

One of my former colleagues used to complain about the way the standard have specified voice call handling, because after a ATD1234; command you first get the final result code OK, and then later when the call is ended you get a new final result code NO CARRIER. This just horribly bad design, the call end indication should have been a specific unsolicited response and not a final response.

So to summarise

Your sms seems to be rejected by the network. Try to find out why. You also have some serious problems with your AT command handling that you should fix; there is no way to handle AT commands without reading and parsing the response text from the modem.