SIM900 GSM/GPRS not getting a proper AT+CREG? answer

Daniel picture Daniel · Jul 9, 2013 · Viewed 20.1k times · Source

I'm using an Arduino UNO with attached IComsat SIM900 GSM/GPRS shield. Using the following tutorial: Arduino Live GPS Tracker I'm stuck with the AT+CREG? command, which checks if the SIM-card is registered at the provider.

The following logic is used: In the GSM_HTTP.INO file within the "void setup()" function, the following line gets executed modem.checkNetwork();

void setup() {           
  Serial.begin(9600); 
  Serial.println("GM862 monitor");
  modem.switchOn();                   // switch the modem on
  delay(4000);                        // wait for the modem to boot
  modem.init();                       // initialize the GSM part of Module
  modem.version();                    // request modem version info
  while (!modem.isRegistered()) {
    delay(1000);
    modem.checkNetwork();             // check the network availability
  }
}

The function "checkNetwork()" is part of the included library GSM862.cpp and looks like this:

void GM862::checkNetwork() {
  char buf[BUF_LENGTH];
  char result;
  requestModem("AT+CREG?", 1000, true, buf);
  result = buf[21];

  if (result == '1') {
    state |= STATE_REGISTERED;
  }
  else {
    state &= ~STATE_REGISTERED;
  }
}

Now this is the important part: The value of "result" that gets received by the function "requestModem" returns cryptic values, but no netword status (number 0-5) which is why there is a endless loop trying to register without error or success message.

As this function gets the "buf" variable out of the function "requestModem" in GSM862.cpp, I've had a look at it as well:

byte GM862::requestModem(const char *command, uint16_t timeout, boolean check, char *buf) {

  byte count = 0;

  *buf = 0;

  modem->flush();
  modem->println(command);
  count = getsTimeout(buf, timeout);
  return count;
}

In order to have a look into the relevant variables for debugging purposes I've changed the last two functions into the following code:

-->checkNetwork

void GSM862::checkNetwork() {
  char buf[BUF_LENGTH];
  char result;
  requestModem("AT+CREG?", 1000, true, buf);
  result = buf[21];

  Serial.print("Debugging buf2:");
  Serial.print(buf[21]);
  Serial.print("Debugging buf2:");
  Serial.print(buf[1]);
  Serial.print("Debugging buf2:");
  Serial.print(buf[0]);
  Serial.print("Debugging result2:");
  Serial.println(result);

  if (result == '1') {
    state |= STATE_REGISTERED;

    Serial.println("Network registered, home network...");
  }
  else {
    state &= ~STATE_REGISTERED;

    if(result == '0'){
      Serial.println("Network not registered, not searching for a new operator to register to...");
    }
    if(result == '2'){
      Serial.println("Still searching for an operators network to register to...");
    }
    if(result == '3'){
      Serial.println("Network registration denied...");
    }
    if(result == '4'){
      Serial.println("Network registration state unknown, probably still starting up...");
    }
    if(result == '5'){
      Serial.println("Network registered, roaming...");
    }
  }
}

--> request Modem

byte GSM862::requestModem(const char *command, uint16_t timeout, boolean check, char *buf) {

  byte count = 0;

  *buf = 0;

  modem->flush();
  modem->println(command);
  count = getsTimeout(buf, timeout);

  Serial.print("Debugging command1:");
  Serial.println(command);
  Serial.print("Debugging count1:");
  Serial.println(count);
  Serial.print("Debugging buf1:");
  Serial.println(buf);
  Serial.print("Debugging timeout1:");
  Serial.println(timeout);

  return count;
}

Like I've mentioned above, it seems that the value out of "result" of the function "checkNetwork" which is actually the value of "buf[21]", displays a cryptic value when displayed on the terminal via Serial.println();

Do you have any idea why or what the exact problem is?

Answer

FlegmatoidZoid picture FlegmatoidZoid · Jun 18, 2014

Network registration information (CREG) output depends on modem configuration.

  1. By sending "AT+CREG=0" one can disable network registration code (which is your case)
  2. By sending "AT+CREG=1" one can enable network registration
  3. By sending "AT+CREG=2" one can enable network registration code with
    location information (location area code and cell ID)

Options 2. and 3. will also automatically emit +CREG messages upon modem boot/network change.


ps: one should not forget to save current AT configuration by executing AT&W

more details on CREG can be found in "SIM900 AT COMMAND MANUAL"