I thought to share my recent experience with working with SIM800L modem. I've had two SIM800 modems installed in production use (remote temperature control with SMS messages) for two years without any stability issues. Recently I got a batch of new SIM800L modem evaluation breakouts from China and ran into four different issues while using SMS.
Below it is shown how I am currently dealing with these problems. The examples assume that all these functions belong to a class "GSM" that I've defined (but of course you can drop the class if that does not work in your case).
I'm using Arduino Mega and modem is connected to Serial1. Modem is powered with 2A power source separate from Arduino but sharing a common ground. This solution has worked stable before so I believe these are not power issues. The SW revision of my modem is "Revision:1418B04SIM800L24".
The solutions are not elegant and it would be great if someone could provide better solutions for these issues.
- Modem loses network connection (led blinks rapidly as it seems that modem tries to recover) and does not automatically recover.
Current solution:
Check every four minutes if modem is connected to network (with command "AT+CREG?" modem should answer "CREG: 0,1") and if not then do a soft reset with "CFUN" command. Command "AT+CFUN=1,1" can be used to reset module purposely at minimum/full functionality mode. Recovery from this takes about 20 seconds in my case (before you can issue new commands).
-
Modem is connected to network but gives a busy signal and SMS's are not received. No connection or call is actually active.
Solution:
Give periodically command "ATH" to drop all the existing connections. -
Modem receives the SMS but has gone back to PDU (non text mode) and thus reading the SMS does not work.
Solution:
Give periodically "AT+CMGF=1" command to keep modem in text mode.
The code below is now run once per four minutes to try to keep the modem operational.
boolean GSM::checkModem()
{
char *ptr, inChar, inputString[50] = "";
int i = 0;
unsigned long start;
sendcommand("AT"); // make sure the baud rate is recognized
delay(300);
sendcommand("ATH"); // drop any ongoing calls (sometimes 800L gets stuck)
delay(2000);
sendcommand("AT+CMGF=1"); // try to keep modem in text mode (drops for some reason)
delay(1000);
sendcommand("AT+CREG?"); // check if modem is registered in network
start=millis();
while (millis() - start < 1000) { // https://www.gammon.com.au/millis
while (Serial1.available()) {
// get the new byte:
inChar = (char)Serial1.read();
inputString[i]=inChar;
inputString[i+1]='\0';
i++;
// if the incoming character is a newline, check if modem has answered OK
if (inChar == '\n') {
ptr = strstr(inputString, "CREG: 0,1"); // check if modem registered
inputString[0]='\0'; // clear the input string for next round of reading
i=0;
if (ptr) {
return true; // modem is registered
} // ptr
} // if \n
// if we for some reason are reading too many characters flush the buffer
else if (i == 48) {
Serial1.flush();
inputString[0]='\0'; // clear the input string for next round of reading
i=0;
}
} // while serial available
} // while start < time modem has 1 second to confirm if it is connected to network
return false; // modem has not confirmed that it is in network
}
If the the previous command returns "false" then cycle functionality of modem
// routine for re-setting (cycling from minimum to full functionality) with
// command "AT+CPOW=1,1". Recovery takes about 20 seconds - Give it 40 secs
// before attempting other commands
void GSM::resetModem()
{
sendcommand("AT+CFUN=1,1"); // this resets the modem - takes 20 secs when tested
return;
}
// routine for sending commands to SIM800L
void GSM::sendcommand(char *cmd) {
Serial1.print(cmd); // issue command
Serial1.write(0x0D); // Carriage Return
}
- deleting the last SMS fails (I prefer to delete the SMS after reading and use only memory position 1).
Solution:
Try deleting SMS once a minute with command "AT+CMGD=1". Check if deletion of SMS is successful (check for "OK" answer from modem). If not then try again after a minute (I'm not posting "checkOK()" code here cause this post is already quite long. Can add if someone needs it). After five consecutive fails (and if more than 1 hour since last restart) restart the modem with command "AT+CPOW=1". Modem restart back to fully functional takes 1 min 15 sec in my case (can vary). Give it at least two minutes before sending new commands. In my case it seems that second SMS deletion attempt (1 minute after first) works and I have not observed modem restarts (but I am not tracking it constantly so it could have restarted without me knowing.)
boolean GSM::deletefirstSMS(void)
{
sendcommand("AT+CMGD=1"); // delete SMS from memory position 1
if(checkOK()) return true; // check if modem responds "OK" within a second
else return false;
}
void GSM::restartModem()
{
sendcommand("AT+CPOW=1"); // this resets the modem - takes 1 min 15 secs when tested
return;
}
With these tricks the modem now seems to work "good enough" as I am normally only sending max a few SMS commands/day. Therefore it is unlikely that the modem is power cycling on the very moment I am sending the command. If you need 100% responsive system then you need a more stable version of the modem. Modem firmware can be updated but I've not found good information of where to find and which SW version to use.

