Full scale GPS Payload

Hi . Can someone help me with Full scale gps payload? I send it to frame port 3 with chanel first, then 4 bytes lon, 4 bytes lat and 2 bytes alt. But cayenne don’t recognized it. When i use the default payload structure and define data type 88 everything is ok - map is showing the position.

Thanks.

you can find a example here http://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-examples-device-with-gps

Thank you for quick response .
Like i said the examples work ! But i want to use full scale GPS payload like is wrote here (Cayenne LPP 2.0) . IPSO expansion pack also don’t work for me? Can you confirm that the IPSO extension pack and LPP2 (i need only full scale gps payload) is integrated in cayenne?

Regards

Hello @shramik_salgaonkar. I have the same problem with Full Scale GPS. I saw the exapmle from you, but this is NOT the full scale GPS if you dont know . Is the LPP 2 is implemented or not ? Pls share example with Full Scale GPS LPP 2 ‘‘11 bytes’’.

@todor.velev @n.manchevmobb here is some code I was using when I was testing with lora/gps.

#include <SoftwareSerial.h>
#include <Wire.h> // for IIC communication
#include "TimerOne.h"
#include <Adafruit_GPS.h>

//GPS info
Adafruit_GPS GPS(&Serial1);
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO false
// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

//************** Device parameters for registration *****************
////////////////////////////////////////////////////////////
char DEVICE_EUI[] = "";
char DEVICE_ADDR[] = "";  //4 bytes required
char APP_KEY[] = ""; //16 bytes required
char NWK_SESSION_KEY[] = ""; //network session key
char APP_SESSION_KEY[] = ""; //network session key
////////////////////////////////////////////////////////////

//************** ACCELEROMETER THRESHOLDS*******************************
#define xThreshold 0.5
#define yThreshold 0.5
#define zThreshold 0.5

//**************** TEMPERATURE SAMPLE TIME *******************************
#define TEMP_SAMPLE_TIME 100   //sample time for temperature


//******************** Channel Status *******************
//set bit channel on = 1, channel off = 0
//bank 0 = channels 0-7, bank 1 = channels 8-15, bank 2 = channels 16-23, bank 3 = channels 24-31, bank 4 = channels 32-39,
//bank 5 = channels 40-47, bank 6 = channels 48-55, bank 7 = channels 56-63, bank 8 = channels 64-71,
//MSB = highest channel number in bank. Example Bank 2 = b11000000. Channels 23 and  22 are on

byte channelBank[] = {B11111111, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B11111111}; 


#define accAddress 0x1D    //right justified accelerometer address
#define tmpAddress 0x48     //right justified TMP112 address
#define I2C_WRITE Wire.write 
#define I2C_READ Wire.read

/******************** ACCELEROMETER Data ************/
// adresss of accelerometer
#define adress_acc    0X1D // MMA8653FC and MMA8652FC

// adress of registers for MMA8653FC
#define ctrl_reg1     0x2A
#define ctrl_reg2     0x2B
#define ctrl_reg3     0x2C
#define ctrl_reg4     0x2D
#define ctrl_reg5     0x2E
#define int_source    0x0C
#define status_       0x00
#define f_setup       0x09
#define out_x_msb     0x01
#define out_y_msb     0x03
#define out_z_msb     0x05
#define sysmod        0x0B
#define xyz_data_cfg  0x0E
#define ff_mt_cfg     0x15
#define ff_mt_src     0x16
#define ff_mt_ths     0x17
#define ff_mt_count   0x18

//************** set resolution of accelerometer *************************
//#define resolution   0.0038;        //resolution for 2g
//#define resolution   0.0078;        //resolution for 4g
#define resolution     0.0156;        //resolution for 8g

//************** set range of accelerometer *************************
//#define range         0x00  //2G full scale
//#define range         0x01  //4G full scale
#define range         0x02  //8G full scale

//************** configure accelerometer *************************
//#define accConfig      0x00    // Output data rate at 800Hz, no auto wake, no auto scale adjust, no fast read mode
//#define accConfig      0x21    // Output data rate at 200Hz, no auto wake, no auto scale adjust, no fast read mode
#define accConfig      0x41    // Output data rate at 50Hz, no auto wake, no auto scale adjust, no fast read mode
//#define accConfig      0x71    // Output data rate at 1.5Hz, no auto wake, no auto scale adjust, no fast read mode



//****************** sensor variables **************************
float axeXnow ;
float axeYnow ;
float axeZnow ;
float axeXprev;
float axeYprev;
float axeZprev;
float tempC;

int printTemp;
int printXaxis;
int printYaxis;
int printZaxis;
long printLat;
long printLong;
long printAlt;
char charVal[4][5];
char charGPS[2][7];
long tempCounter;

//*******************************************************************************************************
SoftwareSerial loraSerial(10, 11); // RX, TX   ** Set to 10, 11 for Mega2560 boards

void setup() {

delay(1000);                //startup delay - gives Lora module time to reset if cold start
Serial.begin(115200);        //terminal serial port
loraSerial.begin(57600);      
Wire.begin();                              // join i2c bus
ACC_INIT();                                //initialize accelerometer

getConfig();                           //get module information
setChannelStatus();                        //configure channels to be on or off

configureABP();                          //configure Access By Personalization (ABP)
//configureOTAA();                         //configure Over The Air Activation (OTAA)

Timer1.initialize(500000);         // initialize timer1, and set to 0.5 second period
Timer1.attachInterrupt(systemTimer);    //set ISR

I2C_READ_ACC(0x01);   //get initial readings
axeXprev = axeXnow;
axeYprev = axeYnow;
axeZprev = axeZnow;

tempCounter = 0;

  //GPS Setup
  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);
  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!
  useInterrupt(true);
  delay(1000);
}

//GPS Functions
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

String padGPS(String hex){
  String validHEX;
  int len = hex.length();
  switch (len){
    case 1:
      validHEX = "00000" + hex;
      break;
    case 2:
      validHEX = "0000" + hex;
      break;
    case 3:
      validHEX = "000" + hex;
      break;
    case 4:
      validHEX = "00" + hex;
      break;
    case 5:
      validHEX = "0" + hex;
      break;
    case 6:
      validHEX = hex;
      break;
    default:
      validHEX = hex.substring(len - 6, len);
      break;
  }
  return validHEX;
}

uint32_t timer = millis();
void loop() {
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
  }
  
  /*if (millis() - timer > 2000) { 
    timer = millis(); // reset the timer

    if (GPS.fix) {
      int len;
      Serial.print("Lat : ");Serial.println(GPS.latitudeDegrees,4);
      printLat = (GPS.latitudeDegrees * 10000);
      Serial.print("Lat * 10000: ");Serial.println(printLat);
      String stringLat = String(printLat,HEX);
      Serial.print("stringLat: ");Serial.println(stringLat);
      String hexLat = padGPS(stringLat);
      Serial.print("Lat HEX: ");Serial.println(hexLat);
      hexLat.toCharArray(charGPS[0],7);
      Serial.print("Lat toCharArray: ");Serial.println(hexLat);
      
      Serial.print("Long : ");Serial.println(GPS.longitudeDegrees,4);
      printLong = (GPS.longitudeDegrees * 10000);
      Serial.print("Long * 10000: ");Serial.println(printLong);
      String stringLong = String(printLong,HEX);
      Serial.print("stringLong: ");Serial.println(stringLong);
      String hexLong = padGPS(stringLong);
      Serial.print("Long HEX: ");Serial.println(hexLong);
      hexLong.toCharArray(charGPS[1],7);
      Serial.print("Long toCharArray: ");Serial.println(hexLong);

      Serial.print("Alt: ");Serial.println(GPS.altitude);
      printAlt = GPS.altitude;
      String stringAlt = String(printAlt,HEX);
      Serial.print("stringAlt: ");Serial.println(stringAlt);
      String hexAlt = padGPS(stringAlt);
      Serial.print("Alt HEX: ");Serial.println(hexAlt);
      hexAlt.toCharArray(charGPS[2],7);
      Serial.print("Alt toCharArray: ");Serial.println(hexAlt);

      Serial.print("Prefix; ");
      Serial.println("0188");
      Serial.print("Lat; ");
      Serial.println(charGPS[0]);
      Serial.print("Long; ");
      Serial.println(charGPS[1]);
      Serial.print("Alt; ");
      Serial.println(charGPS[2]);
      Serial.print("0188");Serial.print(charGPS[0]);Serial.print(charGPS[1]);Serial.print(charGPS[2]);
    }
  }*/
  
  while (loraSerial.available()) {
    Serial.write(loraSerial.read());
  }

  if (tempCounter >= TEMP_SAMPLE_TIME)   //send data every x time
  {
     getTemperature();
     I2C_READ_ACC(0x01);
     sendAllData();
     tempCounter = 0;
  }
  delay(50);
  I2C_READ_ACC(0x01);
#if 0 
  if ((abs(axeXprev-axeXnow))>xThreshold || (abs(axeYprev-axeYnow))>yThreshold || (abs(axeZprev-axeZnow))>zThreshold)  //send data if any axis exceeds threshold
  {
     getTemperature();
     sendAllData();
     axeXprev = axeXnow;
     axeYprev = axeYnow;
     axeZprev = axeZnow;
  }
#endif
}

void sendAllData(void)
{
  Serial.println();
  Serial.println("****************************************");
  Serial.print("Temperature (deg C): ");Serial.println(tempC);
  Serial.print("X Axis Now: ");Serial.println(axeXnow);
  Serial.print("Y Axis Now: ");Serial.println(axeYnow);
  Serial.print("Z Axis Now: ");Serial.println(axeZnow);
  Serial.print("X Axis Previous: ");Serial.println(axeXprev);
  Serial.print("Y Axis Previous: ");Serial.println(axeYprev);
  Serial.print("Z Axis Previous: ");Serial.println(axeZprev);
  if (GPS.fix) {
    Serial.print("Location (in degrees, works with Google Maps): ");
    Serial.print(GPS.latitudeDegrees, 4);
    Serial.print(", "); 
    Serial.println(GPS.longitudeDegrees, 4);
    Serial.print("Alt: ");Serial.println(GPS.altitude);
  }
  Serial.println();

  formatData();
  loraSerial.print("mac tx uncnf 10 ");loraSerial.print("0167");loraSerial.print(charVal[0]);
  loraSerial.print("0271");loraSerial.print(charVal[1]);loraSerial.print(charVal[2]);loraSerial.println(charVal[3]);
  delay(5000);
  loraSerial.print("mac tx uncnf 10 ");loraSerial.print("0388");loraSerial.print(charGPS[0]);loraSerial.print(charGPS[1]);loraSerial.println(charGPS[2]);
  
  Serial.print("mac tx uncnf 10 ");Serial.print("0167");Serial.print(charVal[0]);
  Serial.print("0471");Serial.print(charVal[1]);Serial.print(charVal[2]);Serial.println(charVal[3]);
  Serial.print("mac tx uncnf 10 ");Serial.print("0388");Serial.print(charGPS[0]);Serial.print(charGPS[1]);Serial.println(charGPS[2]);
  
  waitCommandResponse();

}

void systemTimer(void)
{
  tempCounter++;
  
}


//************************ format data for lora tx **********************************
//modified for Cayenne Lora
void formatData(void)
{
  int len;
   
  printTemp = int(tempC*10);
  String stringT = String(printTemp,HEX);
  len = stringT.length();
  stringT.toCharArray(charVal[0],5);
  leadingZero(0,len);
  
  printXaxis = int(axeXnow * 1000);
  String stringX = String(printXaxis,HEX);
  len = stringX.length();
  stringX.toCharArray(charVal[1],5);
  leadingZero(1,len);

  printYaxis = int(axeYnow * 1000);
  String stringY = String(printYaxis,HEX);
  len = stringY.length();
  stringY.toCharArray(charVal[2],5);
  leadingZero(2,len);

  printZaxis = int(axeZnow * 1000);
  String stringZ = String(printZaxis,HEX);
  len = stringZ.length();
  stringZ.toCharArray(charVal[3],5);
  leadingZero(3,len);

  printLat = (GPS.latitudeDegrees * 10000);
  String stringLat = String(printLat,HEX);
  String hexLat = padGPS(stringLat);
  hexLat.toCharArray(charGPS[0],7);

  printLong = (GPS.longitudeDegrees * 10000);
  String stringLong = String(printLong,HEX);
  String hexLong = padGPS(stringLong);
  hexLong.toCharArray(charGPS[1],7);
  
  printAlt = GPS.altitude;
  String stringAlt = String(printAlt,HEX);
  String hexAlt = padGPS(stringAlt);
  hexAlt.toCharArray(charGPS[2],7);
}
//********************* Add leading zeros to hex value ********************************
void leadingZero(byte dataID, byte lenStr)
{
  charVal[dataID][4]='\0';
  
  if (lenStr==3)
  {
    charVal[dataID][3]=charVal[dataID][2];
    charVal[dataID][2]=charVal[dataID][1];
    charVal[dataID][1]=charVal[dataID][0];
    charVal[dataID][0]='0';
  }
  else if (lenStr==2)
  {    
    charVal[dataID][3]=charVal[dataID][1];
    charVal[dataID][2]=charVal[dataID][0];
    charVal[dataID][1]='0';
    charVal[dataID][0]='0';
  }
  else if (lenStr==1)
  {
    charVal[dataID][3]=charVal[dataID][0];
    charVal[dataID][2]='0';
    charVal[dataID][1]='0';
    charVal[dataID][0]='0';
  }
}
//****************** Write to I2C Slave Registers *********************************************

void I2C_SEND(unsigned char REG_ADDRESS, unsigned  char DATA)  //SEND data to MMA7660
{
  
  Wire.beginTransmission(adress_acc);
  Wire.write(REG_ADDRESS);
  Wire.write(DATA);
  Wire.endTransmission();
}

//****************************** Read I2C Slave register *******************************************
void I2C_READ_REG(int ctrlreg_address) //READ number data from i2c slave ctrl-reg register and return the result in a vector
{
  unsigned char REG_ADDRESS;
  int i=0; 
  Wire.beginTransmission(adress_acc); //=ST + (Device Adress+W(0)) + wait for ACK
  Wire.write(ctrlreg_address);  // register to read
  Wire.endTransmission();
  Wire.requestFrom(adress_acc,1); // read a number of byte and store them in write received
}

//****************** Accelerometer Initialization ************************************
 void ACC_INIT()
{
    I2C_SEND(ctrl_reg1 ,0X00); // standby to be able to configure
    delay(10);
    I2C_SEND(f_setup ,B01100000); // set FIFO mode - circular mode 32 byte watermark
    delay(5);
    I2C_SEND(xyz_data_cfg ,range); // set full range
    delay(1);
    I2C_SEND(ctrl_reg1 ,accConfig); // configure accelerometer
    delay(1);
}
//************************** Read Acceleromter Registers ************************************

void I2C_READ_ACC(int ctrlreg_address) //READ number data from i2c slave ctrl-reg register and return the result in a vector
{
  byte REG_ADDRESS[7];
  int accel[4];
  int i=0; 
  Wire.beginTransmission(adress_acc); //=ST + (Device Adress+W(0)) + wait for ACK
  Wire.write(ctrlreg_address);  // store the register to read in the buffer of the wire library
  Wire.endTransmission(); // actually send the data on the bus -note: returns 0 if transmission OK-
  Wire.requestFrom(adress_acc,7); // read a number of byte and store them in wire.read (note: by nature, this is called an "auto-increment register adress")

  for(i=0; i<7; i++) // 7 because on datasheet p.19 if FREAD=0, on auto-increment, the adress is shifted
  // according to the datasheet, because it's shifted, outZlsb are in adress 0x00
  // so we start reading from 0x00, forget the 0x01 which is now "status" and make the adapation by ourselves
  //this gives:
  //0 = status
  //1= X_MSB
  //2= X_LSB
  //3= Y_MSB
  //4= Y_LSB
  //5= Z_MSB
  // 6= Z_LSB
  {
  REG_ADDRESS[i]=Wire.read(); //each time you read the write.read it gives you the next byte stored. The couter is reset on requestForm
}


// MMA8653FC gives the result in 10bits. 8bits are in _MSB, and 2 are in _LSB
// this part is used to concatenate both, and then put a sign on it (the most significant bit is giving the sign)
// the explanations are on p.14 of the 'application notes' given by freescale.
      for (i=1;i<7;i=i+2)
      {
      accel[0] = (REG_ADDRESS[i+1]|((int)REG_ADDRESS[i]<<8))>>6; // X
        if (accel[0]>0x01FF) {accel[1]=(((~accel[0])+1)-0xFC00);} // note: with signed int, this code is optional
        else {accel[1]=accel[0];} // note: with signed int, this code is optional
            switch(i){
            case 1: axeXnow=accel[1]*resolution;
                              break;
            case 3: axeYnow=accel[1]*resolution;
                              break;
             case 5: axeZnow=accel[1]*resolution;
                              break;
                }
       }

}

//******************** Temperature Sensor (TMP112) Reading *****************************
void getTemperature(void)
{
  long tempSum;
  int tempReadingIn[2];
  Wire.requestFrom(tmpAddress,2); 
  tempReadingIn[0] = Wire.read();
  tempReadingIn[1] = Wire.read();

  //it's a 12bit int, using two's compliment for negative
  tempSum = ((tempReadingIn[0] << 8) | tempReadingIn[1]) >> 4; 
  tempC = tempSum*0.0625;
}

//********************* configure ABP ************************************************
void configureABP(void)
{
  loraSerial.print("mac set deveui ");loraSerial.println(DEVICE_EUI);
  Serial.print("mac set deveui ");Serial.println(DEVICE_EUI);
  waitCommandResponse();
  
  //loraSerial.print("mac set appeui ");loraSerial.println(APP_EUI);
  //Serial.print("mac set appeui ");Serial.println(APP_EUI);
  //waitCommandResponse();
  
  loraSerial.print("mac set appkey ");loraSerial.println(APP_KEY);
  Serial.print("mac set appkey ");Serial.println(APP_KEY);
  waitCommandResponse();
  loraSerial.print("mac set devaddr ");loraSerial.println(DEVICE_ADDR);
  Serial.print("mac set devaddr ");Serial.println(DEVICE_ADDR);
  waitCommandResponse();
  loraSerial.print("mac set nwkskey ");loraSerial.println(NWK_SESSION_KEY);
  Serial.print("mac set nwkskey ");Serial.println(NWK_SESSION_KEY);
  waitCommandResponse();
  loraSerial.print("mac set appskey ");loraSerial.println(APP_SESSION_KEY);
  Serial.print("mac set appskey ");Serial.println(APP_SESSION_KEY);
  waitCommandResponse();
  loraSerial.println("mac save");
  Serial.println("mac save");
  waitCommandResponse();
  loraSerial.println("mac join abp");
  Serial.println("mac join abp");
  waitCommandResponse();
}

#if 0 //not supported on free account
//************************ configure OTAA ************************************
void configureOTAA(void)
{
  loraSerial.print("mac set deveui ");loraSerial.println(DEVICE_EUI);
  Serial.print("mac set deveui ");Serial.println(DEVICE_EUI);
  waitCommandResponse();
  loraSerial.print("mac set appeui ");loraSerial.println(APP_EUI);
  Serial.print("mac set appeui ");Serial.println(APP_EUI);
  waitCommandResponse();
  loraSerial.print("mac set appkey ");loraSerial.println(APP_KEY);
  Serial.print("mac set appkey ");Serial.println(APP_KEY);
  waitCommandResponse();
  loraSerial.println("mac save");
  Serial.println("mac save");
  waitCommandResponse();
  loraSerial.println("mac join otaa");
  Serial.println("mac join otaa");
   waitCommandResponse();
}
#endif

//********************* configure channels on or off ******************************
void setChannelStatus()
{
  byte channelNumber=0;
  for (int x=0; x<9; x++)
  {
    for (int b=0; b<8; b++)
    {
      if (bitRead(channelBank[x],b))
      {
        loraSerial.print("mac set ch status ");loraSerial.print(channelNumber);loraSerial.println(" on");
        Serial.print("mac set ch status ");Serial.print(channelNumber);Serial.println(" on");
      }
      else
      {
        loraSerial.print("mac set ch status ");loraSerial.print(channelNumber);loraSerial.println(" off");
        Serial.print("mac set ch status ");Serial.print(channelNumber);Serial.println(" off");
      }
    channelNumber++;
    waitCommandResponse();
    }
  }
  loraSerial.println("mac set adr off");
  Serial.println("mac set adr off");
  waitCommandResponse();
  loraSerial.println("mac set pwridx 5");
  Serial.println("Set Tx power");
  waitCommandResponse();
  //loraSerial.println("mac set dr 4");
  //Serial.println("Set Data Rate 4");
  //waitCommandResponse();
  loraSerial.println("mac save");
  delay(200);
}

//******************** wait for response from module *************************************
void waitCommandResponse(void)
{
  unsigned long currentTime,startTime;
  startTime = millis(); 
  while (loraSerial.available() == 0)
  {
    currentTime = millis();
    if (currentTime > (startTime + 3000))       //exit wait routine if nor response in 3 seconds
    {
      Serial.println("No Response from Lora Module");
      return;
    }
  }
 
  while (loraSerial.available()) 
    {
      Serial.write(loraSerial.read());
    }
}

//************************ get configuration information from module *********************
void getConfig(void)
{
  loraSerial.println("sys get ver");      //get module version
  Serial.print("Module Version: ");
  waitCommandResponse();
  Serial.println();
  
  loraSerial.println("sys get hweui");      //get module version
  Serial.print("EUI Node Address: ");
  waitCommandResponse();
  Serial.println();
}
1 Like