Has anyone tried sending GPS coords to TTN?

Of course. Quit hogging our gateways god dammit! :triumph:

ADR would be best, then the network server will set the appropriate SF, but I don’t know if LMIC supports this.

1 Like

only static nodes should use ADR

https://www.thethingsnetwork.org/wiki/LoRaWAN/ADR

UPDATE:

It’s working, but it outputs bullshit. See below

Okay so here is my script:

//DEBUGGING
#define DEBUG
#define DEBUG_XL

//Includes
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>

//LoRaWAN credentials
#ifdef CREDENTIALS
static const u1_t NWKSKEY[16] = NWKSKEY1;
static const u1_t APPSKEY[16] = APPSKEY1;
static const u4_t DEVADDR = DEVADDR1;
#else
static const u1_t NWKSKEY[16] = { 0x0C, 0x3F, 0x0A, 0x47, 0xF7, 0xEE, 0x23, 0xAC, 0xC2, 0x9E, 0x38, 0x29, 0x25, 0x29, 0x88, 0x30 };
static const u1_t APPSKEY[16] = { 0x93, 0x35, 0xC9, 0x49, 0x15, 0xC1, 0xF8, 0x2B, 0x54, 0x3A, 0x8E, 0x7F, 0x93, 0x61, 0xD9, 0x30 };
static const u4_t DEVADDR = 0x2601189E;
#endif

uint8_t mydata[14]; //Extra bytes as buffer to play with
const unsigned message_size =11;
// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }

//Sendjob
static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 250;
dr_t LMIC_DR_sequence[] = {DR_SF12, DR_SF10, DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF9, DR_SF7, DR_SF7, DR_SF7, DR_SF7};
int LMIC_DR_sequence_count = 12;
int LMIC_DR_sequence_index = 0;

// Pin mapping Dragino Shield
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = LMIC_UNUSED_PIN,
.rst = 9,
.dio = {2, 6, 7},
};

// TinyGPS object
TinyGPS gps;

//SoftwareSerial pin mapping
SoftwareSerial ss(3, 2); // RX, TX  Arduino RX, TX --> GPS TXD, RXD

void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
//Error catching
switch(ev) {
  case EV_SCAN_TIMEOUT:
    Serial.println(F("EV_SCAN_TIMEOUT"));
    break;
  case EV_BEACON_FOUND:
    Serial.println(F("EV_BEACON_FOUND"));
    break;
  case EV_BEACON_MISSED:
    Serial.println(F("EV_BEACON_MISSED"));
    break;
  case EV_BEACON_TRACKED:
    Serial.println(F("EV_BEACON_TRACKED"));
    break;
  case EV_JOINING:
    Serial.println(F("EV_JOINING"));
    break;
  case EV_JOINED:
    Serial.println(F("EV_JOINED"));
    //Disable link check validarion (Auto enabled during join, but not supported by TTN);
    LMIC_setLinkCheckMode(0);
    break;
  case EV_RFU1:
    Serial.println(F("EV_RFU1"));
    break;
  case EV_JOIN_FAILED:
    Serial.println(F("EV_JOIN_FAILED"));
    break;
  case EV_REJOIN_FAILED:
    Serial.println(F("EV_REJOIN_FAILED"));
    break;
    break;
  case EV_TXCOMPLETE:
        Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
        if (LMIC.txrxFlags & TXRX_ACK)
          Serial.println(F("Received ack"));
        if (LMIC.dataLen) {
          Serial.println(F("Received "));
          Serial.println(LMIC.dataLen);
          Serial.println(F(" bytes of payload"));
        }
    // Schedule next transmission
    os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
    break;
  case EV_LOST_TSYNC:
    Serial.println(F("EV_LOST_TSYNC"));
    break;
  case EV_RESET:
    Serial.println(F("EV_RESET"));
    break;
  case EV_RXCOMPLETE:
    //Recieved data in ping slot
    Serial.println(F("EV_RX_COMPLETE"));
    break;
  case EV_LINK_DEAD:
    Serial.println(F("EV_LINK_DEAD"));
    break;
  case EV_LINK_ALIVE:
    Serial.println(F("EV_LINK_ALIVE"));
    break;
  default:
    //If error != debug then display default value
    Serial.println(F("What the fuck is going on"));
    break;
    
}
}

// do_send call is scheduled in event handler
void do_send(osjob_t* j){
  // starting version == martijn's version

Serial.println("\ndo_send was called");

// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
    Serial.println(F("OP_TXRXPEND, not sending"));
} else {
    // Prepare upstream data transmission at the next possible time.
    // Debug for sending

    #ifdef DEBUG
    Serial.println("  expected   CA DA F? 83 5E 9? 0 ?? ?? " );  
    Serial.println("    dummy   7F FF FF 7F FF FF 0 0 0 " );    
    #endif  
    Serial.print(" mydata[] = [");
    Serial.print( mydata[0], HEX );
    Serial.print(" ");
    Serial.print( mydata[1], HEX );
    Serial.print(" ");
    Serial.print( mydata[2], HEX );
    Serial.print(" ");
    Serial.print( mydata[3], HEX );
    Serial.print(" ");
    Serial.print( mydata[4], HEX );
    Serial.print(" ");
    Serial.print( mydata[5], HEX );
    Serial.print(" ");
    Serial.print( mydata[6], HEX );
    if (message_size>7) Serial.print(" ");
    if (message_size>7) Serial.print( mydata[7], HEX );
    if (message_size>8) Serial.print(" ");
    if (message_size>8) Serial.print( mydata[8], HEX );
    if (message_size>9) Serial.print(" / ");
    if (message_size>9) Serial.print( mydata[9], HEX );
    if (message_size>10) Serial.print(" ");
    if (message_size>10) Serial.print( mydata[10], HEX );
    Serial.print("]    ");
    
    Serial.print("DR [ ");
    Serial.print( LMIC_DR_sequence_index );
    Serial.print(" ] = ");
    Serial.print( LMIC_DR_sequence[LMIC_DR_sequence_index] );
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF7) Serial.print(" DR_SF7 "); 
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF8) Serial.print(" DR_SF8 "); 
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF9) Serial.print(" DR_SF9 "); 
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF10) Serial.print(" DR_SF10 "); 
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF11) Serial.print(" DR_SF11 "); 
    if ( LMIC_DR_sequence[LMIC_DR_sequence_index]==DR_SF12) Serial.print(" DR_SF12 ");
    Serial.print("Data =");
    Serial.println(mydata[0]);
    Serial.println(mydata[1]);
    Serial.println(mydata[2]);
    Serial.println(mydata[3]);
    Serial.println(mydata[4]);
    Serial.println(mydata[5]);
    Serial.println(mydata[6]);
    Serial.println(mydata[7]);
    Serial.println(mydata[8]);
    Serial.println(mydata[9]);
    Serial.println(mydata[10]);
    

    // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library
    // for the ttn mapper always use SF7. For other use cases, SF12 can be used, however that will require 60 mins quiet time,
    // according to TTN rules.
    LMIC_setDrTxpow(LMIC_DR_sequence[LMIC_DR_sequence_index],14); // Set data rate

    LMIC_DR_sequence_index = LMIC_DR_sequence_index + 1;
    if (LMIC_DR_sequence_index >= LMIC_DR_sequence_count) {
      LMIC_DR_sequence_index=0;
    }

    // Send that shit
    LMIC_setTxData2(1, mydata, message_size, 0);

    Serial.println(" - packet queued");
    
}
// Next TX is scheduled after TX_COMPLETE event.
}

void lmic_init() {
  os_init();
  //Reset MAC state
  LMIC_reset();

//  //EU config
//  #if defined(CFG_eu868)
//  // Set up the channels for TTN
//  // Corresponds to most default EU gateways
//  // Good for debugging, doesn't overload frequencies
//  LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
//  LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
//  LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band
//  #elif defined(CFG_us915)
//  //USA frequency config
//  LMIC_selectSubBand(1);
//  #endif
  LMIC_setLinkCheckMode(0); //Enable/disable link check validation

  // TTN uses SF9 for its RX2 window
  LMIC.dn2Dr = DR_SF9;
  //Set data rate and transmit power for uplink
  LMIC_setDrTxpow(DR_SF12,14);
  
}

void setup() {
Serial.begin(115200);
Serial.println(F("Starting..."));

//Load the send buffer with dummy location. 0,0 is recognized as dummy by TTN and will therefor not be displayed.
put_gpsvalues_into_sendbuffer( 0,0,0,0);

Serial.println();
Serial.println();
Serial.println("Starting GPS LoRa transmission");
Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
Serial.println();

//GPS Serial
ss.begin(9600); //Software serial with GPS module.

 lmic_init();

 //Start job delayed so system can look for GPS first
 os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(20), do_send);

// Set static session parameters.
LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
}

void loop() {

// process the serial feed from GPS module
Serial.println(" ");
Serial.println("Read GPS... ");
char c;
unsigned long start = millis();
do 
{   
  while (ss.available())
  {
    char c = ss.read();
    #ifdef DEBUG_XL
    Serial.write(c); // uncomment this line if you want to see the GPS data flowing
    #endif
    
    if (gps.encode(c)) // Did a new valid sentence come in?
        process_gps_values();
  }
} while (millis() - start < 3000); // if too high a value then system wil delay scheduled jobs and the send sequence will take too long
 
os_runloop_once();  // system picks up scheduled jobs
}

void process_gps_values()
{ 
  // retrieve some usefull values from GPS library
  float flat, flon, alt;
  unsigned long age; 
  int hdopNumber;
  
  gps.f_get_position(&flat, &flon, &age);  // lat -90.0 .. 90.0 as a 4 byte float, lon -180 .. 180 as a 4 byte float, age in 1/1000 seconds as a 4 byte unsigned long
  alt = gps.f_altitude();    // signed float altitude in meters
  hdopNumber = gps.hdop();   // int 100ths of a meter

  // check if possibly invalid
  bool GPS_values_are_valid = true;
  if (flat == TinyGPS::GPS_INVALID_F_ANGLE)    GPS_values_are_valid = false;
  if (flon == TinyGPS::GPS_INVALID_F_ANGLE)    GPS_values_are_valid = false;
  if (hdopNumber == TinyGPS::GPS_INVALID_HDOP) GPS_values_are_valid = false;
  if (age == TinyGPS::GPS_INVALID_AGE)         GPS_values_are_valid = false;
  
  if (alt == TinyGPS::GPS_INVALID_F_ALTITUDE)  GPS_values_are_valid = false;   // if alt, hdop remain giving errors, possibly the GPS character read misses every start few characters of every feed. Solution: make the code lighter so it returns quicker to character read. Or process a bit of buffer while doing other actions, see TinyGPS example.

  // if valid, put into buffer
  if (GPS_values_are_valid) put_gpsvalues_into_sendbuffer( flat, flon, alt, hdopNumber);
// after init, sendbuffer holds 0,0 lovation; after first fix it will retain the last valid location
  
  Serial.print(".");
  //show me something
  #ifdef DEBUG
  // keep some values out as seems to take performance and/or make for code to miss GPS sentences
  unsigned long chars = 0;
  //unsigned short sentences = 0, failed = 0;
  //uint32_t sat; 
  //gps.stats(&chars, &sentences, &failed);
  //sat = gps.satellites();
  
  Serial.println();
  Serial.print("Data: ");
  if (GPS_values_are_valid) Serial.print("(valid) ");
  if (!GPS_values_are_valid) Serial.print("(** INVALID");
  if (flat == TinyGPS::GPS_INVALID_F_ANGLE)    {Serial.print(" lat="); Serial.print(flat);}
  if (flon == TinyGPS::GPS_INVALID_F_ANGLE)    {Serial.print(" lon="); Serial.print(flon);}
  if (hdopNumber == TinyGPS::GPS_INVALID_HDOP) {Serial.print(" hdop="); Serial.print(hdopNumber);}
  if (age == TinyGPS::GPS_INVALID_AGE)         {Serial.print(" age="); Serial.print(age);}
  if (alt == TinyGPS::GPS_INVALID_F_ALTITUDE)  {Serial.print(" alt="); Serial.print(alt);}
  if (!GPS_values_are_valid) Serial.print(" **) ");
  Serial.print("  LAT, LON=");
  Serial.print( flat, 6);   
  Serial.print(", ");
  Serial.print(flon, 6); // 52.632656, 4.738389
  Serial.print(" hdop=");
  Serial.print( hdopNumber);
  Serial.print(" alt=");
  Serial.print( alt );
  Serial.print(" AGE=");
  Serial.print(age);
  //Serial.print(" SAT=");
  //Serial.print( sat);
  
  //  Serial.print(" CHARS=");
  //  Serial.print(chars);
  //Serial.print(" SENT=");
  //Serial.print(sentences);
  //Serial.print(" ERR=");
  //Serial.print(failed);
  Serial.println("");
  #endif
  
  #ifdef DEBUG_XL
  if (chars == 0)
Serial.println("** No characters from GPS: check wiring **");
  else if (age > 5000)
Serial.println("Warning: possible stale GPS data (age over 5 seconds)");
  else
Serial.println("GPS Data is fresh (age less than 5 seconds)");

  Serial.print("For TTN message LatitudeBinary, LongitudeBinary, altitudeGps, accuracy: ");

Serial.print( LatitudeBinary, HEX);
Serial.print(", ");
Serial.print( LongitudeBinary, HEX );
Serial.print(", ");
Serial.print( altitudeGps, HEX );
Serial.print(", ");
Serial.println( accuracy, HEX );
  Serial.println("expected   CA DA F. 83 5E 9. 0 .. .. " );     
  Serial.println("    dummy   7F FF FF 7F FF FF 0 0 0 " );    
  Serial.print(  "mydata[] = ");
  Serial.print( mydata[0], HEX );
  Serial.print(" ");
  Serial.print( mydata[1], HEX );
  Serial.print(" ");
  Serial.print( mydata[2], HEX );
  Serial.print(" ");
  Serial.print( mydata[3], HEX );
  Serial.print(" ");
  Serial.print( mydata[4], HEX );
  Serial.print(" ");
  Serial.print( mydata[5], HEX );
  Serial.print(" ");
  Serial.print( mydata[6], HEX );
  if (message_size>6) Serial.print(" ");
  if (message_size>6) Serial.print( mydata[7], HEX );
  if (message_size>7) Serial.print(" ");
  if (message_size>7) Serial.print( mydata[8], HEX );
  if (message_size>8) Serial.print(" / ");
  if (message_size>8) Serial.print( mydata[9], HEX );
  if (message_size>9) Serial.print(" ");
  if (message_size>9) Serial.print( mydata[10], HEX );
  Serial.println("]");
  #endif    
}



void put_gpsvalues_into_sendbuffer(float flat, float flon, float alt, int hdopNumber)
{  
  
  uint32_t LatitudeBinary = ((flat + 90) / 180) * 16777215;
  uint32_t LongitudeBinary = ((flon + 180) / 360) * 16777215;
  uint16_t altitudeGps = alt;         // altitudeGps in meters, alt from tinyGPS is float in meters
  if (alt<0) altitudeGps=0;   // unsigned int wil not allow negative values and warps them to huge number, needs to be zero'ed
  // uint8_t accuracy = hdopNumber*10;   // needs to be /10 instead of *10 as per example JP
  uint8_t accuracy = hdopNumber/10;   // from TinyGPS horizontal dilution of precision in 100ths, TinyGPSplus seems the same in 100ths as per MNEMA string
  
  mydata[0] = ( LatitudeBinary >> 16 ) & 0xFF;
  mydata[1] = ( LatitudeBinary >> 8 ) & 0xFF;
  mydata[2] = LatitudeBinary & 0xFF;

  mydata[3] = ( LongitudeBinary >> 16 ) & 0xFF;
  mydata[4] = ( LongitudeBinary >> 8 ) & 0xFF;
  mydata[5] = LongitudeBinary & 0xFF;

  // altitudeGps in meters into unsigned int
  mydata[6] = ( altitudeGps >> 8 ) & 0xFF;
  mydata[7] = altitudeGps & 0xFF;

  // hdop in tenths of meter
  mydata[8] = accuracy & 0xFF;
  
  mydata[9] = 0;  // fill up next bytes in buffer, just for play. As-if null terminated string.
  mydata[10] = 0xFF;  // dummy filler byte
}

Whem I’m outside the lat/lng output in the arduino serial monitor is correct. It also puts the output in a HEX format for ttn to support. But once I convert it back into readable text it outputs someting like this:
CAFC49849B8800000F00FF
wich translates into:
ÊüI„›ˆÿ

I don’t get it, the console looks all good but the output makes no sense at all.

1 Like

HI Nidaros. How’s this project progressing? Any updates on Solar powered GPS trackers?

1 Like

Hi there, I have a prototype working but not on solar sadly. I’ts currently on usb

oh and i also got the decoding part working, if i can find it ill post below. Give me a sec

Here is what I used for my decorder. This was like 4 months ago so please don’t ask me questions :joy:

function Decoder (bytes) {
  var _lat = ((bytes[0] << 16) + (bytes[1] << 8) + bytes[2]) / 16777215.0 * 180.0 - 90;
  var _lng = ((bytes[3] << 16) + (bytes[4] << 8) + bytes[5]) / 16777215.0 * 360.0 - 180;
  var _alt = (bytes[6] << 8) + bytes[7];
  var _acc = bytes[8] / 10.0;
  var _VCC = bytes[9] / 50;
  var _tempCPU = bytes[10] -100;
  var _time_to_fix_bin = bytes[11];
  var _time_to_fix;
  if (_time_to_fix_bin>=218) { _time_to_fix = 60*60+(_time_to_fix_bin-218)*600 }
  else if (_time_to_fix_bin>=168) { _time_to_fix = 10*60+(_time_to_fix_bin-168)*60 }
  else if (_time_to_fix_bin>=60) {  _time_to_fix = 60+(_time_to_fix_bin-60)*5 }
  else  {_time_to_fix = _time_to_fix_bin }
      
          // 0..60 sec  at 1 sec interval <==> values 0 .. 60 
          // 1..10 min at 5 sec interval  <==> values 60 ..  168
          // 10..60 min at 1 min interval <==> values 168 .. 218
          // 1..7 hour at 10 min interval <==> values 218 ..254; 255 means "more than 7 hours"
          

      return {
        gps_lat: _lat,
        gps_lng: _lng,
        gps_alt: _alt,
        gps_prec: _acc,
        arduino_VCC: _VCC,
        arduino_temp: _tempCPU,
        time_to_fix: _time_to_fix,
      };
    }
1 Like

Thanks for the update :slight_smile:

1 Like

@Nidaros @Epyon @Gig @casper

For mapping or range test. I am building Arudino mega + lora shield + adafruit ultimate gps v3 … Please correct me if I am wrong. Many thanks
GPS >> arduino Shield pin mapping…
vin >>vin
Gnd >> gnd
Tx >> rx (0)
Rx >> tx (1)

Config with ABP :
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <TinyGPS.h>

TinyGPS gps;

GPS got fixed in 30 second to 1 min… however, only 0000000000 delivered as a payload.

Compiling the code has no error.arduino-gps

isn’t the GPS 3v3 logic level ? ( and the mega uart 5v)

Thanks for prompt reply. I powered mega by USB 5v. and GPS breakout board by mega VIN. Like this UNO examplw wiring @https://learn.adafruit.com/adafruit-ultimate-gps/arduino-wiring. Please tell me how should I wire since mega use hw serial as discussed in previous posts.

I’m doing it with a Seeeduino LoRaWAN w/ GPS

IMG_20171224_171046320

FB_IMG_1514918358117

Thanks for sharing. However, I do not have those hw/resource and the frequency is EU.

rxrx

// what’s the name of the hardware serial port?
#define GPSSerial Serial1

I have added #define GPSSerial Serial1

Serial output : However, not receiving any packet in the console.

Sta69,N,01323.7657,E,0.16,292.15,040118,A6F
$GPVTG,292.15,T,M,0.16,N,0.30,K,A
34
Packet queued

$GPRMC,095352.000,A,5232.2469,N,01323.7657,E,0.16,292.15,040118,A6F
$GPVTG,292.15,T,M,0.16,N,0.30,K,A
34
Packet queued
Starting
,603
$GPRMC,095356.000,A,5232.2473,N,01323.7654,E,0.25,292.15,040118,A
63
$GPVTG,292.15,T,M,0.25,N,0.47,K,A*34
$GPGGA,095357.000,5232.2474,N,01323.7655,E,1,06,0.98,69.3,M,44.7,M,5C
$GPGSA,A,3,09,03,31,17,22,02,1.30,0.98,0.86
Packet queued

Code…

hi,

pls read this when you are placing lots of code

did you see the edited picture … youre wiring is wrong for the mega

Thank you. I have changed the Pinout : GPS >> Mega

VIN >> 5V
GND >> GND
Tx >> RX1 (19)
Rx >> TX1 (18)

Is it correct? The GPS got a fix but no data in the console

If I was you I disconnect the lora board from the mega and first try to get communication between the mega and the GPS module.
also I think that the signallevel from the GPS is to low for the mega but I’m not sure @ this moment

I’m trying to get a TTN Mapper node working with Pro Mini, RFM95W, Neo6 GPS, and a small OLED display with the position information. I want it to be able to happily run in the background unless I press a button to turn on the display.

All working fine, except it takes longer than normal to lock, and doesn’t take read all the position data in one go - it will update long, say, then a few iterations later HDOP, Alt etc. All this makes me suspect it’s not reading the serial feed properly.

I clearly don’t understand the scheduling of lmic and/or how to handle the softserial port. I’ve got the GPS feeding into ss(9, 8). I’ve got the serial GPS reading in do_send (see below) which just doesn’t feel like the right place for it. Would it make more sense (and be cleaner) to do the reading and OLED update in an interrupt service routine?

*Forgot to say - I’m using the sample ttn-abp code as a base, and TinyGPS++.

Mark

void do_send(osjob_t* j) {
  // Check if there is not a current TX/RX job running
  if (LMIC.opmode & OP_TXRXPEND) {
    Serial.println(F("OP_TXRXPEND, not sending"));
  } else {

    while (ss.available())
      GPS.encode(ss.read());

    oled.clear();
    if (GPS.location.lat() == 0.0) {
      oled.println("NO FIX :(");
    }
    else {
      oled.println("FIX LOCKED!");
      oled.print("Lat: "); oled.println(GPS.location.lat(), 6);
      oled.print("Lon: "); oled.println(GPS.location.lng(), 6);
      oled.print("Alt: "); oled.print(GPS.altitude.meters(), 1); oled.print(" ");
      oled.print("HDOP: "); oled.print(GPS.hdop.hdop(), 1);
    }

    lpp.reset(); // clear the buffer
    lpp.addGPS(1, GPS.location.lat(), GPS.location.lng(), GPS.altitude.meters());                 
    LMIC_setTxData2(1, lpp.getBuffer(),  lpp.getSize(), 0);
    Serial.println(F("Packet queued"));
  }

}

Not exactly the same, but a sort of similar question passed by in another topic. Maybe this example may be useful for you too.

1 Like