0

Feather M0 Logger with Ultimate GPS and LSM9DS1
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Feather M0 Logger with Ultimate GPS and LSM9DS1

by kioblewe on Thu Sep 23, 2021 12:53 pm

Hi,
I started to built a data logger for GPS and acceleration with the Feather M0 Adalogger, the UltimateGPS Breakout V3 and the LSM9DS1. I followed the adafruit tutorials and combined the example code from the libraries (see below in code). When logging only GPS OR acceleration readings everything works fine. However, when combining both in in one loop the GPS reading becomes useless. When printing last NMEA to the serial the sentences are broken.

Wiring: GPS on RX and TX, LSM9DS1 on SDA and SCL. The wiring and the soldering should be fine as everything works as expected when using only the UltimateGPS or the Accelerometer alone

I'm new to all coding and the arduino world, so any help is highly appreciated!! Thanks in advance.
.

Code: Select all | TOGGLE FULL SIZE
#include <SD.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GPS.h>

#include <Adafruit_LSM9DS1.h>
#include <Adafruit_Sensor.h>  // not used in this demo but required!

const int chipSelect = 4;
#define GPSSerial Serial1
Adafruit_GPS GPS(&GPSSerial);
#define GPSECHO false
uint32_t timer = millis();
uint32_t timer2 = millis();

// i2c
Adafruit_LSM9DS1 lsm = Adafruit_LSM9DS1();

#define LSM9DS1_SCK A5
#define LSM9DS1_MISO 12
#define LSM9DS1_MOSI A4
#define LSM9DS1_XGCS 6
#define LSM9DS1_MCS 5


void setupSensor()
{
  // 1.) Set the accelerometer range
  lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_2G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_4G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_8G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_16G);
 
  // 2.) Set the magnetometer sensitivity
  lsm.setupMag(lsm.LSM9DS1_MAGGAIN_4GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_8GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_12GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_16GAUSS);

  // 3.) Setup the gyroscope
  lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_245DPS);
  //lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_500DPS);
  //lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_2000DPS);
}


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

  Serial.print("Initializing SD card...");
 if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
{
  Serial.begin(115200);
   // 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);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  delay(1000);

  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);

  while (!Serial) {
    delay(1); // will pause Zero, Leonardo, etc until serial console opens
  }
 
  Serial.println("LSM9DS1 data read demo");
 
  // Try to initialise and warn if we couldn't detect the chip
  if (!lsm.begin())
  {
    Serial.println("Oops ... unable to initialize the LSM9DS1. Check your wiring!");
    while (1);
  }
  Serial.println("Found LSM9DS1 9DOF");

  // helper to just set the default scaling we want, see above!
  setupSensor();
}
}
void loop() //write readings of both sensores on SD card in two seperate files
{
 
  motion();
    location();


}
 

void location()
{
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  // 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 trying to print out data
    Serial.print(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 ( timer > millis () ) timer = millis () ;
   if (millis() - timer > 10000) {
    timer = millis(); // reset the timer
   
timer2=millis();//timer2 needed to merge data of accel. to real time of GPS postprocessing
  File dataFile = SD.open("location.txt", FILE_WRITE);
 if (dataFile) {
 //time and date
 dataFile.print(timer2);
 dataFile.print(',');
 dataFile.print(GPS.day,DEC);dataFile.print('/');
  dataFile.print(GPS.month,DEC);dataFile.print('/');
  dataFile.print(GPS.year,DEC);
  dataFile.print(',');
   if (GPS.hour<10) {dataFile.print('0') ;}
  dataFile.print(GPS.hour, DEC);
  dataFile.print(':');
   if (GPS.minute<10) {dataFile.print('0') ;}
  dataFile.print(GPS.minute,DEC);
  dataFile.print(':');
   if (GPS.seconds<10) {dataFile.print('0') ;}
  dataFile.print(GPS.seconds,DEC);
   dataFile.print('.');
   if (GPS.milliseconds<10) {dataFile.print('00') ;}
   else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
      dataFile.print("0");
    }
    dataFile.print(GPS.milliseconds);

  dataFile.print(',');
 //location
  if (GPS.fix){
     dataFile.print(GPS.latitude,4);dataFile.print(GPS.lat);dataFile.print(',');
     dataFile.print(GPS.longitude,4);dataFile.print(GPS.lon);dataFile.print(',');
     dataFile.print(GPS.speed);dataFile.print(',');
     dataFile.print(GPS.angle);dataFile.print(',');
     dataFile.print(GPS.altitude);dataFile.print(',');
     dataFile.println((int)GPS.satellites);
   
    dataFile.close();
  }
  else{
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.println("NA");
     
     dataFile.close();
  }
  }
 
 
 else {
    Serial.println("error opening datalog");
    delay (1000) ;
return ;
  }
   }
}
void motion()
{
  lsm.read();  /* ask it to read in the data */

  /* Get a new sensor event */
  sensors_event_t a, m, g, temp;

  lsm.getEvent(&a, &m, &g, &temp);
  timer2=millis();//timer2 needed to merge data of accel. to real time of GPS postprocessing
File dataFile = SD.open("ACCLOG.txt", FILE_WRITE);
if (dataFile){
dataFile.print(timer2);
 dataFile.print(',');
   dataFile.print(a.acceleration.x);dataFile.print(',');dataFile.print(a.acceleration.y);dataFile.print(',');dataFile.print(a.acceleration.z);dataFile.print(',');
    dataFile.print(m.magnetic.x);dataFile.print(',');dataFile.print(m.magnetic.y);dataFile.print(',');dataFile.print(m.magnetic.z);dataFile.print(',');
    dataFile.print(g.gyro.x);dataFile.print(',');dataFile.print(g.gyro.y);dataFile.print(',');dataFile.println(g.gyro.z);
   
  dataFile.close();
  delay(200);
  }

else {
   Serial.println("error opening acclog");
    delay (1000) ;
return ;
}
}

kioblewe
 
Posts: 4
Joined: Thu Sep 23, 2021 12:25 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by mikeysklar on Fri Sep 24, 2021 6:57 pm

@kioblewe,

I scrolled the code and my first thought is that timer2 might need an adjustment for how long it is waiting for both devices to report in.

You could remove the timer logic and start with manual delays initially to reduce the complexity.

mikeysklar
 
Posts: 5873
Joined: Mon Aug 01, 2016 8:10 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by kioblewe on Sat Sep 25, 2021 10:43 am

Hi,
thank you for your reply. I did remove the timers and used delay() instead, without success. The NMEA sentences printed to the serial still don't make any sense. A example of the serial output is below. The last line stops the functionality of the GPS, at least I can not see any more output on the serial or written to the SD card.
Code: Select all | TOGGLE FULL SIZE
16:29:48.627 -> $PMTK001,314,3*36
16:29:52.994 -> $PMTK001,220,3*30
16:29:56.727 -> $PGACK,33,1*6F
16:30:00.394 -> $PGTOP,11,2*6E
16:30:09.594 -> $GPGGA,235943.800,,,,,0,00,,,M,,M,,*7A
16:30:20.894 -> $GPRMC,235943.800,V,,,,,0.00,0.00,050180,,,N*43
16:30:32.394 -> $PMTK705,AXN_2.31_3339_13101700,5632,PA6H,1.0*6B
16:30:36.060 -> $PGTOP,11,2*6E
16:30:45.294 -> $GPGGA,235944.799,,,,,0,00,,,M,,M,,*72
16:30:56.560 -> $GPRMC,235944.799,V,,,,,0.00,0.00,050180,,,N*4B
16:31:00.227 -> $PGTOP,11,2*6E
16:31:57.554 -> $GPGGA,235945.799,,$PG$PGTV$PGT$PGT$PGT3$PGT$PGT$PGT0$PGT$PGT$$PGTM$PG.$PGT$PGT0$PG,$PGT$$PGT2$PG1$PGT$PGT8$PG$$PG$PGT1

For the last few lines the FIX LED of the GPS Board indicated fix.

kioblewe
 
Posts: 4
Joined: Thu Sep 23, 2021 12:25 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by kioblewe on Sat Sep 25, 2021 12:10 pm

Another thing: Even if the motion() function which is supposed to write the accelerometer data on SD only writes a string the GPS shows the same problems. Vice versa, if motion() only reads and prints the accelerometer data to the serial, same problem...

kioblewe
 
Posts: 4
Joined: Thu Sep 23, 2021 12:25 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by mikeysklar on Mon Sep 27, 2021 11:50 am

Since the GPS and accelerometer work well independently writing to the console or SD card let's try using just the GPS and commenting out all the accelerometer. Verify that still works as expected. Then line by line re-enable the accelerometer. First just the lsm i2c initializer then lines of the motion() function. Maybe this will help narrow down where the conflict is occurring.

Go ahead and post some photos of your wiring and soldering just to confirm all that looks good. I don't think that will be an issue.

mikeysklar
 
Posts: 5873
Joined: Mon Aug 01, 2016 8:10 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by kioblewe on Tue Oct 05, 2021 3:13 am

Hi,
not opening the data file at higher rates than 1Hz solves the problem. Additionally, using delay() in the loop seems to disturb the parsing the of the GPS sentences. So, for now the solution is:
1. set the frequency of lsm9 readings with a timer not with delay()
2. "collecting" the lsm9 readings in a variable with String(), which creates a paragraph
3. open the datafile at 1Hz rate than print the paragraph and the GPS data to the File on the SD card

Definitely room to improve the code, but it works for now
Thank you for your help

Code: Select all | TOGGLE FULL SIZE
#include <SD.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GPS.h>

#include <Adafruit_LSM9DS1.h>
#include <Adafruit_Sensor.h>  // not used in this demo but required!

const int chipSelect = 4;
#define GPSSerial Serial1
Adafruit_GPS GPS(&GPSSerial);
#define GPSECHO false
uint32_t timer = millis();//for writing data on SD card
uint32_t timer2 = millis();//for timestamping accelerometer data
uint32_t timer3 = millis();//for writing accelerometer data to paragraph string
String parag;
// i2c
Adafruit_LSM9DS1 lsm = Adafruit_LSM9DS1();

#define LSM9DS1_SCK A5
#define LSM9DS1_MISO 12
#define LSM9DS1_MOSI A4
#define LSM9DS1_XGCS 6
#define LSM9DS1_MCS 5


void setupSensor()
{
  // 1.) Set the accelerometer range
  lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_2G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_4G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_8G);
  //lsm.setupAccel(lsm.LSM9DS1_ACCELRANGE_16G);
 
  // 2.) Set the magnetometer sensitivity
  lsm.setupMag(lsm.LSM9DS1_MAGGAIN_4GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_8GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_12GAUSS);
  //lsm.setupMag(lsm.LSM9DS1_MAGGAIN_16GAUSS);

  // 3.) Setup the gyroscope
  lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_245DPS);
  //lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_500DPS);
  //lsm.setupGyro(lsm.LSM9DS1_GYROSCALE_2000DPS);
}


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

  Serial.print("Initializing SD card...");
 if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
{
  Serial.begin(115200);
   // 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);
  // uncomment this line to turn on only the "minimum recommended" data
 GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  delay(1000);

  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);

  while (!Serial) {
    delay(1); // will pause Zero, Leonardo, etc until serial console opens
  }
 
  Serial.println("LSM9DS1 data read demo");
 
  // Try to initialise and warn if we couldn't detect the chip
  if (!lsm.begin())
  {
    Serial.println("Oops ... unable to initialize the LSM9DS1. Check your wiring!");
    while (1);
  }
  Serial.println("Found LSM9DS1 9DOF");

  // helper to just set the default scaling we want, see above!
  setupSensor();
}
}

void loop()
{
 char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  // 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 trying to print out data
    Serial.print(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
  }

 
 
lsm.read();  /* ask it to read in the data */

  /* Get a new sensor event */
sensors_event_t a, m, g, temp;

 lsm.getEvent(&a, &m, &g, &temp);
//readcounter=readcounter + 1;
timer2=millis();//timer2 to merge data of accel. to real time of GPS
 
  parag;
if ( timer3 > millis () ) timer3 = millis () ;
 if (millis() - timer3 > 200) { //about 5 Hz reading frequ
   timer3 = millis () ;
 parag=String(parag + '\n' +a.acceleration.x+',' + a.acceleration.y +',' + a.acceleration.z + ','+g.gyro.x+','+g.gyro.y+','+g.gyro.z+','+timer2);//+','+m.magnetic.x+','+m.magnetic.y+','+m.magnetic.z+','+timer2);
 
 
 }


 

 
 


if ( timer > millis () ) timer = millis () ;
 if (millis() - timer > 1000) {
timer = millis(); // reset the timer

     
//timer2=millis();//timer2 to merge data of accel. to real time of GPS
  File dataFile = SD.open("log.txt", FILE_WRITE);
 if (dataFile) {
 //time and date
// dataFile.print(timer2);
// dataFile.print(',');
dataFile.print(parag);dataFile.print(',');
 dataFile.print(GPS.day,DEC);dataFile.print('/');
  dataFile.print(GPS.month,DEC);dataFile.print('/');
  dataFile.print(GPS.year,DEC);
  dataFile.print(',');
   if (GPS.hour<10) {dataFile.print('0') ;}
  dataFile.print(GPS.hour, DEC);
  dataFile.print(':');
   if (GPS.minute<10) {dataFile.print('0') ;}
  dataFile.print(GPS.minute,DEC);
  dataFile.print(':');
   if (GPS.seconds<10) {dataFile.print('0') ;}
  dataFile.print(GPS.seconds,DEC);
   dataFile.print('.');
   if (GPS.milliseconds<10) {dataFile.print('00') ;}
   else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
      dataFile.print("0");
    }
    dataFile.print(GPS.milliseconds);

  dataFile.print(',');
 //location
  if (GPS.fix){
     dataFile.print(GPS.latitude,4);dataFile.print(GPS.lat);dataFile.print(',');
     dataFile.print(GPS.longitude,4);dataFile.print(GPS.lon);dataFile.print(',');
     dataFile.print(GPS.speed);dataFile.print(',');
     dataFile.print(GPS.angle);dataFile.print(',');
     dataFile.print(GPS.altitude);dataFile.print(',');
     dataFile.println((int)GPS.satellites);
   
    dataFile.close();
    parag=String();//clear the collect paragraph
     
  }
  else{
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.print("NA,");
     dataFile.println("NA");
     
     dataFile.close();
     parag=String();
     
  }
  }
 

 else {
    Serial.println("error opening datalog");
    delay (1000) ;
return ;
  }
   }
}

kioblewe
 
Posts: 4
Joined: Thu Sep 23, 2021 12:25 pm

Re: Feather M0 Logger with Ultimate GPS and LSM9DS1

by mikeysklar on Tue Oct 05, 2021 3:29 pm

Thank you for sharing your solution. The slower file access and lsm9 frequency + bulk readings seemed to have resolved it for you. Appreciate you providing the working code.

mikeysklar
 
Posts: 5873
Joined: Mon Aug 01, 2016 8:10 pm

Please be positive and constructive with your questions and comments.