Rak5860 Unable to run sample code - USA - CatM1 - Hologram

Hello,
I am running the sample code “Hologram_TCP”. I have filled in my correct Device Key. The device is connected to cellular (according to hologram), but I dont see any data coming through in the Hologram logs.

Here is the output from the Arduino Console:

AT+CPIN?

+CPIN: READY

OK

APP RDY

AT+QNWINFO

+QNWINFO: "eMTC","310260","LTE BAND 12",5035

OK
AT+QCSQ

+QCSQ: "eMTC",-86,-111,136,-12

OK


+CSQ: 15,99

OK


OK


OK

Send test data to Hologram via TCP!

OK

+QIOPEN: 0,565


+QGPSLOC: 200501.000,2957.7815N,9813.4475W,3.6,352.3,3,0.00,0.0,0.0,

OK

{"k":"eOhYKlms","d":2957.7815N,9813.4475W,"t":"TOPIC1"}


Send test data to Hologram via TCP!

OK


+QGPSLOC: 201038.000,2957.7871N,9813.4546W,1.6,346.8,3,0.00,0.0,0.0


OK

{"k":"eOhYKlms","d":2957.7871N,9813.4546W,"t":"TOPIC1"}

When I check the log in Hologram to see if the device successful transmitted data, I don’t see anything. The last message I see was from a month ago when I did a SIM swap. See below:

Here is the code I am currently running:

/**
   @file Hologram_Tcp.ino
   @author rakwireless.com
   @brief BG77 tcp test with Hologram, send gps data to server
   @version 0.1
   @date 2020-12-28
   @copyright Copyright (c) 2020
**/
#include <Adafruit_TinyUSB.h>


#define BG77_POWER_KEY WB_IO1
#define BG77_GPS_ENABLE WB_IO2

String bg77_rsp = "";

//Hologarm tcp message format is jason. Remember to replace the card key in type k. 
//About key details: https://support.hologram.io/hc/en-us/articles/360035212714-Device-keys
//About message details: https://www.hologram.io/references/embedded-apis#send-a-message-to-the-hologram-cloud 
String hologram_msg_pre = "{\"k\":\"eOhYKlms\",\"d\":";
String hologram_msg_suff = ",\"t\":\"TOPIC1\"}";
String hologram_msg = "";
String send_data_length_at = "";
String gps_data = "";

void setup()
{
	time_t serial_timeout = millis();
	Serial.begin(115200);
	while (!Serial)
	{
		if ((millis() - serial_timeout) < 5000)
		{
        delay(100);
    }
    else
    {
        break;
    }
	}
	Serial.println("RAK11200 Cellular TEST With Hologram sim card!");

	//BG77 init , Check if the modem is already awake
  time_t timeout = millis();
  bool moduleSleeps = true;
  Serial1.begin(115200);
  delay(1000);
  pinMode(BG77_GPS_ENABLE, OUTPUT);
  digitalWrite(BG77_GPS_ENABLE, 1);
  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!");

  //active and join to the net, this part may depend on some information of your operator.
	bg77_at("AT+CFUN=1,0", 500);
	delay(2000);
	bg77_at("AT+CPIN?", 500);
	delay(2000);
	bg77_at("AT+QNWINFO", 500);
	delay(2000);
	bg77_at("AT+QCSQ", 500);
	delay(2000);
	bg77_at("AT+CSQ", 500);
	delay(2000);
	bg77_at("AT+QIACT=1", 3000);
	delay(2000);

  //open tcp link with Hologram server
  bg77_at("AT+QIOPEN=1,0,\"TCP\",\"cloudsocket.hologram.io\",9999,0,1", 5000);
  delay(2000);
  
}
void parse_gps()
{
   int index1 = gps_data.indexOf(',');

   if(strstr(gps_data.c_str(),"E") != NULL)
   {
      int index2 = gps_data.indexOf('E'); 
      gps_data = gps_data.substring(index1+1,index2+1); 
   }
   if(strstr(gps_data.c_str(),"W") != NULL)
   {
      int index3 = gps_data.indexOf('W'); 
      gps_data = gps_data.substring(index1+1,index3+1);       
   }   
   
}


void get_gps()
{
  int gps_count = 300;
  int timeout = 1000;
  while(gps_count--)
  {
    Serial1.write("AT+QGPSLOC?\r");
    timeout = 1000;
    while (timeout--)
    {
      if (Serial1.available())
      {
         gps_data += char(Serial1.read());
      }
      delay(1);
    }
    if(strstr(gps_data.c_str(),"CME ERROR") != NULL)
    {
      gps_data = "";
      continue;
    }      
    if(strstr(gps_data.c_str(),"E") != NULL || strstr(gps_data.c_str(),"W") != NULL)
    {
      Serial.println(gps_data);
      parse_gps();
      break;
    }      
  }
}


//this function is suitable for most AT commands of bg96. e.g. bg96_at("ATI")
void bg77_at(char *at, uint16_t timeout)
{
	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())
		{
			bg77_rsp += char(Serial1.read());
		}
		delay(1);
	}
	Serial.println(bg77_rsp);
	bg77_rsp = "";
}

void send_test_data()
{
  //open gps, gsm/nb will stop work now
  bg77_at("AT+QGPS=1,1", 20000);
  //get gps data, this will cost some time
  get_gps();
  //close gps
  bg77_at("AT+QGPSEND", 2000);  
  //combine the data packet
  hologram_msg = hologram_msg_pre+gps_data+hologram_msg_suff;
  Serial.println(hologram_msg);
  gps_data = "";
  //send data length command
  char tmp[256] = {0};
  send_data_length_at = "AT+QISEND=0," + hologram_msg.length();
  strncpy(tmp, send_data_length_at.c_str(), send_data_length_at.length());
  bg77_at(tmp, 3000);
  delay(2000);
  //send data
  memset(tmp,0,256);
  strncpy(tmp, hologram_msg.c_str(), hologram_msg.length());
  bg77_at(tmp, 1000);
  delay(1000);
}

void loop()
{
	Serial.println("Send test data to Hologram via TCP!");
	send_test_data();
  //consider the gps fix time, interval should be long
  delay(300000);
}

Any thoughts on how to get data to post on Hologram?

For a quick test, I just loaded the “Hologram_Ping_LTE” sample code. It looks like the ping is passing here…

Modem response after start:
ATI

Quectel
BG77
Revision: BG77LAR02A04

OK

BG77 power up!
AT+CMEE=2

OK

AT+CFUN=1,0

OK

AT+QCFG="iotopmode",0,1

OK

AT+QICSGP=1,1,"hologram","","",1

OK

Waiting for registration
Registered: Roaming
Waiting for NW Info
AT+QNWINFO

+QNWINFO: "eMTC","310260","LTE BAND 12",5035

OK
Activating PDP
AT+QIACT=1

OK

Sending ping
1 ping sent 1 ping received
Waiting AT command

+QIURC: "pdpdeact",1

Here is the code for ping:

/**
 * @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 = "";
  }
}