Electron with neo6mv2

Howdy.

I’m trying to use a neo6mv2 with the asset tracker.

Now, I know you’ll say the asset tracker already has a GPS chip in it, but my experience with it has been subpar, and I need good quality GPS for this project.

So, the setup:

VCC -> VIN
GND -> GND
RX  -> TX
TX  -> RX

The code:

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

// This #include statement was automatically added by the Particle IDE.
#include <TinyGPS.h>

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

// This #include statement was automatically added by the Spark IDE.
#include "TinyGPS.h"



// Variables
int temperature;
int humidity;

SYSTEM_THREAD(ENABLED);


int DHpin = 6;
byte dat [5];
byte read_data () {
  byte data;
  for (int i = 0; i < 8; i ++) {
    if (digitalRead (DHpin) == LOW) {
      while (digitalRead (DHpin) == LOW); // wait for 50us
      delayMicroseconds (30); // determine the duration of the high level to determine the data is '0 'or '1'
      if (digitalRead (DHpin) == HIGH)
        data |= (1 << (7-i)); // high front and low in the post
      while (digitalRead (DHpin) == HIGH); // data '1 ', wait for the next one receiver
     }
  }
return data;
}

void start_test () {
  digitalWrite (DHpin, LOW); // bus down, send start signal
  delay (30); // delay greater than 18ms, so DHT11 start signal can be detected
 
  digitalWrite (DHpin, HIGH);
  delayMicroseconds (40); // Wait for DHT11 response
 
  pinMode (DHpin, INPUT);
  while (digitalRead (DHpin) == HIGH);
  delayMicroseconds (80); // DHT11 response, pulled the bus 80us
  if (digitalRead (DHpin) == LOW);
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data
 
  for (int i = 0; i < 4; i ++) // receive temperature and humidity data, the parity bit is not considered
    dat[i] = read_data ();
 
  pinMode (DHpin, OUTPUT);
  digitalWrite (DHpin, HIGH); // send data once after releasing the bus, wait for the host to open the next Start signal
}
 

TinyGPS gps;
char szInfo[64];
// Every 15 minutes 
int sleep = 10 * 1000;


void setup(){
    pinMode (DHpin, OUTPUT);
    Serial1.begin(9600);
}

void loop(){
    bool isValidGPS = false;
    

    for (unsigned long start = millis(); millis() - start < 1000;){
        // Check GPS data is available
        while (Serial1.available()){
            char c = Serial1.read();
            
            // parse GPS data
            if (gps.encode(c))
                isValidGPS = true;
        }
    }

    // If we have a valid GPS location then publish it
    if (isValidGPS){
        float lat, lon;
        unsigned long age;
    
        gps.f_get_position(&lat, &lon, &age);
        
        sprintf(szInfo, "%.6f,%.6f", (lat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : lat), (lon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : lon));
    }
    else{
        // Not a vlid GPS location, jsut pass 0.0,0.0
        // This is not correct because 0.0,0.0 is a valid GPS location, we have to pass a invalid GPS location
        // and check it at the client side
        sprintf(szInfo, "0.0,0.0");
    }
    
    start_test ();
    

    Particle.publish("temp=", dat [0]);
    Spark.publish("temperature", dat [0] + " °C");
    

    //Spark.publish("gpsloc", szInfo);
    
    // Sleep for some time
    delay(sleep);
}

Nothing shows up on the console as a publish event.

The neo6mv2 starts blinking red after a while, but no data.

I had an older GPS chip I used previously where this worked, but my soldering skills put an end to that.

Any suggestions?

I’m starting to think there’s something wrong with this thing.

I tried ALL GPS libraries. I tried the Photon and Electron. Tried switching wires TX to RX and TX to TX. I just dont get any data. I tried BOTH of them (i have two). Unless someone has any suggestions, they are going in the garbage.

How about a most minimalistic test code without library?

void setup()  {
  Serial.begin(115200);
  Serial1.begin(9600);
}

void loop() {
  while (Serial1.available()) {
    Serial.write(Serial1.read());
  }
}

This should just dump the module’s output to USB serial.

Also make sure you leave the module running for some time with clear view at the sky to get a fix.
And unplug the controller from the Asset Tracker shield.

@r0b0tn1k, you are publishing too often, breaking the 1/sec, max 4/s burst rule so the Particle Cloud is blocking the publishes. Comment out the publishes for now and, as @ScruffR suggests, focus on just the console output.

I love how you guys managed to hunt down my proton and see my publish frequency :slight_smile:

Will test tomorrow morning, lost my nerves for tonight. If you guys were any closer to me, i’d buy you beers :slight_smile:

@r0b0tn1k, we didn’t hunt down your photon. I simply looked at your code!

Yes, I noticed that after I clicked Reply :slight_smile:

Still love you guys :slight_smile:

What a difference a day makes!

Here’s what happened:

  • Got a completely new Photon
  • Wired it up from scratch (new wires and all)
  • Coded in the minimalistic code provided by @ScruffR
  • Started getting NMEI data.

Then I used the Asset shield code on the Photon to get GPS coordinates.
30 seconds later, I had a very accurate GPS of my location.

Now, all that is great, except, I want the neo6mv2 to work with the Asset shield…
If I use the same code, it will get the coordinates from the Asset Shield GPS, and not the Neo6mv2.

Ideas?

Btw, this whole project is about sending an asset shield to space! Issue is my country is too small, so when the balloon bursts, I want it to keep in free fall until about 2000-3000 meters, when I use the servos to deploy the parachute. Otherwise according to some weather estimates, it ends up in a neighboring country, which is what I dont want.

Here’s the code below:

// This #include statement was automatically added by the Particle IDE.
#include <AssetTracker.h>

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

/* -----------------------------------------------------------
This example shows a lot of different features. As configured here
it'll check for a good GPS fix every 10 minutes and publish that data
if there is one. If not, it'll save you data by staying quiet. It also
registers 3 Particle.functions for changing whether it publishes,
reading the battery level, and manually requesting a GPS reading.
---------------------------------------------------------------*/

// Getting the library

// Set whether you want the device to publish data to the internet by default here.
// 1 will Particle.publish AND Serial.print, 0 will just Serial.print
// Extremely useful for saving data while developing close enough to have a cable plugged in.
// You can also change this remotely using the Particle.function "tmode" defined in setup()
int transmittingData = 1;
int angle = 1;
Servo myservo;
int pos = 0;
float lat, lon, alt;

// Used to keep track of the last time we published data
long lastPublish = 0;

// How many minutes between publishes? 10+ recommended for long-time continuous publishing!
int delayMinutes = 1;

// Creating an AssetTracker named 't' for us to reference
AssetTracker t = AssetTracker();

// A FuelGauge named 'fuel' for checking on the battery state
FuelGauge fuel;

// setup() and loop() are both required. setup() runs once when the device starts
// and is used for registering functions and variables and initializing things
void setup() {
    // Sets up all the necessary AssetTracker bits
    myservo.attach(D0);
    t.begin();
    
    // Enable the GPS module. Defaults to off to save power. 
    // Takes 1.5s or so because of delays.
    t.gpsOn();
    
    // Opens up a Serial port so you can listen over USB
    Serial.begin(9600);
    
    // These three functions are useful for remote diagnostics. Read more below.
    Particle.function("sa", servoToAngle);
    Particle.function("tmode", transmitMode);
    Particle.function("batt", batteryStatus);
    Particle.function("gps", gpsPublish);
    
}

// loop() runs continuously
void loop() {
    // You'll need to run this every loop to capture the GPS output

    t.updateGPS();

    // if the current time - the last time we published is greater than your set delay...
    if(millis()-lastPublish > delayMinutes*60*1000){
        // Remember when we published
        lastPublish = millis();
        
        //String pubAccel = String::format("%d,%d,%d",t.readX(),t.readY(),t.readZ());
        //Serial.println(pubAccel);
        //Particle.publish("A", pubAccel, 60, PRIVATE);
        
        // Dumps the full NMEA sentence to serial in case you're curious
        Serial.println(t.preNMEA());
        
        // GPS requires a "fix" on the satellites to give good data,
        // so we should only publish data if there's a fix
        if(t.gpsFix()){
            lat = t.readLat();
            lon = t.readLon();
            alt = t.getAltitude();
            // Only publish if we're in transmittingData mode 1;
            if(transmittingData){
                // Short publish names save data!
                Particle.publish("G", t.readLatLon(), 60, PRIVATE);
                Serial.println("lat=");
                Serial.println(lat);
                Serial.println("lon=");
                Serial.println(lon);
                Serial.println("alt=");
                Serial.println(alt);
            }
            // but always report the data over serial for local development
            Serial.println(t.readLatLon());
            
        }
    }
}

// Allows you to remotely change whether a device is publishing to the cloud
// or is only reporting data over Serial. Saves data when using only Serial!
// Change the default at the top of the code.
int transmitMode(String command){
    transmittingData = atoi(command);
    return 1;
}

int servoToAngle(String command){
    angle = command.toInt();
    //myservo.attach(D0);
    myservo.write(angle);
    //myservo.detach();
    //analogWrite(D1, angle);
    return angle;
}

String latLonAlt = "";

// Actively ask for a GPS reading if you're impatient. Only publishes if there's
// a GPS fix, otherwise returns '0'
int gpsPublish(String command){
    if(t.gpsFix()){ 
        //latLonAlt = t.readLatLon() + " " + t.getAltitude();
        latLonAlt = t.readLatLon();
        Particle.publish("G", latLonAlt, 60, PRIVATE);
                Serial.println("lat=");
                Serial.println(lat);
                Serial.println("lon=");
                Serial.println(lon);
                Serial.println("alt=");
                Serial.println(alt);
        
        
        // uncomment next line if you want a manual publish to reset delay counter
        // lastPublish = millis();
        return 1;
    }
    else { return 0; }
}

// Lets you remotely check the battery status by calling the function "batt"
// Triggers a publish with the info (so subscribe or watch the dashboard)
// and also returns a '1' if there's >10% battery left and a '0' if below
int batteryStatus(String command){
    // Publish the battery voltage and percentage of battery remaining
    // if you want to be really efficient, just report one of these
    // the String::format("%f.2") part gives us a string to publish,
    // but with only 2 decimal points to save space
    Particle.publish("B", 
          "v:" + String::format("%.2f",fuel.getVCell()) + 
          ",c:" + String::format("%.2f",fuel.getSoC()),
          60, PRIVATE
    );
    // if there's more than 10% of the battery left, then return 1
    if(fuel.getSoC()>10){ return 1;} 
    // if you're running out of battery, return 0
    else { return 0;}
}

If you want to keep the Asset Tracker from sending GPS data don’t pull D6 low.
But if you use an alternative serial interface (the Electron has two more at your disposition) you can use both GPS modules in parallel.

Yes, but the default code above would have it pull GPS from the Asset shield. What do I have to change for it to work using the external GPS?

How about not calling t.gpsOn()?

This is what that function does

void AssetTracker::gpsOn() {
    // Power to the GPS is controlled by a FET connected to D6
    pinMode(D6,OUTPUT);
    digitalWrite(D6,LOW);
    gps.begin(9600);
    gps.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
    delay(500);
    // Default is 1 Hz update rate
    gps.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
    delay(500);
    gps.sendCommand(PGCMD_NOANTENNA);
    delay(500);
    //for ublox maxm8 gps only
    //internal antenna selected as default
    for(uint8_t i=0;i<12;i++)
    {
        Serial1.write(internalANT[i]);
    }
    delay(500);
}

And this is what I said

But since you won’t be using the stock GPS module, why do you use the Asset Tracker shield and library at all?

Aaam, it was the first library that got it to work :slight_smile:

I can try the others again now that the darn thing started working.

1 Like

Hi there, me again :frowning:

So, I did not call t.gpsOn(), but i’m not getting any GPS data.

The example with calling Serial1 works, but I cant seem to get any GPS data from the Asset shield from the external GPS.

Here’s my code updated:

// This #include statement was automatically added by the Particle IDE.
#include <AssetTracker.h>

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

/* -----------------------------------------------------------
This example shows a lot of different features. As configured here
it'll check for a good GPS fix every 10 minutes and publish that data
if there is one. If not, it'll save you data by staying quiet. It also
registers 3 Particle.functions for changing whether it publishes,
reading the battery level, and manually requesting a GPS reading.
---------------------------------------------------------------*/

// Getting the library

// Set whether you want the device to publish data to the internet by default here.
// 1 will Particle.publish AND Serial.print, 0 will just Serial.print
// Extremely useful for saving data while developing close enough to have a cable plugged in.
// You can also change this remotely using the Particle.function "tmode" defined in setup()
int transmittingData = 1;
int angle = 1;
Servo myservo;
int pos = 0;
float lat, lon, alt;

// Used to keep track of the last time we published data
long lastPublish = 0;

// How many minutes between publishes? 10+ recommended for long-time continuous publishing!
int delayMinutes = 1;

// Creating an AssetTracker named 't' for us to reference
AssetTracker t = AssetTracker();

// A FuelGauge named 'fuel' for checking on the battery state
FuelGauge fuel;

// setup() and loop() are both required. setup() runs once when the device starts
// and is used for registering functions and variables and initializing things
void setup() {
    // Sets up all the necessary AssetTracker bits
    myservo.attach(D0);
    t.begin();
    
    // Enable the GPS module. Defaults to off to save power. 
    // Takes 1.5s or so because of delays.
    //t.gpsOn();
    
    // Opens up a Serial port so you can listen over USB
    Serial1.begin(9600);
    
    // These three functions are useful for remote diagnostics. Read more below.
    Particle.function("sa", servoToAngle);
    Particle.function("tmode", transmitMode);
    Particle.function("batt", batteryStatus);
    Particle.function("gps", gpsPublish);
    
}

// loop() runs continuously
void loop() {
    // You'll need to run this every loop to capture the GPS output

    t.updateGPS();

    // if the current time - the last time we published is greater than your set delay...
    if(millis()-lastPublish > delayMinutes*60*1000){
        // Remember when we published
        lastPublish = millis();
        
        //String pubAccel = String::format("%d,%d,%d",t.readX(),t.readY(),t.readZ());
        //Serial.println(pubAccel);
        //Particle.publish("A", pubAccel, 60, PRIVATE);
        
        // Dumps the full NMEA sentence to serial in case you're curious
        Serial.println(t.preNMEA());
        
        // GPS requires a "fix" on the satellites to give good data,
        // so we should only publish data if there's a fix
        if(t.gpsFix()){
            lat = t.readLat();
            lon = t.readLon();
            alt = t.getAltitude();
            // Only publish if we're in transmittingData mode 1;
            if(transmittingData){
                // Short publish names save data!
                Particle.publish("G", t.readLatLon(), 60, PRIVATE);
                Serial.println("lat=");
                Serial.println(lat);
                Serial.println("lon=");
                Serial.println(lon);
                Serial.println("alt=");
                Serial.println(alt);
            }
            // but always report the data over serial for local development
            Serial.println(t.readLatLon());
            
        }
    }
}

// Allows you to remotely change whether a device is publishing to the cloud
// or is only reporting data over Serial. Saves data when using only Serial!
// Change the default at the top of the code.
int transmitMode(String command){
    transmittingData = atoi(command);
    return 1;
}

int servoToAngle(String command){
    angle = command.toInt();
    //myservo.attach(D0);
    myservo.write(angle);
    //myservo.detach();
    //analogWrite(D1, angle);
    return angle;
}

String latLonAlt = "";

// Actively ask for a GPS reading if you're impatient. Only publishes if there's
// a GPS fix, otherwise returns '0'
int gpsPublish(String command){
    if(t.gpsFix()){ 
        //latLonAlt = t.readLatLon() + " " + t.getAltitude();
        latLonAlt = t.readLatLon();
        Particle.publish("G", latLonAlt, 60, PRIVATE);
                Serial.println("lat=");
                Serial.println(lat);
                Serial.println("lon=");
                Serial.println(lon);
                Serial.println("alt=");
                Serial.println(alt);
        
        
        // uncomment next line if you want a manual publish to reset delay counter
        // lastPublish = millis();
        return 1;
    }
    else { return 0; }
}

// Lets you remotely check the battery status by calling the function "batt"
// Triggers a publish with the info (so subscribe or watch the dashboard)
// and also returns a '1' if there's >10% battery left and a '0' if below
int batteryStatus(String command){
    // Publish the battery voltage and percentage of battery remaining
    // if you want to be really efficient, just report one of these
    // the String::format("%f.2") part gives us a string to publish,
    // but with only 2 decimal points to save space
    Particle.publish("B", 
          "v:" + String::format("%.2f",fuel.getVCell()) + 
          ",c:" + String::format("%.2f",fuel.getSoC()),
          60, PRIVATE
    );
    // if there's more than 10% of the battery left, then return 1
    if(fuel.getSoC()>10){ return 1;} 
    // if you're running out of battery, return 0
    else { return 0;}
}

Also tried the following code, no luck there…

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

// Copyright © 2016-2017 Daniel Porrey. All Rights Reserved.
//
// This file is part of the Particle.GPS library.
// 
// Particle.GPS library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Particle.GPS library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Particle.GPS library. If not, 
// see http://www.gnu.org/licenses/.
//

// ***
// *** 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.
  // ***
  Serial1.begin(9600);
  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.println("2) Global Positioning System Fixed Data ($GPGGA)");
    Serial.println("======================================================");
    Serial.print("UTC Time: "); Serial.println(gga.utcTime);
    Serial.print("Latitude: "); Serial.println(gga.latitude);
    Particle.publish("Lat=", gga.latitude);
    Particle.publish("Lon=", gga.longitude);
    Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
    Serial.print("Longitude: "); Serial.println(gga.longitude);
    Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
    Serial.print("Position Fix Indicator: "); Serial.println(gga.positionFixIndicator);
    Serial.print("Satellites Used: "); Serial.println(gga.satellitesUsed);
    Serial.print("Horizontal Dilution of Precision: "); Serial.println(gga.hdop);
    Serial.print("Altitude: "); Serial.prinhttps://www.faceplusplus.com/t(gga.altitude); Serial.print(" "); Serial.println(gga.altitudeUnit);
    Serial.print("Geoidal Separation: "); Serial.print(gga.geoidalSeparation); Serial.print(" "); Serial.println(gga.geoidalSeparationUnit);
    Serial.print("Age of Diff. Corr.: "); Serial.println(gga.ageOfDiffCorr);
    Serial.println("");
  }

  // ***
  // *** 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);
    Serial.print("Speed Over Ground: "); Serial.println(rmc.speedOverGround);
    Serial.print("Course Over Ground: "); Serial.println(rmc.courseOverGround);
    Serial.print("Date: "); Serial.println(rmc.date);
    Serial.print("Magnetic Variation: "); Serial.print(rmc.magneticVariation); Serial.print(" "); Serial.println(rmc.magneticVariationDirection);
    Serial.print("Mode: "); Serial.println(rmc.mode);
    Serial.println("");
  }

  delay(1000);
}

I quoted the original code of gpsOn()above to show what is done for the onboard module. I guess all of that needs to be done for the external module too, except the pulling D6 low which enables the onboard module.

So, in layman’s terms, copy the code from the gps on function in to setup, and comment the D6 low line?

Something along that line, yes.

Technically no, seems i’ll have to recompile the .h file too with the modified code. Looks like a fun Saturday, learning Arduino code and cursing when it fails :slight_smile:

I’ll let you know if I get stuck…

Ok, ping…

I tried downloading the libraries individually, but it just keeps including one file to another, etc.

Is there a way I can download the ino file and the libraries associated so I can do a local compile?

Hello?