Particle and GPS Module Particle.GPS.h package help

HI

I have my GPS connected up to the Argon and can see it working just using the default package example and using putty on my COM3 port to verify values are displaying.

What i am trying to do is convert this so i can publish it as part of a JSON file.

So the following works on Putty COM3 serial port with no issues;

#include "Particle-GPS.h"

// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);

// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);

void setup()
{
  delay(2000);

  // ***
  // *** Initialize the USB Serial for debugging.
  // ***
  Serial.begin();
  Serial.println("Initializing...");

  // ***
  // *** Initialize the GPS.
  // ***
  _gps.begin(9600);

  // ***
  // *** Start the timer.
  // ***
  _timer.start();
}

void onSerialData()
{
  _gps.onSerialData();
}

void loop()
{
  // ***
  // *** Get the Antenna Status ($PGTOP).
  // ***
  Pgtop pgtop = Pgtop(_gps);
  if (pgtop.parse())
  {
    Serial.println("1) Antenna Status ($PGTOP)");
    Serial.println("======================================================");
    Serial.print("Command ID: "); Serial.println(pgtop.commandId);
    Serial.print("Antenna Status: "); Serial.println(pgtop.reference);
    Serial.println("");
  }

  // ***
  // *** Get the Global Positioning System Fixed Data ($GPGGA).
  // ***
  Gga gga = Gga(_gps);
  if (gga.parse())
  {
    Serial.print("UTC Time: "); Serial.println(gga.utcTime);
    Serial.print("Latitude: "); Serial.println(gga.latitude);
    Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
    Serial.print("Longitude: "); Serial.println(gga.longitude);
    Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
  }

  // ***
  // *** Get the Recommended Minimum Navigation Information ($GPRMC).
  // ***
  Rmc rmc = Rmc(_gps);
  if (rmc.parse())
  {
    Serial.println("3) Recommended Minimum Navigation Information ($GPRMC)");
    Serial.println("======================================================");
    Serial.print("UTC Time: "); Serial.println(rmc.utcTime);
    Serial.print("Latitude: "); Serial.println(rmc.latitude);
    Serial.print("North/SouthIndicator: "); Serial.println(rmc.northSouthIndicator);
    Serial.print("Longitude: "); Serial.println(rmc.longitude);
    Serial.print("East/WestIndicator: "); Serial.println(rmc.eastWestIndicator);
  }

  delay(1000);
}

However, what i am trying to achieve is rewrite this so i can publish the co-ordinates into a JSON file to my Particle device when i attempt to compile the code below it gives an error. I am not very good at the C language…

My code is as follows (basically just want to return one value for now);

// This #include statement was automatically added by the Particle IDE.

#include "Particle-GPS.h"

//GPS Setup
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);

// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);


void setup() {
    Wire.begin();
    Serial.begin();
      _timer.start();
    
void loop() {
    // *** Get the Antenna Status ($PGTOP).
    Pgtop pgtop = Pgtop(_gps);
  // *** Get the Global Positioning System Fixed Data ($GPGGA).
  // ***
  Gga gga = Gga(_gps);   
 
    // create JSON ojects set ups
    char buf[622];
    memset(buf, 0, sizeof(buf));
    JSONBufferWriter writer(buf, sizeof(buf)-1);
    
    writer.beginObject();
    addToJSON(writer);
    writer.endObject();
    
    Particle.publish("JSON", String(buf), PRIVATE);
    
    delay(10000);
    
    toggleLed();
    
}

// function to add to JSON object
void addToJSON(JSONBufferWriter &writer){
    writer.name("UTCTime").value(String(Gga.utcTime)));
}

void onSerialData()
{
  _gps.onSerialData();
}

The issue is to do with the line;

 writer.name("UTCTime").value(String(Gga.utcTime)));

Specifically, i am just trying to get the utcTime. In the example that works this is done by;

Serial.print("UTC TIme: "); Serial.println(gga.utcTime);

Which error exactly?
The error messages usually already provide a hint about a possible solution too - especially when looking the the raw error output.

However, one error I found already: Your void setup() is missing a closing curly brace } before void loop()

OK i got it to compile and because of poor satellite signal i stuck to having only statement as

Rmc rmc = Rmc(_gps);

Then later at my statement for the JSON file i have

void addToJSONBuefferWriter &writer){
     writer.name("UTCTime").value(_gps.data);
     writer.name("A").value(_gps.data[1]);
     writer.name("B").value(_gps.data[2]);

This compiles but results show on the particle events as;

UTCTime = true
A = 0
B = 0

The fact it works on the serial port, means i am doing something wrong. I just want the values to pass over same as serial. Not sure where i am going wrong… tricky one…

Just a note on your object instantiations

Gps _gps = Gps(&Serial1);
Timer _timer = Timer(1, onSerialData);
Pgtop pgtop = Pgtop(_gps);
Gga gga = Gga(_gps);
Rmc rmc = Rmc(_gps);

are all better written as

Gps _gps(&Serial1);
Timer _timer(1, onSerialData);
Pgtop pgtop(_gps);
Gga gga(_gps);
Rmc rmc(_gps);

Also _gps.data is an array of String objects, hence I doubt writer.name("UTCTime").value(_gps.data); makes a lot of sense.

You probably want to use rmc.utcTime, rmc.latitude and rmc.longitude instead - providing rmc.parse() returned true.

In your code you are never parsing the NMEA sentences and hence will never get the “translation” of the received data.
When you have some working code (e.g. your serial output sample) you should try to understand what the individual lines in that code do and only then toss them out once you can be certain they won’t be needed for your ultimate goal :wink:

Thank you so much for your reply and makes sense. OK i’ve further amended my code as follows, yes it compiles but no values coming through to the particle events…

I’ve included my full code as i have this working alongside an accelerometer in which the values come over as expected.

Basically the results from following code in events on JSON file show;

{
"ax":"-488"
"ay":"-176"
"az":"15440"
"gx":"-525"
"gy":"287"
"gz":"-483"
"UTCTime":true
"A":""
"B":""
"C":""
"D":""
"E":""
}

The full code is;

// This #include statement was automatically added by the Particle IDE.
#include <MPU6050.h>
#include "Particle-GPS.h"

int ledPin = D7;

//GPS Setup
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps(&Serial1);

// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);

// MPU variables:
MPU6050 accelgyro;
int16_t ax, ay, az;
int16_t gx, gy, gz;

////trial
bool ledState = false;
void toggleLed() {
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
}

int analogvalue; //declaring the integer variable
String data = "";  //Used to send value to the cloud

void setup() {
    pinMode(ledPin, OUTPUT);

    Wire.begin();
    Serial.begin();
    _timer.start();
    
    //Declare variables that can be seen in the Particle console for the accelarometer
    //Particle.variable("ax",ax);
    //Particle.variable("ay",ay);
    //Particle.variable("az",az);
    //Particle.variable("gx",gx);
    //Particle.variable("gy",gy);
    //Particle.variable("gz",gz);
    
    //Declare a Particle.variable() for access values in the cloud
    Particle.variable("analogvalue", &analogvalue, INT);

    // The following line will wait until you connect to the Spark.io using serial and hit enter. This gives
    // you enough time to start capturing the data when you are ready instead of just spewing data to the UART.
    //
    // So, open a serial connection using something like:
    // screen /dev/tty.usbmodem1411 9600
    //while(!Serial.available()) SPARK_WLAN_Loop();
    
    //Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // Cerify the connection:
    //Serial.println("Testing device connections...");
    //Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}

void loop() {
    // *** Get the Antenna Status ($PGTOP).
    //Pgtop pgtop = Pgtop(_gps);
    Rmc rmc(_gps);

  // *** Get the Global Positioning System Fixed Data ($GPGGA).
  // ***
  //Gga gga = Gga(_gps);   
    
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    //Serial.print("a/g:\t");
    analogvalue = analogRead(ax);
    data = analogvalue;
   // Particle.publish("ax", String(ax), PRIVATE);
//    Particle.publish("ay", String(ay), PRIVATE);
 //   Particle.publish("az", String(az), PRIVATE);
 //   Particle.publish("gx", String(gx), PRIVATE);
 //   Particle.publish("gy", String(gy), PRIVATE);
 //   Particle.publish("gz", String(gz), PRIVATE);
    
    // create JSON ojects set ups
    char buf[622];
    memset(buf, 0, sizeof(buf));
    JSONBufferWriter writer(buf, sizeof(buf)-1);
    
    writer.beginObject();
    addToJSON(writer);
    writer.endObject();
    
    Particle.publish("JSON", String(buf), PRIVATE);
    
    delay(10000);    
    toggleLed();   
}

// function to add to JSON object
void addToJSON(JSONBufferWriter &writer){
    writer.name("ax").value(String(ax));
    writer.name("ay").value(String(ay));
    writer.name("az").value(String(az));
    writer.name("gx").value(String(gx));
    writer.name("gy").value(String(gy));
    writer.name("gz").value(String(gz));
    writer.name("UTCTime").value(_gps.data);
    writer.name("C").value(_gps.data[3]);
    writer.name("D").value(_gps.data[4]);
    writer.name("E").value(_gps.data[5]);
    writer.name("E").value(_gps.data[6]);
}

void onSerialData() {
  _gps.onSerialData();
}

Any further guidance would be much appreciated.

Just a few questions to ponder about before I offer a possible solution

  • what do you think the Rmc rmc(_gps) line is for in your loop()?
  • why is it there but rmc is never used in loop()?
  • why does the serial print example use rmc.parse() and why may I have mentioned it in my previous post?
  • what does gps.onSerialData() do exactly?
  • why is there still this line writer.name("UTCTime").value(_gps.data); although I raised this point?

Finally, when you go back to the serial print example, what do you see there in setup() that is missing in both your codes with regards to GPS?
Which brings us back to this statement

Hi thanks for your reply and for your help.

My thinking is as follows, basically i know i can output and see these values in the COM3 port, so i’m trying to convert this to publish into a JSON file. Apologies if i am wrong but let me explain my thinking in answering your questions and i am appreciating your help :slight_smile:

  • hat do you think the Rmc rmc(_gps) line is for in your loop() ?

I believe this is calling the function to get the Get the Recommended Minimum Navigation Information ($GPRMC). But again i could be wrong - i am taking this from the original code that calls the serial port an modifying as per your post which had suggested trying

Rmc rmc = Rmc(_gps);

  • why is it there but rmc is never used in loop() ?

I thought that having the statement ‘Rmc rmc(_gps);’ might be calling this?

  • why does the serial print example use rmc.parse() and why may I have mentioned it in my previous post?

There should be no print statements these were only previously used for debugging to serial port in which i can do and understand this side of things (i think)

  • what does gps.onSerialData() do exactly?

That should have been included in the first post, as it was part of the original example when i went to the library which gives a working example of the code working against the device.

  • why is there still this line writer.name("UTCTime").value(_gps.data); although I raised this point?

I had only included this in here to see what came over, i had tried other multiple lines just hoping to see something come through.

I understand my understanding on this is limited. I can work out the accelarometer part but this GPS part i’m really struggling.

As stated before i really appreciate any help you can give, or even pointers on what i can try next

Many thanks

Paul

OK, let’s address these one by one

This instruction only instantiates (constructs) an Rmc object which should act on the NmeaBuffer object (_gps) you are passing to it. But it does not do anything other than that.

The syntax in the original code is not perfect as it first instantiates a dummy object rmc, then instantiates another object Rmc(_gps) and then assigns that to overwrite the dummy object - a lot of work for no benefit but rather waste of time and memory.

Since you are not using the rmc object that you had instanitated earlier it will vanish without ever having done anything just to be re-instantiated and vanish again over and over as long loop() is being called.

This is the function that does the work: Parsing the received NMEA sentences the provided NmeaBuffer may already contain in order to populate the RMC fields of the object.
It has nothing to do whether you are printing the data or not, it’s there to have the data available when you want to use them whichever way you need them.

to which you said

I didn’t ask where it came from but rather what you think that instruction is good for :wink:

In the original example and your code this instruction is called every millisecond (less often would do just fine IMHO) to check whether new data from the GPS module has arrived in the serial buffer and if so feed it into an intermediary buffer where individual NMEA sentences are collected and then dispatched into the respective categories for further processing (e.g. via Rmc).

In your JSON example you see that this renders true as value but doesn’t really tell you anything other than that _gps.data is not a NULL pointer. That’s why I said it doesn’t make sense.

You may have missed my later edit to that post

You are missing _gps.begin(9600) which is there in the original but missing in your code, hence the GPS data acquisition is never even started and hence your data[] strings will always remain empty.

BTW

This is outdated syntax.
Nowadays we’d write it this way

Particle.variable("analogvalue", analogvalue);

Since buf already is a string you should be able to just write

  Particle.publish("JSON", buf, PRIVATE);

Many thanks for your help, i managed to get it all working with your help

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.