Sketch breaks when I try to recieve GPS data

Hey, the project I'm currently working on should log GPS data using the neo 6 and acceleration data using the MPU6050 to an SD card. The problem is that I cannot find a spot in the code to receive GPS data. I am using the tinygps++ library, and wherever I place this code:

while(serial_connection.available())
  {
   gps.encode(serial_connection.read());
    
  }

the program breaks on me and nothing gets logged when the Arduino restarts, then only a new file is created and not even the CSV titles get written. If I let it out, the Arduino logs the acceleration perfect and created files it logs to after restart but obviously I don't get GPS data.
The csv file then looks like this:
deltaMillis, x, y, z, GPS data
28.91 0.09 -0.01 0.97
28.95 0.09 -0.01 0.97
28.98 0.09 -0.00 0.96 0 0.000000 0.000000 0.00 0.00 0.00 0
29.01 0.10 -0.00 0.97
29.05 0.10 -0.00 0.97

And if I only place
gps.encode(serial_connection.read()); The program also breaks.

Here is the full code without the code above.

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "TinyGPS++.h"
#include "SoftwareSerial.h"

const int frequency1 = 10;//MPU6050 frequency
const int frequency2 = 750;//GPS frequency
unsigned long timer1 = 0;
unsigned long timer2 = 0;

long accelX, accelY, accelZ;
float gForceX, gForceY, gForceZ;

float deltaTime;

int RXPin = 3;
int TXPin = 2;

String fileName = "data";
int count = 0;
bool file = false;


SoftwareSerial serial_connection(3, 2);
TinyGPSPlus gps;
File dataFile;

void setup() {

  Serial.begin(9600);
  serial_connection.begin(9600);//This opens up communications to the GPS
  Wire.begin();
  setupMPU();

//initialization of SD-card
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
//checks if the file already exists, else creates a new one with a new name
  while(!file){
    if(SD.exists(fileName + ".csv")){
      count++;
      fileName = "data" + String(count);
    }else{
      file = true;
    }
  }
//titles(); = csv titles
  titles();
  Serial.println("GOGO");
  delay(50);
  deltaTime = millis();//time in csv

  
}

void loop() {
//logs acceleration  
  if(millis() >= (timer1 + frequency1)) {
    recordAccelRegisters();
    dataFile = SD.open((fileName + ".csv"), FILE_WRITE);
    if(dataFile){
      dataFile.print((millis()-deltaTime)/1000);
      dataFile.print(",");
      dataFile.print(gForceX);
      dataFile.print(",");
      dataFile.print(gForceY);
      dataFile.print(",");
      dataFile.println(gForceZ);
      dataFile.close();  
      }else{    
        Serial.println("Does not log data!");
       }
    
    Serial.print(" Accel (g)");
    Serial.print(" X=");
    Serial.print(gForceX);
    Serial.print(" Y=");
    Serial.print(gForceY);
    Serial.print(" Z=");
    Serial.println(gForceZ);
    Serial.print("");
    timer1 = millis();
  }
  //logs GPS
  if(millis() >= timer2 + frequency2){    
    recordAccelRegisters();
    dataFile = SD.open((fileName + ".csv"), FILE_WRITE);
    if(dataFile){
      dataFile.print((millis()-deltaTime)/1000);
      dataFile.print(",");
      dataFile.print(gForceX);
      dataFile.print(",");
      dataFile.print(gForceY);
      dataFile.print(",");
      dataFile.print(gForceZ);
      dataFile.print(",");  
      dataFile.print(gps.time.value());
      dataFile.print(",");
      dataFile.print(gps.location.lat(), 6);
      dataFile.print(",");
      dataFile.print(gps.location.lng(), 6);
      dataFile.print(",");
      dataFile.print(gps.speed.mps());
      dataFile.print(",");
      dataFile.print(gps.speed.kmph());
      dataFile.print(",");
      dataFile.print(gps.altitude.meters());
      dataFile.print(",");
      dataFile.println(gps.satellites.value());
      dataFile.close();
      }else{   
        Serial.println("No GPS");
    }    
    Serial.print(gps.time.value());
    Serial.print(",");
    Serial.print(gps.location.lat(), 6);
    Serial.print(",");
    Serial.print(gps.location.lng(), 6);
    Serial.print(",");
    Serial.print(gps.speed.mps());
    Serial.print(",");
    Serial.print(gps.speed.kmph());
    Serial.print(",");
    Serial.print(gps.altitude.meters());
    Serial.print(",");
    Serial.println(gps.satellites.value());       

    timer2 = millis();
 }

}

void titles(){
  
  dataFile = SD.open((fileName + ".csv"), FILE_WRITE);
  if(dataFile){
    dataFile.print("time");
    dataFile.print(",");
    dataFile.print("x");
    dataFile.print(",");
    dataFile.print("y");
    dataFile.print(",");
    dataFile.print("z");
    dataFile.print(",");
    dataFile.print("GPS_time");
    dataFile.print(",");
    dataFile.print("Latitude");
    dataFile.print(",");
    dataFile.print("Longitude");
    dataFile.print(",");
    dataFile.print("m/s");
    dataFile.print(",");
    dataFile.print("km/h");
    dataFile.print(",");
    dataFile.print("altitude (m)");
    dataFile.print(",");
    dataFile.println("satellites");
    dataFile.close();
  }else{
    Serial.println("error opening sd card");
  }
}

void setupMPU(){
  Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
  Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
  Wire.write(0b00000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
  Wire.endTransmission();  
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4) 
  Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s 
  Wire.endTransmission(); 
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5) 
  Wire.write(0b00000000); //Setting the accel to +/- 2g
  Wire.endTransmission(); 
}

void recordAccelRegisters() {
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x3B); //Starting register for Accel Readings
  Wire.endTransmission();
  Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
  while(Wire.available() < 6);
  accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
  accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
  accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
  processAccelData();
}

void processAccelData(){
  gForceX = accelX / 16384.0;
  gForceY = accelY / 16384.0; 
  gForceZ = accelZ / 16384.0;
}

Thanks in advance :slight_smile:

Have you tried the example sketches that come with the TinyGPS++ library? Do they work? You should get it working by itself before you try to incorporate it into another sketch.

Also, the way you are tracking elapsed time will eventually bite you

  if(millis() >= (timer1 + frequency1)) {
  ...

The only safe way to perform unsigned math involving millis() is subtraction

  if(millis() - timer1 >= frequency1) {
  ...

Thank you for your reply, yes the tinygps++ example sketches work. I will try your recommended millis() tracking. Any suggestions were in the code I can update the GPS data?

Its just possible its related to the Arduino and hardware you are using.

Litiumtitan:
Thank you for your reply, yes the tinygps++ example sketches work. I will try your recommended millis() tracking. Any suggestions were in the code I can update the GPS data?

If the examples work, I'd start with that sketch and begin adding in your code for the rest of the project. Add some functionality, test, repeat until you succeed or things break.

I would look at the following things.

1.) Do not open and close files multiple times a second. Open one file and write to it. Only close it with a specific event. e.g. stop recording button, enough number of samples taken.

2.) Use if(serial_connection.available()). Try to make your loop run as often as possible. Only doing things that are necessary and one step at a time. This will allow you to interleave slow and fast tasks easier. Avoid while loops if possible, you do not know how long something will take.

3.) Try to find a way to figure out how long things take. Sometimes there are long timeouts in functions breaking your software when you combine it with other functions. If you have an oscilloscope just toggle a pin around functions. You can also use timers to measure functions. Whatever is easiest for you.

I am grateful for all the responses, and I will test them today, but one thing I did not clarify is that when I use this code:

void loop() {

while(serial_connection.available())
  {
   gps.encode(serial_connection.read());
   
  }

//logs acceleration 
  if(millis() >= (timer1 + frequency1)) {
    recordAccelRegisters();
    dataFile = SD.open((fileName + ".csv"), FILE_WRITE);
    if(dataFile){
      dataFile.print((millis()-deltaTime)/1000);
      dataFile.print(",");

The code works perfectly fine for the first csv it creates, logs acceleration and GPS. In my case this is data.csv. But if I hit restart on the Arduino a new file is created data2.csv, but nothing gets logged to it. Why does it only log to the first file it creates?
Edit:
tried
if(serial_connection.available())
{
gps.encode(serial_connection.read());

}
instead, and it also just works in the first file.

When you hit restart on your Arduino, you do a reset of the Arduino only. The SD card only gets restarted when you do a power cycle. Maybe your SD card is not happy, you doing all the file open/close stuff and then just hitting reset. Consumer products usually tell you to not switch power off when the memory card access LED is blinking. They probably know memory cards are sensitive little cheap buggers:)