Questions that come up related to SIM 800/900 modules often use single Serial.println("AT_COMMAND_EXAMPLE"); lines for AT command execution, usually delays inserted between them and not checking the response for each command at all!
As different commands execution time can vary greatly and each response from the module contains valuable information, this is far from reliable communication with such modules. Furthermore one particular command can take very different times, for example establishing a GPRS connection can vary between 2-8 seconds based on my experiences (or not connected at all, which situation also has to be handled).
If someone is aiming for a better solution, than just sending the commands blindly, here is a simple function (found at first a long-long time ago in the hidden depths of cyberspace) for response checking with timeout:
bool sendATcommand(const char* ATcommand, const char* expected_answer, const unsigned long timeout)
{
const uint8_t RESPONSE_SIZE = 160;
//response array could be made global
char response[RESPONSE_SIZE];
bool answer = false;
uint8_t respx = 0;
unsigned long previous = 0ul;
//clear whole array
memset(response, '\0', RESPONSE_SIZE);
//clean the input buffer (with timeout)
previous = millis();
while ( (Serial.available() > 0) && ((millis() - previous) < 1000ul) )
{
Serial.read();
}
//send the AT command
Serial.println(ATcommand);
previous = millis();
//this loop waits for the answer with timeout
do
{
if (Serial.available() != 0)
{
//if there is data in the UART input buffer, reads it and checks for the answer
response[respx] = Serial.read();
respx++;
//prevent buffer overflow
if (respx >= RESPONSE_SIZE)
{
respx = RESPONSE_SIZE - 1;
}
//check if the desired answer is in the response of the module
if (strstr(response, expected_answer) != NULL)
{
answer = true;
}
}
}
while (!answer && ((millis() - previous) < timeout));
//terminate the string, respx was limited to (RESPONSE_SIZE - 1)
response[respx] = '\0';
return answer;
}
This is intended to be just an example to encourage users to develop their AT commands usage.
Any location/service provider dependent stuff has to be solved by the users.
Another advice is to always check the module's AT Command Manual!
M2MSupport is also a good relevant page.
After having this (or any similar) function, for example a simple network registered check would look like:
if (sendATcommand("AT+CREG?", "+CREG: 0,1", 1000ul)
{
//registered, home network
}
else if (sendATcommand("AT+CREG?", "+CREG: 0,5", 1000ul)
{
//registered, roaming
}
else
{
//not registered
}