Randomly receiving error while sending SMS (+CMS ERROR: 2162)

I am doing a simply Sketch that sends an SMS when a button is pressed. Using Arduino UNO with Arduino GSM shield (Quectel chip) Here the code:

#include <GSM.h>

GSM gsmAccess(true);
GSMScanner scannerNetworks; //Used to demonstrate that there is network connection
GSM_SMS sms;

const int BUTTON = 8;

int buttonVal = 0;
int buttonOldVal = 0;

char remoteNbr[20] = "##########"; //remote phone number
char textMessage[140] = "Txt";

void setup (){
  Serial.begin(9600);
  Serial.println("Send SMS when click on button");
  scannerNetworks.begin();
  
  pinMode(BUTTON, INPUT); //Initialize the BUTTON pin
  
  boolean notConnected = true;
  
  // Connect to the GSM network
  while(notConnected){
    if(gsmAccess.begin() == GSM_READY) //Note: PIN # not required
      notConnected = false;
    else {
      Serial.println("Not connected, trying again");
      delay(1000);
    }
  }
  
  Serial.println("GSM initialized, and connected to the network");
  Serial.println("Waiting for button presses");
    
}

void loop(){
    
  buttonVal = digitalRead(BUTTON);

  if((buttonVal == LOW) && (buttonOldVal == HIGH)){ //With Parallax 5 position switch: if LOW = activated, HIGH = not activated
    sendSMS();
    delay(10);
  }
  
  if((buttonVal == HIGH) && (buttonOldVal == LOW))
    delay(10);
  
  buttonOldVal = buttonVal; 
  
}


void sendSMS(){
  
  Serial.println("\nSENDING SMS");
  
  int result = -1;
  
  sms.beginSMS(remoteNbr);
  sms.print(textMessage);
  result = sms.endSMS();
  if(result == 1){
    Serial.println("MESSAGE SENT");
  } else {
    Serial.print("SENDING ERROR: ");
    Serial.println(result);
    Serial.print("Current carrier: ");
    Serial.println(scannerNetworks.getCurrentCarrier());
    Serial.print("Signal Strength: ");
    Serial.println(scannerNetworks.getSignalStrength());
  }
  
}

I can connect to the network and when I click the button, most of the times the message is correctly sent, but randomly I get the following an error message (i.e. sms.endSMS() returns 0). The debug gives me the following (from my Serial Monitor):

SENDING SMS
AT+CMGS="#########"%13%
88 92>%13%%10%>
Txt%26%%13%
88 112>%13%%10%> %13%%10%+CMS ERROR: 2162%13%%10%
SENDING ERROR: 0
Current carrier: AT+COPS?%13%%10%T-Mobile USA
Signal Strength: AT+CSQ%13%%10%11

I couldn't find any reference to a error code +CMS ERROR: 2162

Does anybody have an idea of what this is? Where can I find a list of all error codes?

Or is the expectation that I should include retries in my code?

Any help greatly appreciated.

Thanks

Hello!

We've been re-reading our old books on GSM. When talking with the base station the modem accesses first a common channel using an aloha-like protocol. It uses this channel to request a stable channel. But two requests may collide on the air at the same time. In that case both messages and the base station understands nothing. When the modems don't receive any answer from base they wait for a random and re-send the message. They repeat this process until they get an answer from base station, but there is a limit of retries. When the limit is reached the modem gives you an error message, v.g. 2162.

So, the deep meaning is that you're area is quite crowded with GSM devices (over 25% of total capacity)

You can try two things:
1st: simply capture the error at sketch level and try again.
2nd, configure your modem so it retries more times

  • Open the SoftwareSerialExample
  • Modify it so it runs at 9600 bps
  • Execute it on your Arduino.
  • Run the Serial Monitor, 9600 bps, NL&CR
  • Press (for 1'') the shield Power button until the status led lights up
  • Now you can type commands to the modem. Type AT (CR) twice. See that the modem answers OK.
  • Type AT+CRLP?
  • You'll get something like +CRLP: 61,61,128,6,0,3
  • The fourth parameter is the number of retries. You can modify that parameter, for example to 10, executing:
    AT+CRLP=61,61,128,10,0,3
    OK
  • check the new settings with AT+CRLP? again
  • Execute AT&W so the configuration is saved

We can not verify easily the effectivity of this solution, as our cell is not crowded. So it'd great if you can check if the above sequence improves your effectivity. In any case this modification will only reduce your failure ratio, but will not make the failures disappear.

Thank you for the reply!

First a couple of notes for people that might read this in the future: when modifying the SoftwareSerialExample and you are using the Arduino GSM shield, you also have to change the RX and TX pins to be 2 and 3 in the constructor of SoftwareSerial, as the shield communicates on these two pins. So:

SoftwareSerial mySerial(2, 3);

I tried modifying the retry of the modem, but it did not help much (I tried 10 times and 15 times). It actually appeared to be worse as it failed more often (but no scientific proof, just a feeling I had).

I noticed that the error appears to happens when I leave it idle for some few seconds (e.g. >10 secs). If I receive an error, and I press the button immediately after, it works, and it will continue to work if I do not let it sit idle. What I will probably do, is a retry mechanism in the sketch.

In the meantime, zorzano or others, if you have other ideas that could be linked to the fact of it being idle would be great to know.

After further trials, I found out that it is sufficient to do a retry in the sketch and it works 100% of the time at the 1st retry, at 2 second interval after the initial error (I tried 1 second and it was not sufficient).

At this point I am convinced that it has something to do with the modem "waking up" after some idle time and for some reason it cannot connect to the radio.

Here the code of the sendSMS() function with the workaround:

void sendSMS(){

  int result = -1;
  int i = 0;
  
  Serial.println("\nSENDING SMS");
    
  sms.beginSMS(remoteNbr);
  sms.print(textMessage);
  result = sms.endSMS(); //first try
  
  for(i = 0; i < MAX_RETRIES && result != 1; i++){ // if there was an error try again MAX_RETRIES times
    Serial.println("Error, trying again...");
    delay(WAIT_FOR_RETRY);
    sms.beginSMS(remoteNbr);
    sms.print(textMessage);
    result = sms.endSMS();
  }
  
  if(result == 1){
    Serial.println("MESSAGE SENT: ");
  } else {
    Serial.print("SENDING ERROR: ");
    Serial.println(result);
  }
  
}

It may be something particular here in the US and to the T-Mobile network (AWS/UMTS Band IV).