Assettracker Shield - Can it support GPS and Accelerometer at the same time

I am attempting to use the Asset Tracker shield and library to report the location of an object. Whenever I enable the GPS, the Accelerometer stops working, without the GPS enabled the Accelerometer works fine.

I have searched the forum and can find similar posts but around using the wake on movement function, I am not using that, I simply want to collect GPS and Accelerometer readings at the same time.

Below is the code I am using, it publishes:

Event: A - 0,0,0

If I remove the line t.gpsOn() it publishes accelerometers readings.

Thanks

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

long lastPublish = 0;
int delaySecondsActive = 15;
int delaySecondsNotActive = 30; //3600;

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

// 9000 is VERY sensitive, 12000 will still detect small bumps
int accelThreshold = 11000;

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

double mainBatteryVoltage;
double auxBatteryVoltage;
bool isolatorStatus;

String gpsLocation = "";
long gpsTime = 0;

void setup() {
    // Sets up all the necessary AssetTracker bits
    t.begin();
    
    // Enable the GPS module. Defaults to off to save power. 
    // Takes 1.5s or so because of delays.
    t.gpsOn();
    
    // These three functions are useful for remote diagnostics. Read more below.
    Particle.function("b", batteryStatus);
    Particle.function("f", hasGPSFix);
    Particle.function("t", accelThresholder);
    Particle.variable("l", gpsLocation);
}

// loop() runs continuously
void loop() {
    // You'll need to run this every loop to capture the GPS output
    //t.updateGPS();
    
    int publishDelaySeconds = 0;
    
    if(t.readXYZmagnitude() > accelThreshold){
        publishDelaySeconds = delaySecondsActive;
    }else{
        publishDelaySeconds = delaySecondsNotActive;
    }
    
    if(lastPublish == 0 || millis()-lastPublish > publishDelaySeconds*1000){
        //Let's publush
        lastPublish = millis();
        
        if(t.gpsFix()) {
            gpsLocation = t.readLatLon();
            gpsTime = millis();
        }
        
        mainBatteryVoltage = getMainBatteryVoltage();
        auxBatteryVoltage = getMainBatteryVoltage();
        isolatorStatus = getIsolatorStatus();
        
        Particle.publish("vs", statusData(), 60, PRIVATE);
        
        String pubAccel = String::format("%d,%d,%d",t.readX(),t.readY(),t.readZ());
        Particle.publish("A", pubAccel, 60, PRIVATE);
        Particle.publish("D", String::format("%d",publishDelaySeconds), 60, PRIVATE);
    }
}

String statusData() {
    
    //Start JSON
    String data = String("{ ");
            
    //GPS Location
    data.concat("\"1\": \"");
    data.concat(gpsLocation);
    data.concat("\"");
            
    //Main Battery
    data.concat(", \"2\": \"");
    data.concat(String::format("%.1f",mainBatteryVoltage));
    data.concat("\"");
            
    //Aux Battery
    data.concat(", \"3\": \"");
    data.concat(String::format("%.1f",auxBatteryVoltage));
    data.concat("\"");
            
    //GPS Time
    data.concat(", \"4\": \"");
    data.concat(String::format("%d",millis()-gpsTime));
    data.concat("\"");
             
    //Finish JSON
    data.concat("}");
    
    return data;
}

double getMainBatteryVoltage() {

    return 12.5;    

}

double getAuxBatteryVoltage() {
    
    return 13.4;

}

bool getIsolatorStatus() {
    
    return true;
    
}

int hasGPSFix(String command) {
    if(t.gpsFix()) {
        return 1;
    }else {
        return 0;
    }
}

// Remotely change the trigger threshold!
int accelThresholder(String command){
    accelThreshold = atoi(command);
    return 1;
}

// 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;}
}

Try the AssetTrackerRK library instead.

1 Like

Thanks, I will look into this library. Wondering if anyone can confirm if the Particle Library should support this or not, curious if I am doing something wrong.

I was having the same problem, found this post, and tried the AssetTrackerRK library as recommended, but am seeing the exact same issue even with the new library - the accelerometer works fine as long as the GPS is never turned on, but as soon as I include gpsOn(), the accelerometer output is stuck at one value and does not update. Please see my code below and let me know if I have forgotten to initialize something?

// This #include statement was automatically added by the Particle IDE.
#include <AssetTrackerRK.h>`
// Adding accelerometer data logging detection to the AssetTracker example code from https://www.hackster.io/jake644/car-finder-fba654

/* -----------------------------------------------------------
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.
---------------------------------------------------------------*/

// 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 = 0; // TODO: revert before outdoor test

// 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 = 10;

// Last accelerometer XYZ magnitude
int accelXYZmagnitude = 0;
int m_accelX = 0;
int m_accelY = 0;
int m_accelZ = 0;
char accelString[32]; /* At least big enough for 31 chars + null. */

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

// 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
    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);

}

// loop() runs continuously
void loop() {
    // You'll need to run this every loop to capture the GPS output
    //t.updateGPS(); // TODO: Should there be a delay on this?

    // Look for drop
    accelXYZmagnitude = t.readXYZmagnitude();
    m_accelX = t.readX();
    m_accelY = t.readY();
    m_accelZ = t.readZ();
    sprintf(accelString, "AccX %d AccY %d AccZ %d AccMag %d\n", m_accelX, m_accelY, m_accelZ, accelXYZmagnitude);

    // if the current time - the last time we published is greater than your set delay...
    if(millis()-lastPublish > 1000) { //delayMinutes*60*1000){ // TODO: revert this after testing

        Serial.println(accelString); 

        // Remember when we published
        lastPublish = millis();

    }
}

You can use both, you just need to perform the activation / initialization in a specific order:

Essentially, initialize the accelerometer after you’ve powered on the GPS and given it some time to settle.

This app uses both - https://github.com/dmiddlecamp/fancy-asset-tracker/tree/master/motion-tracker

Thanks,
David

1 Like

Thanks! Could you tell me where you pull the GPS_math.h library from? It isn’t available in the Particle community library search.

I’m also having trouble compiling - Web IDE keeps giving me a

fatal error: Adafruit_GPS.h: No such file or directory

I’ll keep trying to work around that too.

Hi @yoohsiu,

That file is here: https://github.com/dmiddlecamp/fancy-asset-tracker/blob/master/gps-library/GPS_Math.h

I don’t remember if I created that file or copied it from somewhere, but it has a function I’m using in my example. :slight_smile:

If you’re copying the project to the Online IDE, you might need to remove my include statements and use the automatically generated ones instead.

I hope that helps!

Thanks,
David

Since creating this I was able to get both GPS and Accelerometer to work at the same time using the Particle Asset Tracker Library.

I added in: SYSTEM_THREAD(ENABLED);

This causes my original code to work, however I am curious if anyone knows of if this is a good idea?

I am unable to find documentation for exactly what changes this makes.

Since my previous post i found details about changed the system thread - https://docs.particle.io/reference/firmware/photon/#system-thread

@Dave answer has actually solved it for me and the it’s as simple as changing the order I do the setup. As long as I call t.gpsOn(); before calling t.begin(); it works fine.

Thanks for the help.

3 Likes