RAK5860 stuck on "Waiting for registration", Hologram Ping LTE

I am using a RAK5860 in conjunction with a RAK4630 using a RAK5005 baseboard.
I am trying to connect to the Hologram network using a sim card they provided.
Running the example code from the RAK Arduino sketch “Hologram_Ping_LTE” results in the following output, getting stuck at the “waiting for registration” step:

23:42:31.720 -> BG77 LTE ping test!
23:42:31.720 -> Modem response after start:
23:42:31.720 -> ATI

23:42:31.720 -> Quectel
23:42:31.720 -> BG77
23:42:31.720 -> Revision: BG77LAR02A04
23:42:31.720 -> 
23:42:31.720 -> OK
23:42:31.720 -> 
23:42:35.730 -> BG77 power up!
23:42:37.177 -> AT+CMEE=2

23:42:37.177 -> OK
23:42:37.177 -> 
23:42:38.580 -> AT+CFUN=1,0

23:42:38.580 -> OK
23:42:38.580 -> 
23:42:40.513 -> AT+QCFG="iotopmode",0,1

23:42:40.513 -> OK
23:42:40.513 -> 
23:42:42.512 -> AT+QICSGP=1,1,"hologram","","",1

23:42:42.512 -> OK
23:42:42.512 -> 
23:42:42.512 -> Waiting for registration

Here is the code used, found at [WisBlock/Hologram_Ping_LTE.ino at master · RAKWireless/WisBlock · GitHub] (WisBlock/Hologram_Ping_LTE.ino at master · RAKWireless/WisBlock · GitHub)

/**
 * @file BG77_Hologram_Ping.ino
 * @author rakwireless.com
 * @brief RAK4631 + RAK5860 BG77 module product testing
 * @version 0.1
 * @date 2021-01-26
 * 
 * @copyright Copyright (c) 2021
 * 
 * @note RAK5005-O GPIO mapping to RAK4631 GPIO ports
   RAK5005-O <->  nRF52840
   IO1       <->  P0.17 (Arduino GPIO number 17)
   IO2       <->  P1.02 (Arduino GPIO number 34)
   IO3       <->  P0.21 (Arduino GPIO number 21)
   IO4       <->  P0.04 (Arduino GPIO number 4)
   IO5       <->  P0.09 (Arduino GPIO number 9)
   IO6       <->  P0.10 (Arduino GPIO number 10)
   SW1       <->  P0.01 (Arduino GPIO number 1)
   A0        <->  P0.04/AIN2 (Arduino Analog A2
   A1        <->  P0.31/AIN7 (Arduino Analog A7
   SPI_CS    <->  P0.26 (Arduino GPIO number 26) 
 */
#include <Adafruit_TinyUSB.h>

#define BG77_POWER_KEY 17
char cArr[128] = {0};
String bg_rsp = "";
bool bg_timeout = false;

//this function is suitable for most AT commands of bg96. e.g. bg96_at("ATI")
boolean bg_at(char *at, uint16_t timeout)
{
  bg_rsp = "";
  char tmp[256] = {0};
  int len = strlen(at);
  strncpy(tmp, at, len);
  uint16_t t = timeout;
  tmp[len] = '\r';
  Serial1.write(tmp);
  delay(10);
  while (t--)
  {
    if (Serial1.available())
    {
      bg_rsp += char(Serial1.read());
    }
    delay(1);
  }
  if( bg_rsp.length() > 0 )
    bg_timeout = false;
  else
    bg_timeout = true;
  return bg_timeout;
}

void deact(void)
{
  // deactivate PDP
  bg_at("AT+QIDEACT=1" ,1500);
  // Set minimal UE Functionality
  bg_at("AT+CFUN=0,0" ,1500); 
}

void setup()
{
  bool reg= false;
  bool pdp_active = false;
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    delay(10);
  Serial.println("BG77 LTE ping test!");
  // Check if the modem is already awake
  time_t timeout = millis();
  bool moduleSleeps = true;
  Serial1.begin(115200);
  delay(1000);
  Serial1.println("ATI");
  //BG77 init
  while ((millis() - timeout) < 6000)
  {
    if (Serial1.available())
    {
      String result = Serial1.readString();
      Serial.println("Modem response after start:");
      Serial.println(result);
      moduleSleeps = false;
    }
  }
  if (moduleSleeps)
  {
    // Module slept, wake it up
    pinMode(BG77_POWER_KEY, OUTPUT);
    digitalWrite(BG77_POWER_KEY, 0);
    delay(1000);
    digitalWrite(BG77_POWER_KEY, 1);
    delay(2000);
    digitalWrite(BG77_POWER_KEY, 0);
    delay(1000);
  }
  Serial.println("BG77 power up!");
  
// Verbose Error Reporting to get understandable error reporting 
  bg_timeout = bg_at("AT+CMEE=2" ,1500);
  if ( bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 ) 
      Serial.println(bg_rsp); 

  }
  else
    return;
    
// Set full UE Functionality
  bg_timeout = bg_at("AT+CFUN=1,0" ,1400);
  if (bg_timeout == false) 
  {
    if ( bg_rsp.indexOf('OK') > 0 ) 
      Serial.println(bg_rsp);
  }
  else
    return;
    
// Set eMTC LTE mode
  bg_timeout = bg_at("AT+QCFG=\"iotopmode\",0,1",2000);
  if ( bg_timeout == false )
  {
    if ( bg_rsp.indexOf('OK') > 0 )   
      Serial.println(bg_rsp);
  }
  else
    return;

  // Set the APN to "hologram" with no username or password.
  // Configure parameters of a TCP/IP context
  bg_timeout = bg_at("AT+QICSGP=1,1,\"hologram\",\"\",\"\",1" ,2000);
  if (bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 )  
      Serial.println(bg_rsp);
  }  
  else
    return;
  
  Serial.println("Waiting for registration");
  do 
  {
    reg=false;
    bg_timeout = bg_at("AT+CREG?",2000);
    if ( bg_timeout == false )
    {
        int v =  bg_rsp.indexOf('0,');
        if ( v > 0 )
        {
          if ( bg_rsp[v+1] == '5' )
          {
            reg = true;
            Serial.println("Registered: Roaming");
          } 
          else if ( bg_rsp[v+1] == '1' )
          {
            reg = true;
            Serial.println("Registered: Home");
          }
      
        } 
    }
      
    delay(200);
     
  } while (!reg);

 // Get NW INFO
  Serial.println("Waiting for NW Info");
  do {
    reg=false;
    bg_timeout = bg_at("AT+QNWINFO",1000);
    if ( bg_timeout == false )
    {
      int v = bg_rsp.indexOf('eMTC');
      if ( v >0 )
      {
        reg = true;
        Serial.println(bg_rsp); 
      }
      else 
      { 
        v = bg_rsp.indexOf('ervice'); 
        if ( v >0 )
          Serial.println("No service"); 
      }
     
    }   
    delay(200);
     
  } while (!reg);

// Check if PDP IPV4 is activated
// Don't send data if PDP is deactivated

  pdp_active = false;
  bg_timeout = bg_at("AT+QIACT?",1500);
  if ( bg_timeout == false )
  {
    if ( bg_rsp.indexOf(',1,1') > 0 )
    {
      pdp_active = true;
      Serial.println("PDP is activated");
    }
  }
  else
    return;

// Don't send PDP activate command if PDP is already activated

  if (  pdp_active == false )
  {
 
    Serial.println("Activating PDP");
    do {
        reg=false;
        bg_timeout = bg_at("AT+QIACT=1",1500);
        if ( bg_timeout == false )
        {
          if ( bg_rsp.indexOf('OK') >0 )
          {
            reg = true;
            Serial.println(bg_rsp); 
          }
 
        }
      delay(200);
     
    } while (!reg);

  }

  
}

void loop()
{
  int timeout = 100;
  int retry = 3;
  String resp = "";
  String snd = "";
  int v;
 
//  char cArr[128] = {0};
  if (bg_timeout == true)
  {
    Serial.print("Timeout during initialization");
    while(1);
  }
  delay(100);

  while ( retry--)
  {
    Serial.println("Sending ping");
    bg_at( "AT+QPING=1,\"baidu.com\",15,1",5000 );
    if ( bg_timeout == false )
    {
      v = bg_rsp.indexOf('RROR');
      if ( v > 0)
      {
        Serial.println( "Ping error...retry" );
        continue;
      }
      // Result => 0 received the ping response from the server
      v = bg_rsp.indexOf('+QPING: 0,"');
      if ( v >0 )
        v = bg_rsp.indexOf('+QPING: 0,1,1');       
      if ( v >0 )
      {
        Serial.println( "1 ping sent 1 ping received" );
        break;
      }
    }
    delay(200);
  } // retry--
  
  Serial.println("Waiting AT command");
  while (1)
  {
    timeout = 100;
  
    while (timeout--)
    {
      if (Serial1.available() > 0)
      {
        resp += char(Serial1.read());
      }
      if (Serial.available() > 0)
      {
        snd += char(Serial.read());
      }
      delay(1);
    }
    if (resp.length() > 0)
    {
      Serial.print(resp);
    }
    if (snd.length() > 0)
    {
      memset(cArr, 0, 128);
      snd.toCharArray(cArr, snd.length() + 1);
      Serial1.write(cArr);
      delay(10);
    }
    resp = "";
    snd = "";
  }
}

Hello @zacksahnger

I guess you’ve verified the eMTC coverage in your country, yes?

And you have activated your SIM card, yes?

You could try to execute below command to see what’s available in your area:

AT+COPS=?

Please note that this command can take several minutes to finish.

Thanks
Felix

I’m based in the US, and have eMTC coverage. The sim card has been activated. Here is the view from the dashboard.

It seems to be connected and has transmitted one packet (I think using the TCP sketch).
Even so, I’m still having the “Waiting for registration” issue.

I tried running AT+COPS=? and got no response from the module, using AT+COPS gave an empty response. Here is the output from the serial monitor:

13:40:34.027 -> BG77 LTE ping test!
13:40:34.027 -> Modem response after start:
13:40:34.027 -> ATI

13:40:34.027 -> Quectel
13:40:34.027 -> BG77
13:40:34.027 -> Revision: BG77LAR02A04
13:40:34.027 -> 
13:40:34.027 -> OK
13:40:34.027 -> 
13:40:38.019 -> BG77 power up!
13:40:39.503 -> AT+CMEE=2

13:40:39.503 -> OK
13:40:39.503 -> 
13:40:40.898 -> AT+CFUN=1,0

13:40:40.898 -> OK
13:40:40.898 -> 
13:40:42.835 -> AT+QCFG="iotopmode",0,1

13:40:42.835 -> OK
13:40:42.835 -> 
13:40:44.823 -> AT+QICSGP=1,1,"hologram","","",1

13:40:44.823 -> OK
13:40:44.823 -> 
13:40:47.335 -> AT+CPIN?

13:40:47.335 -> +CPIN: READY
13:40:47.335 -> 
13:40:47.335 -> OK
13:40:47.335 -> 
13:40:49.804 -> AT+QNWINFO

13:40:49.804 -> +QNWINFO: "eMTC","310410","LTE BAND 12",5110
13:40:49.804 -> 
13:40:49.804 -> OK
13:40:52.326 -> AT+QCSQ

13:40:52.326 -> +QCSQ: "eMTC",-69,-99,81,-16
13:40:52.326 -> 
13:40:52.326 -> OK
13:40:52.326 -> 
13:40:54.816 -> AT+CSQ

13:40:54.816 -> +CSQ: 22,99
13:40:54.816 -> 
13:40:54.816 -> OK
13:40:54.816 -> 
13:40:54.816 -> Seeing what's available
13:41:47.214 -> AT+COPS

13:41:47.214 -> OK
13:41:47.214 -> 
13:41:47.214 -> Waiting for registration

I’ve added a few more AT commands to show connection information, here’s the updated code:

/**
 * @file BG77_Hologram_Ping.ino
 * @author rakwireless.com
 * @brief RAK4631 + RAK5860 BG77 module product testing
 * @version 0.1
 * @date 2021-01-26
 * 
 * @copyright Copyright (c) 2021
 * 
 * @note RAK5005-O GPIO mapping to RAK4631 GPIO ports
   RAK5005-O <->  nRF52840
   IO1       <->  P0.17 (Arduino GPIO number 17)
   IO2       <->  P1.02 (Arduino GPIO number 34)
   IO3       <->  P0.21 (Arduino GPIO number 21)
   IO4       <->  P0.04 (Arduino GPIO number 4)
   IO5       <->  P0.09 (Arduino GPIO number 9)
   IO6       <->  P0.10 (Arduino GPIO number 10)
   SW1       <->  P0.01 (Arduino GPIO number 1)
   A0        <->  P0.04/AIN2 (Arduino Analog A2
   A1        <->  P0.31/AIN7 (Arduino Analog A7
   SPI_CS    <->  P0.26 (Arduino GPIO number 26) 
 */
#include <Adafruit_TinyUSB.h>

#define BG77_POWER_KEY 17
char cArr[128] = {0};
String bg_rsp = "";
bool bg_timeout = false;

//this function is suitable for most AT commands of bg96. e.g. bg96_at("ATI")
boolean bg_at(char *at, uint16_t timeout)
{
  bg_rsp = "";
  char tmp[256] = {0};
  int len = strlen(at);
  strncpy(tmp, at, len);
  uint16_t t = timeout;
  tmp[len] = '\r';
  Serial1.write(tmp);
  delay(10);
  while (t--)
  {
    if (Serial1.available())
    {
      bg_rsp += char(Serial1.read());
    }
    delay(1);
  }
  if( bg_rsp.length() > 0 )
    bg_timeout = false;
  else
    bg_timeout = true;
  return bg_timeout;
}

void deact(void)
{
  // deactivate PDP
  bg_at("AT+QIDEACT=1" ,1500);
  // Set minimal UE Functionality
  bg_at("AT+CFUN=0,0" ,1500); 
}

void setup()
{
  bool reg= false;
  bool pdp_active = false;
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    delay(10);
  Serial.println("BG77 LTE ping test!");
  // Check if the modem is already awake
  time_t timeout = millis();
  bool moduleSleeps = true;
  Serial1.begin(115200);
  delay(1000);
  Serial1.println("ATI");
  //BG77 init
  while ((millis() - timeout) < 6000)
  {
    if (Serial1.available())
    {
      String result = Serial1.readString();
      Serial.println("Modem response after start:");
      Serial.println(result);
      moduleSleeps = false;
    }
  }
  if (moduleSleeps)
  {
    // Module slept, wake it up
    pinMode(BG77_POWER_KEY, OUTPUT);
    digitalWrite(BG77_POWER_KEY, 0);
    delay(1000);
    digitalWrite(BG77_POWER_KEY, 1);
    delay(2000);
    digitalWrite(BG77_POWER_KEY, 0);
    delay(1000);
  }
  Serial.println("BG77 power up!");
  
// Verbose Error Reporting to get understandable error reporting 
  bg_timeout = bg_at("AT+CMEE=2" ,1500);
  if ( bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 ) 
      Serial.println(bg_rsp); 

  }
  else
    return;
    
// Set full UE Functionality
  bg_timeout = bg_at("AT+CFUN=1,0" ,1400);
  if (bg_timeout == false) 
  {
    if ( bg_rsp.indexOf('OK') > 0 ) 
      Serial.println(bg_rsp);
  }
  else
    return;
    
// Set eMTC LTE mode
  bg_timeout = bg_at("AT+QCFG=\"iotopmode\",0,1",2000);
  if ( bg_timeout == false )
  {
    if ( bg_rsp.indexOf('OK') > 0 )   
      Serial.println(bg_rsp);
  }
  else
    return;

  // Set the APN to "hologram" with no username or password.
  // Configure parameters of a TCP/IP context
  bg_timeout = bg_at("AT+QICSGP=1,1,\"hologram\",\"\",\"\",1" ,2000);
  if (bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 )  
      Serial.println(bg_rsp);
  }  
  else
    return;
      bg_at("AT+CPIN?", 500);
      
  delay(2000);
  Serial.println(bg_rsp);
  bg_at("AT+QNWINFO", 500);
  delay(2000);
  Serial.println(bg_rsp);
  bg_at("AT+QCSQ", 500);
  delay(2000);
  Serial.println(bg_rsp);
  bg_at("AT+CSQ", 500);
  delay(2000);
  Serial.println(bg_rsp);


    Serial.println("Seeing what's available");
  //bg_timeout = bg_at("AT+COPS=?" ,150000000);
  bg_timeout = bg_at("AT+COPS" ,150000000);
  if (bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 )  
      Serial.println(bg_rsp);
  }  

  Serial.println("Waiting for registration");
  do 
  {
    reg=false;
    bg_timeout = bg_at("AT+CREG?",20000);
    if ( bg_timeout == false )
    {
        int v =  bg_rsp.indexOf('0,');
        if ( v > 0 )
        {
          if ( bg_rsp[v+1] == '5' )
          {
            reg = true;
            Serial.println("Registered: Roaming");
          } 
          else if ( bg_rsp[v+1] == '1' )
          {
            reg = true;
            Serial.println("Registered: Home");
          }
      
        } 
    }
      
    delay(200);
     
  } while (!reg);

 // Get NW INFO
  Serial.println("Waiting for NW Info");
  do {
    reg=false;
    bg_timeout = bg_at("AT+QNWINFO",1000);
    if ( bg_timeout == false )
    {
      int v = bg_rsp.indexOf('eMTC');
      if ( v >0 )
      {
        reg = true;
        Serial.println(bg_rsp); 
      }
      else 
      { 
        v = bg_rsp.indexOf('ervice'); 
        if ( v >0 )
          Serial.println("No service"); 
      }
     
    }   
    delay(200);
     
  } while (!reg);

// Check if PDP IPV4 is activated
// Don't send data if PDP is deactivated

  pdp_active = false;
  bg_timeout = bg_at("AT+QIACT?",1500);
  if ( bg_timeout == false )
  {
    if ( bg_rsp.indexOf(',1,1') > 0 )
    {
      pdp_active = true;
      Serial.println("PDP is activated");
    }
  }
  else
    return;

// Don't send PDP activate command if PDP is already activated

  if (  pdp_active == false )
  {
 
    Serial.println("Activating PDP");
    do {
        reg=false;
        bg_timeout = bg_at("AT+QIACT=1",1500);
        if ( bg_timeout == false )
        {
          if ( bg_rsp.indexOf('OK') >0 )
          {
            reg = true;
            Serial.println(bg_rsp); 
          }
 
        }
      delay(200);
     
    } while (!reg);

  }

  
}

void loop()
{
  int timeout = 100;
  int retry = 3;
  String resp = "";
  String snd = "";
  int v;
 
//  char cArr[128] = {0};
  if (bg_timeout == true)
  {
    Serial.print("Timeout during initialization");
    while(1);
  }
  delay(100);

  while ( retry--)
  {
    Serial.println("Sending ping");
    bg_at( "AT+QPING=1,\"baidu.com\",15,1",5000 );
    if ( bg_timeout == false )
    {
      v = bg_rsp.indexOf('RROR');
      if ( v > 0)
      {
        Serial.println( "Ping error...retry" );
        continue;
      }
      // Result => 0 received the ping response from the server
      v = bg_rsp.indexOf('+QPING: 0,"');
      if ( v >0 )
        v = bg_rsp.indexOf('+QPING: 0,1,1');       
      if ( v >0 )
      {
        Serial.println( "1 ping sent 1 ping received" );
        break;
      }
    }
    delay(200);
  } // retry--
  
  Serial.println("Waiting AT command");
  while (1)
  {
    timeout = 100;
  
    while (timeout--)
    {
      if (Serial1.available() > 0)
      {
        resp += char(Serial1.read());
      }
      if (Serial.available() > 0)
      {
        snd += char(Serial.read());
      }
      delay(1);
    }
    if (resp.length() > 0)
    {
      Serial.print(resp);
    }
    if (snd.length() > 0)
    {
      memset(cArr, 0, 128);
      snd.toCharArray(cArr, snd.length() + 1);
      Serial1.write(cArr);
      delay(10);
    }
    resp = "";
    snd = "";
  }
}

When I run

    Serial.println("Seeing what's available");
  bg_timeout = bg_at("AT+COPS=?" ,1500000000);
  if (bg_timeout == false )
  { 
    if ( bg_rsp.indexOf('OK') > 0 )  
      Serial.println(bg_rsp);
  }  

  Serial.println("Waiting for registration");

the output is

13:50:13.890 -> Seeing what's available
13:50:25.655 -> Waiting for registration

As you can see, there is no output from AT+COPS=?

Hello @zacksahnger

hmm, not sure what’s going on here. One more thing though, is the LTE antenna properly attached to the LTE connector on the board?

Thanks
Felix

Looking at these lines from the output:

13:40:49.804 -> +QNWINFO: "eMTC","310410","LTE BAND 12",5110
13:40:49.804 -> 
13:40:49.804 -> OK
13:40:52.326 -> AT+QCSQ

13:40:52.326 -> +QCSQ: "eMTC",-69,-99,81,-16

the AT+QCSQ command shows the following
-69 = LTE RSSI (received signal strength)

-99 = LTE RSRP(reference signal received power)

81 = LTE SINR (signal to interference plus noise ratio)

-16 = LTE RSRQ (reference signal received quality.

Which would seem to indicate some form of connectivity, which makes me assume the antenna is functioning correctly.
Is there any direction you could point me in towards further narrowing down potential issues?

Hello @zacksahnger

I think you are correct. Sorry I’ve missed that. I wonder if the response to AT+CREG? somehow is different from what the code expects. Maybe add a debug output line to see what the actual response to AT+CREG? is? Or try to see what happens if you comment out the do while (!reg) block dealing with AT+CREG??

BTW: you should also see from the green LED whether the module is still searching or not. From the Quectel_BG77_Hardware_Design_V1.2.pdf document:

- Flicker slowly (200 ms High/1800 ms Low) → Network searching
- Flicker slowly (1800 ms High/200 ms Low) → Idle
- Flicker quickly (125 ms High/125 ms Low) → Data transfer is ongoing
- Always high → Voice calling

Thanks
Felix

I ended up getting around this by ditching the sample code and writing my own.
I could never get a response to AT+COPS=? through arduino, but using quectel’s qnavigator I was able to talk to the bg77 directly and get the response no problem (after downloading the required drivers).
My final solution was to reference Quectel’s manual for HTTP PUTs, using the AT commands provided there.
Hope this helps anyone stuck in a similar situation.