Sending GPS position from one CubeCell to another over LoRa

Hi, guys. Noob (who bit off a little more than he could chew) posting here!

Long story short: I am making a transmitter and locator to play Airsoft. My intention is to have one HTCC-AB02S send its location via LoRa to another HTCC-AB02S to locate it. At this time, I am working on the transmitter, and I have been stuck a couple of weeks now trying to transmit the GPS coordinates.

I have been using the Factory_Test_AB02S as a template. I managed to show the GPS data on screen (Lat & Long - 4 digits on screen, 5 in serial print; I intend to transmit 5 - , GPS Time, HDOP, number of satellites, altitude), and also have it print on scren (serial print), but I cannot get it to transmit. I admit that the whole uint8_t * has done me in. I have tried to understand it, but it is WAY beyond my skill level!

My final intention is to have the receiver calculate the direction of the transmitter, and (with the help of a GY-85 module) point an arrow at the direction of the transmitter and state the distance and the level of accuracy (excellent, good, moderate, fair, poor) based on HDOP. But without the transmitter transmitting its location, nothing moves forward!

I should probably point out that one of the AB02S has the Air530Z module and the other has the Air530 (I ordered both at the same time, so go figure!).

Felipe

PS: I was going to include the code I am using, but the site thinks I am posting links and does not allow me to do it!

Hi, is it possible to transmit ordinary data through LoRa(confirm that Lora communication is OK)?
Please show your code in text.

Hi, is it possible to transmit ordinary data through LoRa(confirm that Lora communication is OK)?
Please show your code in text.

Yes. I used the Factory_Test_AB02S and the transmission worked fine. Here is that code:

#include “LoRaWan_APP.h”
#include “Arduino.h”
#include “HT_SSD1306Wire.h”
#include “GPS_Air530.h”
#include “GPS_Air530Z.h”

Air530Class GPS;

#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

extern SSD1306Wire display;

#define RF_FREQUENCY 868000000

#define TX_OUTPUT_POWER 14

#define LORA_BANDWIDTH 0
#define LORA_SPREADING_FACTOR 7
#define LORA_CODINGRATE 1
#define LORA_PREAMBLE_LENGTH 8
#define LORA_SYMBOL_TIMEOUT 0
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false

#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;
void OnTxDone( void );
void OnTxTimeout( void );
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
void displayInof();
void sleep(void);
void testRGB(void);
void showGpsInfo(void);
int fracPart(double val, int n);
void userKey(void);

typedef enum
{
LOWPOWER,
RX,
TX,
GPSTEST
}States_t;

int16_t txNumber;
States_t state;
bool sleepMode = false;
int16_t Rssi,rxSize;

void setup() {
Serial.begin(115200);
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(100);
display.init();

testRGB();
txNumber=0;
Rssi=0;

pinMode(P3_3,INPUT);
attachInterrupt(P3_3,userKey,FALLING);
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxDone = OnRxDone;

Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                               LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                               LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                               true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );

Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                               LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                               LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                               0, true, 0, 0, LORA_IQ_INVERSION_ON, true );

state=TX;

}

void loop()
{
switch(state)
{
case TX:
delay(1000);
txNumber++;
sprintf(txpacket,"%s",“hello”);
sprintf(txpacket+strlen(txpacket),"%d",txNumber);
sprintf(txpacket+strlen(txpacket),"%s"," rssi : “);
sprintf(txpacket+strlen(txpacket),”%d",Rssi);
turnOnRGB(0x100000,0);

      Serial.printf("\r\nsending packet \"%s\" , length %d\r\n",txpacket, strlen(txpacket));

      Radio.Send( (uint8_t *)txpacket, strlen(txpacket) );
      state=LOWPOWER;
      break;
  case RX:
  	Serial.println("into RX mode");
      Radio.Rx( 0 );
      state=LOWPOWER;
      break;
  case LOWPOWER:
  	if(sleepMode)
  	{
    GPS.end();
  		Radio.Sleep( );
  		display.stop();
  		detachInterrupt(RADIO_DIO_1);
  		turnOffRGB();
  	    pinMode(Vext,ANALOG);
  	    pinMode(ADC,ANALOG);
  	}
  	lowPowerHandler();
    break;
case GPSTEST:
  showGpsInfo();
  break;
default:
  break;

}
Radio.IrqProcess( );
}

void OnTxDone( void )
{
Serial.print(“TX done…”);
displayInof();
turnOnRGB(0,0);
state=RX;
}

void OnTxTimeout( void )
{
Radio.Sleep( );
Serial.print(“TX Timeout…”);
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
Rssi=rssi;
rxSize=size;
memcpy(rxpacket, payload, size );
rxpacket[size]=’\0’;
turnOnRGB(0x001000,100);
turnOnRGB(0,0);
Radio.Sleep( );

Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxpacket,Rssi,rxSize);
Serial.println("wait to send next packet");
displayInof();

state=TX;

}

void displayInof()
{
display.clear();
display.drawString(0, 50, “Packet " + String(txNumber,DEC) + " sent done”);
display.drawString(0, 0, “Received Size " + String(rxSize,DEC) + " packages:”);
display.drawString(0, 15, rxpacket);
display.drawString(0, 30, "With rssi " + String(Rssi,DEC));
display.display();
}

void userKey(void)
{
delay(10);
if(digitalRead(P3_3)==0)
{
uint16_t keyDownTime = 0;
while(digitalRead(P3_3)==0)
{
delay(1);
keyDownTime++;
if(keyDownTime>=700)
break;
}
if(keyDownTime<700)
{
state = LOWPOWER;
sleepMode = true;
}
else
{
state = GPSTEST;
detachInterrupt(RADIO_DIO_1);
Radio.Sleep( );
turnOnRGB(0,0);
GPS.begin();
}
}
}

void testRGB(void)
{
display.drawString(0, 20, “RGB Testing”);
display.display();
for(uint32_t i=0;i<=30;i++)
{
turnOnRGB(i<<16,10);
}
for(uint32_t i=0;i<=30;i++)
{
turnOnRGB(i<<8,10);
}
for(uint32_t i=0;i<=30;i++)
{
turnOnRGB(i,10);
}
turnOnRGB(0,0);
}

void showGpsInfo()
{ uint32_t starttime = millis();
while( (millis()-starttime) < 1000 )
{
while (GPS.available() > 0)
{
GPS.encode(GPS.read());
}
}

char str[30];
display.clear();
display.setFont(ArialMT_Plain_10);
int index = sprintf(str,"%02d-%02d-%02d",GPS.date.year(),GPS.date.day(),GPS.date.month());
str[index] = 0;
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 0, str);

index = sprintf(str,"%02d:%02d:%02d",GPS.time.hour(),GPS.time.minute(),GPS.time.second(),GPS.time.centisecond());
str[index] = 0;
display.drawString(60, 0, str);

if( GPS.location.age() < 1000 )
{
display.drawString(120, 0, “A”);
}
else
{
display.drawString(120, 0, “V”);
}

index = sprintf(str,“alt: %d.%d”,(int)GPS.altitude.meters(),fracPart(GPS.altitude.meters(),2));
str[index] = 0;
display.drawString(0, 16, str);

index = sprintf(str,“hdop: %d.%d”,(int)GPS.hdop.hdop(),fracPart(GPS.hdop.hdop(),2));
str[index] = 0;
display.drawString(0, 32, str);

index = sprintf(str,“lat : %d.%d”,(int)GPS.location.lat(),fracPart(GPS.location.lat(),4));
str[index] = 0;
display.drawString(60, 16, str);

index = sprintf(str,“lon:%d.%d”,(int)GPS.location.lng(),fracPart(GPS.location.lng(),4));
str[index] = 0;
display.drawString(60, 32, str);

index = sprintf(str,“speed: %d.%d km/h”,(int)GPS.speed.kmph(),fracPart(GPS.speed.kmph(),3));
str[index] = 0;
display.drawString(0, 48, str);
display.display();
}
int fracPart(double val, int n)
{
return (int)((val - (int)(val))*pow(10,n));
}

The code for the transmitter I have so far is next. But please note that it does not include the transmission part, as everything I have tried thus far is not compiling.

#include “LoRaWan_APP.h”
#include “Arduino.h”
#include “HT_SSD1306Wire.h”
#include “GPS_Air530.h”
#include “GPS_Air530Z.h”
#include <Wire.h>

Air530Class GPS;

extern SSD1306Wire display;

int fracPart(double val, int n)
{
return (int)((val - (int)(val))*pow(10,n));
}

#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

#define RF_FREQUENCY 915000000
#define TX_OUTPUT_POWER 14
#define LORA_BANDWIDTH 0
#define LORA_SPREADING_FACTOR 7
#define LORA_CODINGRATE 1
#define LORA_PREAMBLE_LENGTH 8
#define LORA_SYMBOL_TIMEOUT 0
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
char TxLatitude;
char TxLongitude;
char TxSpeed;
char TxAltitude;
char TxSatelite;
char TxHdop;

static RadioEvents_t RadioEvents;
void OnTxDone( void );
void OnTxTimeout( void );

typedef enum
{
RX,
TX,
}States_t;

States_t state;

void OnTxDone( void )
{
turnOnRGB(0,0);
state=TX;
}

void OnTxTimeout( void )
{
Radio.Sleep( );
state=TX;
}

void setup() {
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
delay(10);

display.init();
//display.flipScreenVertically();
display.clear();
display.display();

display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setFont(ArialMT_Plain_16);
display.drawString(64, 32-16/2, “GPS initing…”);
display.display();

Serial.begin(115200);
GPS.begin();
GPS.setmode(MODE_GPS_GLONASS);
//GPS.setmode(MODE_GPS_BEIDOU_GLONASS); //only Air530Z supported.

pinMode(P3_3,INPUT);
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;

Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
state=TX;
}

void loop()
{
uint32_t starttime = millis();
while( (millis()-starttime) < 1000 )
{
while (GPS.available() > 0)
{
GPS.encode(GPS.read());
}
}

char str[30];
display.clear();
display.setFont(ArialMT_Plain_10);
int index = sprintf(str,"%02d-%02d-%02d",GPS.date.year(),GPS.date.day(),GPS.date.month());
str[index] = 0;
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 0, str);

index = sprintf(str,"%02d:%02d:%02d",GPS.time.hour(),GPS.time.minute(),GPS.time.second(),GPS.time.centisecond());
str[index] = 0;
display.drawString(60, 0, str);

if( GPS.location.age() < 1000 )
{
display.drawString(120, 0, “A”);
}
else
{
display.drawString(120, 0, “V”);
}

index = sprintf(str,“alt: %d.%d”,(int)GPS.altitude.meters(),fracPart(GPS.altitude.meters(),2));
str[index] = 0;
display.drawString(0, 16, str);
TxAltitude = GPS.altitude.meters();
Radio.IrqProcess( );

index = sprintf(str,“hdop: %d.%d”,(int)GPS.hdop.hdop(),fracPart(GPS.hdop.hdop(),2));
str[index] = 0;
display.drawString(0, 32, str);
TxHdop = GPS.hdop.hdop();
Radio.IrqProcess( );

index = sprintf(str,“lat : %d.%d”,(int)GPS.location.lat(),fracPart(GPS.location.lat(),6));
str[index] = 0;
display.drawString(60, 16, str);
Serial.print(“Latitud: “);
if( GPS.location.age() < 1000 )
{
Serial.print((int)GPS.location.lat() );
Serial.print(”.”);
Serial.println(abs(fracPart(GPS.location.lat(),6)));
}
else
{
Serial.println(0);
}

TxLatitude = GPS.location.lat();
Radio.IrqProcess( );

index = sprintf(str,“lon:%d.%d”,(int)GPS.location.lng(),fracPart(GPS.location.lng(),5));
str[index] = 0;
display.drawString(60, 32, str);
Serial.print(“Longitud: “);
if( GPS.location.age() < 1000 )
{
Serial.print((int)GPS.location.lng());
Serial.print(”.”);
Serial.println(abs(fracPart(GPS.location.lng(),5)));
}
else
{
Serial.println(0);
}
TxLongitude = GPS.location.lng();

index = sprintf(str,“speed: %d.%d km/h”,(int)GPS.speed.kmph(),fracPart(GPS.speed.kmph(),1));
str[index] = 0;
display.drawString(0, 48, str);
display.display();
TxSpeed = GPS.speed.kmph();
Radio.IrqProcess( );

index = sprintf(str,“sat: %d”,(int)GPS.satellites.value());
str[index] = 0;
display.drawString(95, 48, str);
display.display();
Serial.print("Satelites: ");
Serial.println((int)GPS.satellites.value());
TxSatelite = GPS.satellites.value();
Radio.IrqProcess( );

delay (1000);
}

By the way, this is the kind of way I wanted to send the data (longitud as an example), but it did not work:

TxLongitude = GPS.location.lng();
Radio.Send( (uint8_t *)TxLongitude, strlen(TxLongitude) );
Radio.IrqProcess( );

So far, I have been unable to make the variable play nice with the uint8_t* for some reason beyond my comprehension…

Radio.Send( (uint8_t *)&TxLongitude, strlen(TxLongitude) );

Radio.Send( (uint8_t *)&TxLongitude, strlen(TxLongitude) );

Tried it, but still getting an error… invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]

Maybe you should use the string type.

Can you expand? Currently I have no idea what that means.

Any help is greatly appreciated!

Hey, guys. I really need some help with this one. I am stuck and have not been able to move forward. Any help would be greatly appreciated!

you should declare TxLongitude as a float

    float TxLongitude;
    TxLongitude = GPS.location.lng();
    Radio.Send( (uint8_t *)TxLongitude, strlen(TxLongitude) );

Thanks, Jayjay.

Unfortunately, that did not work either. Still getting

Invalid conversion from ‘char’ to ‘const char*’ [-fpermisive]

with the red line in the

Radio.Send( (uint8_t *)TxLatitude, strlen(TxLatitude) );

line (here’s the complete relevant code of that part):

  float TxLongitude;
  TxLatitude = GPS.location.lat();
  Radio.Send( (uint8_t *)TxLatitude, strlen(TxLatitude) );
  Radio.IrqProcess( );

The CubeCell-GPS on the project above is able to transmit and receive over one of four.standard protocols:

  • OGNTP, FLARM, PilotAware - FSK modulation or
  • FANET - LoRa modulation.

One who is lazy or unable to build the firmware from source code can easily install ready-to-use firmware binary.
Instructions are located on this page:

Your code is wrong: where you declared TxLongitude as a float and you are using another variable called TxLatitude instead of TxLongitude so updte your code as below:

  float TxLongitude;
  TxLatitude = GPS.location.lat();
  Radio.Send( (uint8_t *)TxLatitude, strlen(TxLatitude) );
  Radio.IrqProcess( );

new code should be since you are using both TxLatitude and TxLongitude then declare both correctly

  float TxLongitude;
  float TxLatitude ;
  TxLatitude = GPS.location.lat();
  Radio.Send( (uint8_t *)TxLatitude, strlen(TxLatitude) );
  Radio.IrqProcess( );

OK, just checking if you were paying attention! LOL!

In all honesty, I cannot believe I missed that error. Anyway, tried it with the correct lines. Still getting an error message reading:

invalid cast from type ‘float’ to type ‘uint8_t* {aka unsigned char*}’

Hi, guys. With A LOT of trial and error, I have made SOME progress. Very little, but SOME! And what I mean by some is that at last I have gotten the program to compile with the inclusion of the Radio.Send variable. However, SOMETHING is not yet working, as I cannot read the radio message on the second unit. Here is the code as of today:

//Libraries
#include "LoRaWan_APP.h"
#include "Arduino.h"
#include "HT_SSD1306Wire.h"
#include "GPS_Air530.h"
#include "GPS_Air530Z.h"
#include <Wire.h>

//GPS Setup
//if GPS module is Air530, use this
Air530Class GPS;

//if GPS module is Air530Z, use this
//Air530ZClass GPS;

//Display Setup
extern SSD1306Wire  display; 

int fracPart(double val, int n);


// LoRa Setup Values
#ifndef LoraWan_RGB
#define LoraWan_RGB                                 1
#endif

#define RF_FREQUENCY                                915000000 // Hz
#define TX_OUTPUT_POWER                             14        // dBm
#define LORA_BANDWIDTH                              0         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         0         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false
#define RX_TIMEOUT_VALUE                            1000
#define BUFFER_SIZE                                 30 // Define the payload size here

//Tx Package Variables
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
char TxLatitude;
char TxSpeed;
char TxAltitude;
char TxSatelite;
char TxHdop;

static RadioEvents_t RadioEvents;
void OnTxDone( void );
void OnTxTimeout( void );

typedef enum
{
    TX,
}States_t;

States_t state;


//---------------------------OnTxDone------------------------------
void OnTxDone( void )
{
  turnOnRGB(0,0);
  state=TX;
}

//---------------------------OnTxTimeout------------------------------
void OnTxTimeout( void )
{
    Radio.Sleep( );
    state=TX;
}


//----------------------------SETUP-------------------------------
void setup() {
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, LOW);
  delay(10);

  display.init();
  //display.flipScreenVertically();
  display.clear();
  display.display();
  
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.setFont(ArialMT_Plain_16);
  display.drawString(64, 32-16/2, "GPS initing...");
  display.display();
  
  Serial.begin(115200);
  GPS.begin();
  GPS.setmode(MODE_GPS_GLONASS);
  //GPS.setmode(MODE_GPS_BEIDOU_GLONASS);  //only Air530Z supported.

  pinMode(P3_3,INPUT);
  RadioEvents.TxDone = OnTxDone;
  RadioEvents.TxTimeout = OnTxTimeout;

// Radio Tx Configuration in Lora mode
  Radio.Init( &RadioEvents );
  Radio.SetChannel( RF_FREQUENCY );
  Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                                 LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                                 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                                 true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
  state=TX;
}


//----------------------------LOOP-------------------------------
void loop()
{
  uint32_t starttime = millis();
  while( (millis()-starttime) < 1000 )
  {
    while (GPS.available() > 0)
    {
      GPS.encode(GPS.read());
    }
  }
  
  char str[30];
  display.clear();
  display.setFont(ArialMT_Plain_10);
  int index = sprintf(str,"%02d-%02d-%02d",GPS.date.year(),GPS.date.day(),GPS.date.month());
  str[index] = 0;
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(0, 0, str);
  
  index = sprintf(str,"%02d:%02d:%02d",GPS.time.hour(),GPS.time.minute(),GPS.time.second(),GPS.time.centisecond());
  str[index] = 0;
  display.drawString(60, 0, str);

  if( GPS.location.age() < 1000 )
  {
    display.drawString(120, 0, "A");
  }
  else
  {
    display.drawString(120, 0, "V");
  }
  
  index = sprintf(str,"alt: %d.%d",(int)GPS.altitude.meters(),fracPart(GPS.altitude.meters(),2));
  str[index] = 0;
  display.drawString(0, 16, str);


     // HDOP: 
     // The effect of the Dilution of Precision on the horizontal position value. The more good visible 
     // satellites low in the sky, the better the HDOP and the horizontal position (Latitude and Longitude) are.
     // 1 = Ideal
     // 1~2 = Excellent
     // 2~5 = Good
     // 5~10 =  Moderate
     // 10~20 = Fair
     // >20 = Poor
   
  index = sprintf(str,"hdop: %d.%d",(int)GPS.hdop.hdop(),fracPart(GPS.hdop.hdop(),2));
  str[index] = 0;
  display.drawString(0, 32, str);
  Serial.print("Precison: ");
  
    
    if ((int)GPS.hdop.hdop() > 20){
    Serial.println("Poor");
  }
    else if ((int)GPS.hdop.hdop() <= 1){
    Serial.println("Perfect");
  }
  else if ((int)GPS.hdop.hdop() <= 2){
    Serial.println("Excellent");
  }
  else if ((int)GPS.hdop.hdop() <= 5){
    Serial.println("Good");
  }
  else if ((int)GPS.hdop.hdop() <= 10){
    Serial.println("Moderate");
  }
  else if ((int)GPS.hdop.hdop() <= 20){
    Serial.println("Fair");
  }
  else Serial.println("ERROR");
  
     // Para la ubicacion de GPS, el primer decimal nos lleva a un rango de 11.1 Km
     // 2 decimales dan un rango de 1.1Km, 3 decimales 110m, 4 decimales 11m, y 5 decimales 1.1m
     // 6 decimales son 11cm, que es mucho menos que la exactitud de la que tiene este GPS
  
  index = sprintf(str,"lat :  %d.%d",(int)GPS.location.lat(),fracPart(GPS.location.lat(),6));
  str[index] = 0;
  display.drawString(60, 16, str); 
  Serial.print("Latitud: ");
  if( GPS.location.age() < 1000 )
    {
      Serial.print((int)GPS.location.lat() );
      Serial.print(".");
      Serial.println(abs(fracPart(GPS.location.lat(),6)));
    }
    else
  {
    Serial.println(0);
  }
  
  index = sprintf(str,"lon:%d.%d",(int)GPS.location.lng(),fracPart(GPS.location.lng(),5));
  str[index] = 0;
  display.drawString(60, 32, str);
  Serial.print("Longitud: ");
    if( GPS.location.age() < 1000 )
    {
     Serial.print((int)GPS.location.lng());
     Serial.print(".");
     Serial.println(abs(fracPart(GPS.location.lng(),5)));
    }
    else
  {
    Serial.println(0);
  }
  
  index = sprintf(str,"speed: %d.%d km/h",(int)GPS.speed.kmph(),fracPart(GPS.speed.kmph(),1));
  str[index] = 0;
  display.drawString(0, 48, str);
  display.display();

  index = sprintf(str,"sat: %d",(int)GPS.satellites.value());
  str[index] = 0;
  display.drawString(95, 48, str);
  display.display();
  Serial.print("Satelites: ");
  Serial.println((int)GPS.satellites.value());

  Serial.println();
  Serial.print("Data: ");
      if( GPS.location.age() < 1000 )
    {
      sprintf(txpacket,"lat: %d.%d",(int)GPS.location.lat(),abs(fracPart(GPS.location.lat(),6)));
      Radio.Send( (uint8_t *)txpacket, strlen(txpacket) );
      Radio.IrqProcess( );
      Serial.println(txpacket);
    }
    else {
      sprintf(txpacket,"lat: NO DATA");
      Radio.Send( (uint8_t *)txpacket, strlen(txpacket) );
      Radio.IrqProcess( );
      Serial.println(txpacket);
  }

    Serial.print("Data: ");
      if( GPS.location.age() < 1000 )
    {
      sprintf(txpacket,"lng: %d.%d",(int)GPS.location.lng(),abs(fracPart(GPS.location.lng(),5)));
      Radio.Send( (uint8_t *)txpacket, strlen(txpacket) );
      Radio.IrqProcess( );
      Serial.println(txpacket);
    }
    else {
      sprintf(txpacket,"lng: NO DATA");
      Radio.Send( (uint8_t *)txpacket, strlen(txpacket) );
      Radio.IrqProcess( );
      Serial.println(txpacket);
  }
  
  Serial.println();
  delay (1000);
}

int fracPart(double val, int n)
{
  return (int)((val - (int)(val))*pow(10,n));
}

I am at the point where I am seriously considering paying someone to make this program for me! Any ideas how to go about that and what it could cost?

1 Like

Hi, trying to do the same thing. Have you gotten it working?

I GOT IT AHAHALKHA

I made a char array containing the data that i needed. I’ll send the code. It’s really messy and inefficient in how it works and can easily be made better, but it works!

Sender code:

//transfer comm and gps code here, send and make reciever of the same type as being sent.

#include “Arduino.h”
#include “GPS_Air530.h”
#include “LoRaWan_APP.h”

//is it 530Z or 530?
Air530Class Gps;

struct TransData
{
double latitude;
double longitude;
double altitudeM;
double signalQuality;
int locationAge;
double speedKmph;
double courseDeg;
int satellitesConnected;;
int gps_year;
int gps_day;
int gps_month;
int gps_hour;
int gps_minute;
int gps_second;
int gps_centisecond;

//year, day, month, hour, minute, second, centisecond, lat, lng, alt.meters, sats, hdop (quality), age, coursedeg, speedkmph
};

TransData data;

#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

#define RF_FREQUENCY 915000000 // Hz

#define TX_OUTPUT_POWER 14 // dBm

#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7…SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false

#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 32 // Define the payload size here

char finalMessage[BUFFER_SIZE];

char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;

int sentNumber;//the number of communication is being sent to make sure in sync

int16_t rssi,rxSize; // rssi is recieve strength. Why is it on the sender?

void DoubleToString( char *str, double double_num,unsigned int len);

uint32_t gpsTimer = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Gps.begin(9600);
Gps.setmode(MODE_GPS);

rssi=0;

Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                               LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                               LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                               true, 0, 0, LORA_IQ_INVERSION_ON, 3000 ); 

}

void loop() {
// put your main code here, to run repeatedly:

String message = encodeMessage();
message.toCharArray(finalMessage, BUFFER_SIZE);

Radio.Send((uint8_t *)finalMessage, strlen(finalMessage));
Serial.println(“SENT!----------------------------------------------”);
delay(1000);
}

String encodeMessage(){
readGps();//read raw data
updateInfo();//update all variables and data from raw
String message = “”;
char buff[12];
message += data.gps_hour;
message += “:”;
message += data.gps_minute;
message += “:”;
message += data.gps_second;
message += “,”;
message += data.satellitesConnected;
message += “,”;
dtostrf(data.latitude, 5, 6, buff);
message += buff;
message += “,”;
dtostrf(data.longitude, 5, 6, buff);
message += buff;
message += “,”;
message += data.altitudeM;

/*
Serial.println("*********************************");
Serial.println(message);
Serial.println("*********************************");
*/
return message;
}

void readGps(){

if(millis() - gpsTimer > 1000){
while(Gps.available() > 0){

  Gps.encode(Gps.read());
}
gpsTimer = millis();

}

if (millis() > 5000 && Gps.charsProcessed() < 10)
{
Serial.println(“No GPS detected: check wiring.”);
while(true);
}
}

void updateInfo()
{

/*//DEBUG PRINTS FOR LOOP
Serial.print("day: "); Serial.println(data.gps_day);
Serial.print("month: ");Serial.println(data.gps_month);
Serial.print("gps_year: "); Serial.println(data.gps_year);
Serial.print("hour: "); Serial.println(data.gps_hour);
Serial.print("gps_minute: "); Serial.println(data.gps_minute);
Serial.print("gps_second: "); Serial.println(data.gps_second);
Serial.print("gps_centisecond: "); Serial.println(data.gps_centisecond);
Serial.print("latitude: "); Serial.println(data.latitude);
Serial.print("longitude: "); Serial.println(data.longitude);
Serial.print("altitudeM: "); Serial.println(data.altitudeM);
Serial.print("satellites: "); Serial.println(data.satellitesConnected;);
Serial.print("signalQuality: "); Serial.println(data.signalQuality);
Serial.print("locationAge: "); Serial.println(data.locationAge);
Serial.print("courseDeg: "); Serial.println(data.courseDeg);
Serial.print(“speedKmph: “); Serial.println(data.speedKmph);
Serial.println(”>>>>>>>>>>>>>>>>>>…”);
delay(1000);
*/
Serial.print(“Date/Time: “);
if (Gps.date.isValid())
{
data.gps_day = Gps.date.day();
data.gps_month = Gps.date.month();
data.gps_year = Gps.date.year();
Serial.printf(”%d/%02d/%02d”,Gps.date.year(),Gps.date.day(),Gps.date.month());

}
else
{
Serial.print(“INVALID”);
}

if (Gps.time.isValid())
{
data.gps_hour = Gps.time.hour();
data.gps_minute = Gps.time.minute();
data.gps_second = Gps.time.second();
data.gps_centisecond = Gps.time.centisecond();
Serial.printf(" %02d:%02d:%02d.%02d",Gps.time.hour(),Gps.time.minute(),Gps.time.second(),Gps.time.centisecond());
}
else
{
Serial.print(" INVALID");
}
Serial.println();
data.latitude = Gps.location.lat();
data.longitude = Gps.location.lng();
data.altitudeM = Gps.altitude.meters();
Serial.print("LAT: “);
Serial.print(Gps.location.lat(),6);
Serial.print(”, LON: “);
Serial.print(Gps.location.lng(),6);
Serial.print(”, ALT: ");
Serial.print(Gps.altitude.meters());

data.satellitesConnected = Gps.satellites.value();
data.signalQuality = Gps.hdop.hdop();
data.locationAge = Gps.location.age();
data.courseDeg = Gps.course.deg();
data.speedKmph = Gps.speed.kmph();
Serial.println();
Serial.print("SATS: “);
Serial.print(Gps.satellites.value());
Serial.print(”, HDOP: “);
Serial.print(Gps.hdop.hdop());
Serial.print(”, AGE: “);
Serial.print(Gps.location.age());
Serial.print(”, COURSE: “);
Serial.print(Gps.course.deg());
Serial.print(”, SPEED: ");
Serial.println(Gps.speed.kmph());
Serial.println();
}

Reciever code:

//use gpsdata structure to store recieved data to do something with, constantly updating. 

#include “LoRaWan_APP.h”
#include “Arduino.h”

#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

#define RF_FREQUENCY 915000000 // Hz

#define TX_OUTPUT_POWER 14 // dBm

#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7…SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false

#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30 // Define the payload size here

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;

int16_t txNumber;

int16_t rssi,rxSize;

struct recieveData
{
double latitude;
double longitude;
double altitudeM;
double signalQuality;
int locationAge;
double speedKmph;
double courseDeg;
int sats;
int gps_year;
int gps_day;
int gps_month;
int gps_hour;
int gps_minute;
int gps_second;
int gps_centisecond;

//year, day, month, hour, minute, second, centisecond, lat, lng, alt.meters, sats, hdop (quality), age, coursedeg, speedkmph
};

recieveData gpsData;

void setup() {
Serial.begin(115200);

txNumber=0;
rssi=0;

  RadioEvents.RxDone = OnRxDone;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );

Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                               LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                               LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                               0, true, 0, 0, LORA_IQ_INVERSION_ON, true );

turnOnRGB(COLOR_SEND,0); //change rgb color
Serial.println(“into RX mode”);
}

void loop()
{
Radio.Rx( 0 );
delay(500);
Radio.IrqProcess( );
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
rssi=rssi;
rxSize=size;
memcpy(rxpacket, payload, size );
rxpacket[size]=’\0’;
turnOnRGB(COLOR_RECEIVED,0);
Radio.Sleep( );
Serial.printf("\r\nreceived packet “%s” with rssi %d , length %d\r\n",rxpacket,rssi,rxSize);

}

the key was just in

String message = encodeMessage();
message.toCharArray(finalMessage, BUFFER_SIZE);
Radio.Send((uint8_t *)finalMessage, strlen(finalMessage));