GPS Example isn't working, nothing in serial log or console

Also your github code and the docs on the rak website are different I believe, which one should I use and is the most up to date?

Hi @a1projects ,

To send packets, you need to orient your wisblock module properly just like what you did before. Also, it is really hard to troubleshoot if we don’t have logs. I already see GPS coordinates in your log last time. We should see that again and see the packets going to TTN.

Can you help me point the difference you said? I’ll check and update if necessary. Thank you.

First Code

/**
 * @file GPS_Tracker.ino
 * @author rakwireless.com
 * @brief This sketch demonstrate a GPS tracker that collect location from a uBlox M7 GNSS sensor
 *    and send the data to lora gateway.
 *    It uses a 3-axis acceleration sensor to detect movement of the tracker
 * @version 0.2
 * @date 2021-04-30
 * 
 * @copyright Copyright (c) 2020
 * 
 * @note RAK4631 GPIO mapping to nRF52840 GPIO ports
   RAK4631    <->  nRF52840
   WB_IO1     <->  P0.17 (GPIO 17)
   WB_IO2     <->  P1.02 (GPIO 34)
   WB_IO3     <->  P0.21 (GPIO 21)
   WB_IO4     <->  P0.04 (GPIO 4)
   WB_IO5     <->  P0.09 (GPIO 9)
   WB_IO6     <->  P0.10 (GPIO 10)
   WB_SW1     <->  P0.01 (GPIO 1)
   WB_A0      <->  P0.04/AIN2 (AnalogIn A2)
   WB_A1      <->  P0.31/AIN7 (AnalogIn A7)
 */

#include <Arduino.h>
#include <LoRaWan-RAK4630.h> //http://librarymanager/All#SX126x
#include <SPI.h>
#include "SparkFunLIS3DH.h" //http://librarymanager/All#SparkFun-LIS3DH
#include "Wire.h"
#include <TinyGPS.h>        //http://librarymanager/All#TinyGPS

LIS3DH SensorTwo(I2C_MODE, 0x18);

TinyGPS gps;

String tmp_data = "";
int direction_S_N = 0;  //0--S, 1--N
int direction_E_W = 0;  //0--E, 1--W

// RAK4630 supply two LED
#ifndef LED_BUILTIN
#define LED_BUILTIN 35
#endif

#ifndef LED_BUILTIN2
#define LED_BUILTIN2 36
#endif

bool doOTAA = true;   // OTAA is used by default.
#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 60                     /**< Maximum number of events in the scheduler queue. */
#define LORAWAN_DATERATE DR_0                   /*LoRaMac datarates definition, from DR_0 to DR_5*/
#define LORAWAN_TX_POWER TX_POWER_5             /*LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15*/
#define JOINREQ_NBTRIALS 3                      /**< Number of trials for the join request. */
DeviceClass_t gCurrentClass = CLASS_A;          /* class definition*/
LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_US915;    /* Region:EU868*/
lmh_confirm gCurrentConfirm = LMH_UNCONFIRMED_MSG;          /* confirm/unconfirm packet definition*/
uint8_t gAppPort = LORAWAN_APP_PORT;                      /* data port*/

/**@brief Structure containing LoRaWan parameters, needed for lmh_init()
 */
static lmh_param_t lora_param_init = {LORAWAN_ADR_ON, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_OFF};

// Foward declaration
static void lorawan_has_joined_handler(void);
static void lorawan_join_failed_handler(void);
static void lorawan_rx_handler(lmh_app_data_t *app_data);
static void lorawan_confirm_class_handler(DeviceClass_t Class);
static void send_lora_frame(void);

/**@brief Structure containing LoRaWan callback functions, needed for lmh_init()
*/
static lmh_callback_t lora_callbacks = {BoardGetBatteryLevel, BoardGetUniqueId, BoardGetRandomSeed,
                                        lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler, lorawan_join_failed_handler
                                       };
                                       
//OTAA keys !!!! KEYS ARE MSB !!!!

// ABP keys
uint32_t nodeDevAddr = 0x260116F8;
uint8_t nodeNwsKey[16] = {0x7E, 0xAC, 0xE2, 0x55, 0xB8, 0xA5, 0xE2, 0x69, 0x91, 0x51, 0x96, 0x06, 0x47, 0x56, 0x9D, 0x23};
uint8_t nodeAppsKey[16] = {0xFB, 0xAC, 0xB6, 0x47, 0xF3, 0x58, 0x45, 0xC7, 0x50, 0x7D, 0xBF, 0x16, 0x8B, 0xA8, 0xC1, 0x7C};

// Private defination
#define LORAWAN_APP_DATA_BUFF_SIZE 64                     /**< buffer size of the data to be transmitted. */
#define LORAWAN_APP_INTERVAL 10000                        /**< Defines for user timer, the application data transmission interval. 10s, value in [ms]. */
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE];        //< Lora user application data buffer.
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0}; //< Lora user application data structure.

TimerEvent_t appTimer;
static uint32_t timers_init(void);
static uint32_t count = 0;
static uint32_t count_fail = 0;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  // Initialize Serial for debug output
  time_t timeout = millis();
  Serial.begin(115200);
  while (!Serial)
  {
    if ((millis() - timeout) < 5000)
    {
      delay(100);
    }
    else
    {
      break;
    }
  }

  // Initialize LoRa chip.
  lora_rak4630_init();

  Serial.println("=====================================");
  Serial.println("Welcome to RAK4630 LoRaWan!!!");
  if (doOTAA)
  {
    Serial.println("Type: OTAA");
  }
  else
  {
    Serial.println("Type: ABP");
  }

  switch (gCurrentRegion)
  {
    case LORAMAC_REGION_AS923:
      Serial.println("Region: AS923");
      break;
    case LORAMAC_REGION_AU915:
      Serial.println("Region: AU915");
      break;
    case LORAMAC_REGION_CN470:
      Serial.println("Region: CN470");
      break;
  case LORAMAC_REGION_CN779:
    Serial.println("Region: CN779");
    break;
    case LORAMAC_REGION_EU433:
      Serial.println("Region: EU433");
      break;
    case LORAMAC_REGION_IN865:
      Serial.println("Region: IN865");
      break;
    case LORAMAC_REGION_EU868:
      Serial.println("Region: EU868");
      break;
    case LORAMAC_REGION_KR920:
      Serial.println("Region: KR920");
      break;
    case LORAMAC_REGION_US915:
      Serial.println("Region: US915");
    break;
  case LORAMAC_REGION_RU864:
    Serial.println("Region: RU864");
    break;
  case LORAMAC_REGION_AS923_2:
    Serial.println("Region: AS923-2");
    break;
  case LORAMAC_REGION_AS923_3:
    Serial.println("Region: AS923-3");
    break;
  case LORAMAC_REGION_AS923_4:
    Serial.println("Region: AS923-4");
      break;
  }
  Serial.println("=====================================");

  //lis3dh init
  if (SensorTwo.begin() != 0)
  {
    Serial.println("Problem starting the sensor at 0x18.");
  }
  else
  {
    Serial.println("Sensor at 0x18 started.");
  // Set low power mode
  uint8_t data_to_write = 0;
  SensorTwo.readRegister(&data_to_write, LIS3DH_CTRL_REG1);
  data_to_write |= 0x08;
  SensorTwo.writeRegister(LIS3DH_CTRL_REG1, data_to_write);
  delay(100);

  data_to_write = 0;
  SensorTwo.readRegister(&data_to_write, 0x1E);
  data_to_write |= 0x90;
  SensorTwo.writeRegister(0x1E, data_to_write);
  delay(100);
  }
  //gps init

  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, 0);
  delay(1000);
  digitalWrite(WB_IO2, 1);
  delay(1000);
  
  Serial1.begin(9600);
  while (!Serial1);
  Serial.println("gps uart init ok!");
  
  //creat a user timer to send data to server period
  uint32_t err_code;

  err_code = timers_init();
  if (err_code != 0)
  {
    Serial.printf("timers_init failed - %d\n", err_code);
    return;
  }

  // Setup the EUIs and Keys
  if (doOTAA)
  {
    lmh_setDevEui(nodeDeviceEUI);
    lmh_setAppEui(nodeAppEUI);
    lmh_setAppKey(nodeAppKey);
  }
  else
  {
    lmh_setNwkSKey(nodeNwsKey);
    lmh_setAppSKey(nodeAppsKey);
    lmh_setDevAddr(nodeDevAddr);
  }

  // Initialize LoRaWan
  err_code = lmh_init(&lora_callbacks, lora_param_init, doOTAA, gCurrentClass, gCurrentRegion);
  if (err_code != 0)
  {
    Serial.printf("lmh_init failed - %d\n", err_code);
    return;
  }

  // Start Join procedure
  lmh_join();
}

void loop()
{
  // Put your application tasks here, like reading of sensors,
  // Controlling actuators and/or other functions. 
}

/**@brief LoRa function for handling HasJoined event.
 */
void lorawan_has_joined_handler(void)
{
  if(doOTAA == true)
  {
  Serial.println("OTAA Mode, Network Joined!");
  }
  else
  {
    Serial.println("ABP Mode");
  }

  lmh_error_status ret = lmh_class_request(gCurrentClass);
  if (ret == LMH_SUCCESS)
  {
    delay(1000);
    TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
    TimerStart(&appTimer);
  }
}
/**@brief LoRa function for handling OTAA join failed
*/
static void lorawan_join_failed_handler(void)
{
  Serial.println("OTAA join failed!");
  Serial.println("Check your EUI's and Keys's!");
  Serial.println("Check if a Gateway is in range!");
}
/**@brief Function for handling LoRaWan received data from Gateway
 *
 * @param[in] app_data  Pointer to rx data
 */
void lorawan_rx_handler(lmh_app_data_t *app_data)
{
  Serial.printf("LoRa Packet received on port %d, size:%d, rssi:%d, snr:%d, data:%s\n",
          app_data->port, app_data->buffsize, app_data->rssi, app_data->snr, app_data->buffer);
}

void lorawan_confirm_class_handler(DeviceClass_t Class)
{
  Serial.printf("switch to class %c done\n", "ABC"[Class]);
  // Informs the server that switch has occurred ASAP
  m_lora_app_data.buffsize = 0;
  m_lora_app_data.port = gAppPort;
  lmh_send(&m_lora_app_data, gCurrentConfirm);
}

void send_lora_frame(void)
{
  if (lmh_join_status_get() != LMH_SET)
  {
    //Not joined, try again later
    return;
  }

  lmh_error_status error = lmh_send(&m_lora_app_data, gCurrentConfirm);
  if (error == LMH_SUCCESS)
  {
    count++;
    Serial.printf("lmh_send ok count %d\n", count);
  }
  else
  {
    count_fail++;
    Serial.printf("lmh_send fail count %d\n", count_fail);
  }
  TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
  TimerStart(&appTimer);
}

/**@brief Function for analytical direction.
 */
void direction_parse(String tmp)
{
    if (tmp.indexOf(",E,") != -1)
    {
        direction_E_W = 0;
    }
    else
    {
        direction_E_W = 1;
    }
    
    if (tmp.indexOf(",S,") != -1)
    {
        direction_S_N = 0;
    }
    else
    {
        direction_S_N = 1;
    }
}

/**@brief Function for handling a LoRa tx timer timeout event.
 */
String data = "";
void tx_lora_periodic_handler(void)
{ 
  float x = 0;
  float y = 0;
  float z = 0;

  bool newData = false;
  
  Serial.println("check acc!");
  x = SensorTwo.readFloatAccelX() * 1000;
  y = SensorTwo.readFloatAccelY() * 1000;
  z = SensorTwo.readFloatAccelZ() * 1000;
  data = "X = " + String(x) + "mg" + " Y = " + String(y) + "mg" + " Z =" + String(z) + "mg";
  Serial.println(data);
  data = "";
  if( abs(x-z) < 400)
  {
    // For one second we parse GPS data and report some key values
    for (unsigned long start = millis(); millis() - start < 1000;)
    {
      while (Serial1.available())
      {
        char c = Serial1.read();
//         Serial.write(c); // uncomment this line if you want to see the GPS data flowing
        tmp_data += c;
        if (gps.encode(c))// Did a new valid sentence come in?
          newData = true;
      }
    }
    direction_parse(tmp_data);
    tmp_data = "";
    float flat, flon;
    int32_t ilat, ilon;
    if (newData)
    {
      unsigned long age;  
      gps.f_get_position(&flat, &flon, &age);
      flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat;
      ilat = flat * 100000;
      flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon;
      ilon = flon * 100000;
      memset(m_lora_app_data.buffer, 0, LORAWAN_APP_DATA_BUFF_SIZE);
      m_lora_app_data.port = gAppPort;
      m_lora_app_data.buffer[0] = 0x09;
      //lat data
      m_lora_app_data.buffer[1] = (ilat & 0xFF000000) >> 24;
      m_lora_app_data.buffer[2] = (ilat & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[3] = (ilat & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[4] =  ilat & 0x000000FF;
      if(direction_S_N == 0)
      {
        m_lora_app_data.buffer[5] = 'S';    
      }
      else
      {
        m_lora_app_data.buffer[5] = 'N';    
      }
      //lon data
      m_lora_app_data.buffer[6] = (ilon & 0xFF000000) >> 24;
      m_lora_app_data.buffer[7] = (ilon & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[8] = (ilon & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[9] =  ilon & 0x000000FF;
      if(direction_E_W == 0)
      {
        m_lora_app_data.buffer[10] = 'E';
      }
      else
      {
        m_lora_app_data.buffer[10] = 'W';
      }
      m_lora_app_data.buffsize = 11;
      send_lora_frame();
    }
    else
    {
      Serial.println("No Location Found");
      TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
      TimerStart(&appTimer);
    }
  }
  else
  {
    Serial.println("Turn WisBlock with USB pointing up to start location search");
    TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
    TimerStart(&appTimer);
  }
}

/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module. This creates and starts application timers.
 */
uint32_t timers_init(void)
{
  TimerInit(&appTimer, tx_lora_periodic_handler);
  return 0;
}

Second Code

/**
 * @file GPS_Tracker.ino
 * @author rakwireless.com
 * @brief This sketch demonstrate a GPS tracker that collect location from a uBlox M7 GNSS sensor
 *    and send the data to lora gateway.
 *    It uses a 3-axis acceleration sensor to detect movement of the tracker
 * @version 0.2
 * @date 2021-04-30
 * 
 * @copyright Copyright (c) 2020
 * 
 * @note RAK4631 GPIO mapping to nRF52840 GPIO ports
   RAK4631    <->  nRF52840
   WB_IO1     <->  P0.17 (GPIO 17)
   WB_IO2     <->  P1.02 (GPIO 34)
   WB_IO3     <->  P0.21 (GPIO 21)
   WB_IO4     <->  P0.04 (GPIO 4)
   WB_IO5     <->  P0.09 (GPIO 9)
   WB_IO6     <->  P0.10 (GPIO 10)
   WB_SW1     <->  P0.01 (GPIO 1)
   WB_A0      <->  P0.04/AIN2 (AnalogIn A2)
   WB_A1      <->  P0.31/AIN7 (AnalogIn A7)
 */

#include <Arduino.h>
#include <LoRaWan-RAK4630.h> //http://librarymanager/All#SX126x
#include <SPI.h>
#include "SparkFunLIS3DH.h" //http://librarymanager/All#SparkFun-LIS3DH
#include "Wire.h"
#include <TinyGPS.h>        //http://librarymanager/All#TinyGPS
#include "SparkFun_SHTC3.h"   // Click here to get the library: http://librarymanager/All#SparkFun_SHTC3

LIS3DH SensorTwo(I2C_MODE, 0x18);

TinyGPS gps;

String tmp_data = "";
int direction_S_N = 0;  //0--S, 1--N
int direction_E_W = 0;  //0--E, 1--W

// RAK4630 supply two LED
#ifndef LED_BUILTIN
#define LED_BUILTIN 35
#endif

#ifndef LED_BUILTIN2
#define LED_BUILTIN2 36
#endif

bool doOTAA = true;   // OTAA is used by default.
#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 60                     /**< Maximum number of events in the scheduler queue. */
#define LORAWAN_DATERATE DR_0                   /*LoRaMac datarates definition, from DR_0 to DR_5*/
#define LORAWAN_TX_POWER TX_POWER_5             /*LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15*/
#define JOINREQ_NBTRIALS 3                      /**< Number of trials for the join request. */
DeviceClass_t gCurrentClass = CLASS_A;          /* class definition*/
LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_US915;    /* Region:EU868*/
lmh_confirm gCurrentConfirm = LMH_UNCONFIRMED_MSG;          /* confirm/unconfirm packet definition*/
uint8_t gAppPort = LORAWAN_APP_PORT;                      /* data port*/

/**@brief Structure containing LoRaWan parameters, needed for lmh_init()
 */
static lmh_param_t lora_param_init = {LORAWAN_ADR_ON, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_OFF};

// Foward declaration
static void lorawan_has_joined_handler(void);
static void lorawan_join_failed_handler(void);
static void lorawan_rx_handler(lmh_app_data_t *app_data);
static void lorawan_confirm_class_handler(DeviceClass_t Class);
static void send_lora_frame(void);

/**@brief Structure containing LoRaWan callback functions, needed for lmh_init()
*/
static lmh_callback_t lora_callbacks = {BoardGetBatteryLevel, BoardGetUniqueId, BoardGetRandomSeed,
                                        lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler, lorawan_join_failed_handler
                                       };
                                       
//OTAA keys !!!! KEYS ARE MSB !!!!


// ABP keys
uint32_t nodeDevAddr = 0x260116F8;
uint8_t nodeNwsKey[16] = {0x7E, 0xAC, 0xE2, 0x55, 0xB8, 0xA5, 0xE2, 0x69, 0x91, 0x51, 0x96, 0x06, 0x47, 0x56, 0x9D, 0x23};
uint8_t nodeAppsKey[16] = {0xFB, 0xAC, 0xB6, 0x47, 0xF3, 0x58, 0x45, 0xC7, 0x50, 0x7D, 0xBF, 0x16, 0x8B, 0xA8, 0xC1, 0x7C};

// Private defination
#define LORAWAN_APP_DATA_BUFF_SIZE 64                     /**< buffer size of the data to be transmitted. */
#define LORAWAN_APP_INTERVAL 10000                        /**< Defines for user timer, the application data transmission interval. 10s, value in [ms]. */
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE];        //< Lora user application data buffer.
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0}; //< Lora user application data structure.

TimerEvent_t appTimer;
static uint32_t timers_init(void);
static uint32_t count = 0;
static uint32_t count_fail = 0;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  // Initialize Serial for debug output
  time_t timeout = millis();
  Serial.begin(115200);
  while (!Serial)
  {
    if ((millis() - timeout) < 5000)
    {
      delay(100);
    }
    else
    {
      break;
    }
  }

  // Initialize LoRa chip.
  lora_rak4630_init();

  Serial.println("=====================================");
  Serial.println("Welcome to RAK4630 LoRaWan!!!");
  if (doOTAA)
  {
    Serial.println("Type: OTAA");
  }
  else
  {
    Serial.println("Type: ABP");
  }

  switch (gCurrentRegion)
  {
    case LORAMAC_REGION_AS923:
      Serial.println("Region: AS923");
      break;
    case LORAMAC_REGION_AU915:
      Serial.println("Region: AU915");
      break;
    case LORAMAC_REGION_CN470:
      Serial.println("Region: CN470");
      break;
  case LORAMAC_REGION_CN779:
    Serial.println("Region: CN779");
    break;
    case LORAMAC_REGION_EU433:
      Serial.println("Region: EU433");
      break;
    case LORAMAC_REGION_IN865:
      Serial.println("Region: IN865");
      break;
    case LORAMAC_REGION_EU868:
      Serial.println("Region: EU868");
      break;
    case LORAMAC_REGION_KR920:
      Serial.println("Region: KR920");
      break;
    case LORAMAC_REGION_US915:
      Serial.println("Region: US915");
    break;
  case LORAMAC_REGION_RU864:
    Serial.println("Region: RU864");
    break;
  case LORAMAC_REGION_AS923_2:
    Serial.println("Region: AS923-2");
    break;
  case LORAMAC_REGION_AS923_3:
    Serial.println("Region: AS923-3");
    break;
  case LORAMAC_REGION_AS923_4:
    Serial.println("Region: AS923-4");
      break;
  }
  Serial.println("=====================================");

  //lis3dh init
  if (SensorTwo.begin() != 0)
  {
    Serial.println("Problem starting the sensor at 0x18.");
  }
  else
  {
    Serial.println("Sensor at 0x18 started.");
  // Set low power mode
  uint8_t data_to_write = 0;
  SensorTwo.readRegister(&data_to_write, LIS3DH_CTRL_REG1);
  data_to_write |= 0x08;
  SensorTwo.writeRegister(LIS3DH_CTRL_REG1, data_to_write);
  delay(100);

  data_to_write = 0;
  SensorTwo.readRegister(&data_to_write, 0x1E);
  data_to_write |= 0x90;
  SensorTwo.writeRegister(0x1E, data_to_write);
  delay(100);
  }
  //gps init

  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, 0);
  delay(1000);
  digitalWrite(WB_IO2, 1);
  delay(1000);
  
  Serial1.begin(9600);
  while (!Serial1);
  Serial.println("gps uart init ok!");
  
  //creat a user timer to send data to server period
  uint32_t err_code;

  err_code = timers_init();
  if (err_code != 0)
  {
    Serial.printf("timers_init failed - %d\n", err_code);
    return;
  }

  // Setup the EUIs and Keys
  if (doOTAA)
  {
    lmh_setDevEui(nodeDeviceEUI);
    lmh_setAppEui(nodeAppEUI);
    lmh_setAppKey(nodeAppKey);
  }
  else
  {
    lmh_setNwkSKey(nodeNwsKey);
    lmh_setAppSKey(nodeAppsKey);
    lmh_setDevAddr(nodeDevAddr);
  }

  // Initialize LoRaWan
  err_code = lmh_init(&lora_callbacks, lora_param_init, doOTAA, gCurrentClass, gCurrentRegion);
  if (err_code != 0)
  {
    Serial.printf("lmh_init failed - %d\n", err_code);
    return;
  }

  // Start Join procedure
  lmh_join();
}

void loop()
{
  // Put your application tasks here, like reading of sensors,
  // Controlling actuators and/or other functions. 
}

/**@brief LoRa function for handling HasJoined event.
 */
void lorawan_has_joined_handler(void)
{
  if(doOTAA == true)
  {
  Serial.println("OTAA Mode, Network Joined!");
  }
  else
  {
    Serial.println("ABP Mode");
  }

  lmh_error_status ret = lmh_class_request(gCurrentClass);
  if (ret == LMH_SUCCESS)
  {
    delay(1000);
    TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
    TimerStart(&appTimer);
  }
}
/**@brief LoRa function for handling OTAA join failed
*/
static void lorawan_join_failed_handler(void)
{
  Serial.println("OTAA join failed!");
  Serial.println("Check your EUI's and Keys's!");
  Serial.println("Check if a Gateway is in range!");
}
/**@brief Function for handling LoRaWan received data from Gateway
 *
 * @param[in] app_data  Pointer to rx data
 */
void lorawan_rx_handler(lmh_app_data_t *app_data)
{
  Serial.printf("LoRa Packet received on port %d, size:%d, rssi:%d, snr:%d, data:%s\n",
          app_data->port, app_data->buffsize, app_data->rssi, app_data->snr, app_data->buffer);
}

void lorawan_confirm_class_handler(DeviceClass_t Class)
{
  Serial.printf("switch to class %c done\n", "ABC"[Class]);
  // Informs the server that switch has occurred ASAP
  m_lora_app_data.buffsize = 0;
  m_lora_app_data.port = gAppPort;
  lmh_send(&m_lora_app_data, gCurrentConfirm);
}

void send_lora_frame(void)
{
  if (lmh_join_status_get() != LMH_SET)
  {
    //Not joined, try again later
    return;
  }

  lmh_error_status error = lmh_send(&m_lora_app_data, gCurrentConfirm);
  if (error == LMH_SUCCESS)
  {
    count++;
    Serial.printf("lmh_send ok count %d\n", count);
  }
  else
  {
    count_fail++;
    Serial.printf("lmh_send fail count %d\n", count_fail);
  }
  TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
  TimerStart(&appTimer);
}

/**@brief Function for analytical direction.
 */
void direction_parse(String tmp)
{
    if (tmp.indexOf(",E,") != -1)
    {
        direction_E_W = 0;
    }
    else
    {
        direction_E_W = 1;
    }
    
    if (tmp.indexOf(",S,") != -1)
    {
        direction_S_N = 0;
    }
    else
    {
        direction_S_N = 1;
    }
}

/**@brief Function for handling a LoRa tx timer timeout event.
 */
String data = "";
void tx_lora_periodic_handler(void)
{ 
  float x = 0;
  float y = 0;
  float z = 0;

  bool newData = false;
  
  Serial.println("check acc!");
  x = SensorTwo.readFloatAccelX() * 1000;
  y = SensorTwo.readFloatAccelY() * 1000;
  z = SensorTwo.readFloatAccelZ() * 1000;
  data = "X = " + String(x) + "mg" + " Y = " + String(y) + "mg" + " Z =" + String(z) + "mg";
  Serial.println(data);
  data = "";
  if( abs(x-z) < 400)
  {
    // For one second we parse GPS data and report some key values
    for (unsigned long start = millis(); millis() - start < 1000;)
    {
      while (Serial1.available())
      {
        char c = Serial1.read();
         Serial.write(c); // uncomment this line if you want to see the GPS data flowing
        tmp_data += c;
        if (gps.encode(c))// Did a new valid sentence come in?
          newData = true;
      }
    }
    direction_parse(tmp_data);
    tmp_data = "";
    float flat, flon;
    int32_t ilat, ilon;
    if (newData)
    {
      unsigned long age;  
      gps.f_get_position(&flat, &flon, &age);
      flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat;
      ilat = flat * 100000;
      Serial.println('Latitude', ilat);
      flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon;
      ilon = flon * 100000;
      Serial.println('Longitude', ilon);
      memset(m_lora_app_data.buffer, 0, LORAWAN_APP_DATA_BUFF_SIZE);
      m_lora_app_data.port = gAppPort;
      m_lora_app_data.buffer[0] = 0x09;
      //lat data
      m_lora_app_data.buffer[1] = (ilat & 0xFF000000) >> 24;
      m_lora_app_data.buffer[2] = (ilat & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[3] = (ilat & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[4] =  ilat & 0x000000FF;
      if(direction_S_N == 0)
      {
        m_lora_app_data.buffer[5] = 'S';    
      }
      else
      {
        m_lora_app_data.buffer[5] = 'N';    
      }
      //lon data
      m_lora_app_data.buffer[6] = (ilon & 0xFF000000) >> 24;
      m_lora_app_data.buffer[7] = (ilon & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[8] = (ilon & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[9] =  ilon & 0x000000FF;
      if(direction_E_W == 0)
      {
        m_lora_app_data.buffer[10] = 'E';
      }
      else
      {
        m_lora_app_data.buffer[10] = 'W';
      }
      m_lora_app_data.buffsize = 11;
      send_lora_frame();
    }
    else
    {
      Serial.println("No Location Found");
      TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
      TimerStart(&appTimer);
    }
  }
  else
  {
    Serial.println("Turn WisBlock with USB pointing up to start location search");
    TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
    TimerStart(&appTimer);
  }
}

/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module. This creates and starts application timers.
 */
uint32_t timers_init(void)
{
  TimerInit(&appTimer, tx_lora_periodic_handler);
  return 0;
}

I’ve had it standing vertically for 20 minutes and did the gps debug example to see what was going on and never get coordinates it does seem to be communicating to the chip though
image

When it says configure, does that only have to be done once outside then it will work indoors or it only works outdoors?

Where did you get the code 1? Also where did you get code 2?

Yes. You got no GPS signal at all. Is the part of the GPS antenna with the tape (not the metal shield) facing the sky?

GPS will only work outside. GPS does not work indoors.

got one from the documentation on raks docs for the gps and the other came from github solutions for the rak 4630. So there is no way to get gps signals indoors?

The correct code should be here WisBlock/GPS_Tracker.ino at master · RAKWireless/WisBlock · GitHub

Yes. GPS is only for outdoors.

Why can’t GPS be used for indoor positioning?

I did the sensor code by itself and was able to get correct coordinates. I was also able to see the right coordinates in the print on the gps tracker solution u sent me but My gps data keeps coming over the network incorrectly once the data is sent over helium or ttn.

This is my debug data in datacake over helium. When I tried TTN it kept saying longitude was 0, so something I guess in the payload decode is messed up. I’ll post the payload decoder at the bottom

[
    {
        "field": "LOCATION",
        "value": "(7381.97504,0)"
    }
]

Log:

null

Recorded measurements:

LOCATION = (7381.97504,0) (timestamp: auto)

Payload decoder is below. I am using the example gps tracker code in arduino

function Decoder(bytes, port) 
{
  var longitude_int, latitude_int;
  var decoded = {};
  
  if (port === 2)
  {
    if(bytes[0]==9) // check if the header byte is 9.
    {
      latitude_int = (bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | (bytes[4]);
      decoded.latitude = latitude_int / 100000;
      longitude_int = (bytes[6] << 24) | (bytes[7] << 16) | (bytes[8] << 8) | (bytes[9]);
      decoded.longitude = longitude_int / 100000;
      return decoded;
    }
  }
}

any idea why this code above is doing this?

Check first the output via serial logs. Then compare it to what’s being decoded.

The console is showing the correct longitude and latitude data in Helium. I can confirm that it is the payload decoder that is giving the wrong results.

function Decoder(bytes, port)
{
  var longitude_int, latitude_int;
  var decoded = {};

  if (port === 2)
  {
    if(bytes[0]===9) // check if the header byte is 9.
    {
      latitude_int = (bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | (bytes[4]);
      var latitude = latitude_int / 100000;
      longitude_int = (bytes[6] << 24) | (bytes[7] << 16) | (bytes[8] << 8) | (bytes[9]);
      var longitude = longitude_int / 100000;

      return [{
          "field": "LOCATION",
          "value": "(" + latitude + "," + longitude + ")"
      }]

    }
  }
}

This was a slight modification to the decoder just to be able to add the data into the widget but is still based on the same principles as the TTN Decoder here GPS Tracker Example. Why is the decoder giving this as the data points?

After running a test with the standard TTN payload decoder I can confirm that it is not giving correct gps coordinates, but it is in helium console debug. This is with the standard payload decoder from your GPS Tracker Example and is definitely giving invalid coordinates
image
image

The coordinates you see in the helium console is the location/coordinates of the hotspot/gateway, not your device. As I said before, it is hard to tell what is the root cause unless we see if the device is giving the right coordinates on the device level first and not on the decoded one in ttn or helium. That is the reason why I propose to check the serial logs first on the device level.

I did it with that gps example not connected to lora and it was definitely giving the correct coordinates. We traveled around town with a laptop connected and looked up the locations and everything came out fine. Something is wrong maybe somewhere between when it is submitted to helium or when it goes from helium to datacake and I use the payload decoder

When I use TTN it also gave wrong info too, same wrong info as datacake

If you test the only the GPS without the LoRa code, the test verifies that the GPS is working but we can’t verify if the GPS data is parse correctly in the LoRaWAN code before transmission. If I am in your case, I will test again and check the logs in the actual code used for the LoRaWAN transmission.

Check the coordinates before the payload is formatted as well as how the data looks before sending a s LoRaWAN uplink packets. Along the way in steps, one is is probably not right. I am the one who created that documentation with the decoder and tested it many times already :wink:

Ok so when I use the gps ublox it is giving correct coordinates. should I try and re print ilat and ilong to see what it is giving before and send that to you?

We already know that the GPS module is working based on your independent test. What I am saying is on the LoRaWAN code you use.