Loop in code creates timing issues with GPS read

I am using a Feather M0 Adalogger connected to an ultimate GPS Featherwing, a BNO055 9 DOF sensor, and 2 external sensors on analog pins A0 and A1.

I am recording GPS data at 5Hz and the other sensor data at 20Hz, so the sensors are read/logged 4 times for each GPS read/log.

My code appears to work fine when written out as GPS+sensor read, followed by 3 more sensor-only reads. However, when I try and simplify to code to put the 3 extra sensor reads in a loop, the code starts missing GPS reads, generally 1 or 2 every couple of seconds.

I don’t understand why the loop would introduce this error, since it seems unlikely to take any longer than writing the sensor-read/log code three additional times.

Thanks. Code is below

 //5Hz GPS
//20Hz BNO and sensors
  

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
   
Adafruit_BNO055 bno = Adafruit_BNO055(55);

#include <SPI.h>
#include <SdFat.h>
#define CHIP_SELECT 4
#define LOG_FIXONLY false
SdFat SD;

File logfile; 

#include <NMEAGPS.h>

#define gpsPort Serial1
NMEAGPS gps;

 //f sensors on A0 and A1
int f0=A0;
int f1=A1;
int f0Value;
int f1Value;


void setup() {

  pinMode(f0,INPUT);
  pinMode(f1,INPUT);
  
  Serial.begin(115200);
  delay( 5000 );
  Serial.println( F("\r\nUltimate GPS featherwing with NeoGPS") ); 

  // make sure that the default chip select pin is set to output
  pinMode(4, OUTPUT);

    // see if the card is present and can be initialized:
  if (!SD.begin(CHIP_SELECT)) {   
    Serial.println( F("Card init. failed!") );
  }

  char filename[15] = "JTEST00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  } 

    logfile = SD.open(filename, FILE_WRITE);
  if( ! logfile.isOpen() ) {
    Serial.print( F("Couldnt create ") ); 
    Serial.println(filename);
  }

  Serial.print( F("Writing to ") ); 
  Serial.println(filename);

  //switch gps to 38400 baud if not already
  gpsPort.begin( 9600 );
  delay( 100 );
  gps.send_P( &gpsPort, F("PMTK251,38400") ); //baud 38400
  delay( 100 );
  gpsPort.flush();
  delay( 100 );
  gpsPort.end();
  
  gpsPort.begin( 38400 );
  delay( 100 );

  //GPS settings
  gps.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC_GGA
  delay( 100 );
  gps.send_P( &gpsPort, F("PMTK220,200") );  // 5Hz
  delay( 100 );
  gps.send_P( &gpsPort, F("PGCMD,33,0") );   // No antenna status messages needed
  delay( 100 );


  /* Initialise the sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
  
  delay(1000);
    
  bno.setExtCrystalUse(true);


 Serial.println("Ready!");
}


void loop() {

  // Parse GPS characters until a complete fix has been assembled.
  if (gps.available( gpsPort )) {
 
    // A complete fix structure is finally ready, get it.
    gps_fix fix = gps.read();

  for (uint8_t j = 0; j < 4; j++) {

    f0Value = analogRead(f0);
    f1Value = analogRead(f1);

      /* Get a new sensor event */ 
    sensors_event_t event; 
    bno.getEvent(&event);

    imu::Vector<3> sid = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);

    // Log it and serial print 
    Serial.println( F("Log") );


    logfile.print(fix.dateTime.hours); 
    logfile.print(':');
    logfile.print(fix.dateTime.minutes); 
    logfile.print(':');
    logfile.print(fix.dateTime.seconds); 
    logfile.print('.');
    if (fix.dateTime_cs < 10)
      logfile.print( '0' );
    logfile.print(fix.dateTime_cs);
    logfile.print(',');

    logfile.print(fix.dateTime.date); 
    logfile.print('/');
    logfile.print(fix.dateTime.month); 
    logfile.print(','); 
    logfile.print(fix.latitude(), 4);  
    logfile.print(',');        
    logfile.print(fix.longitude(), 4); 
    logfile.print(','); 
    logfile.print(fix.altitude() ); 
    logfile.print(',');  
    logfile.print(event.orientation.x, 4);
    logfile.print(','); 
    logfile.print(event.orientation.y, 4);
    logfile.print(',');
    logfile.print(fix.speed_mph() ); 
    logfile.print(',');
    logfile.print(sid.x());
    logfile.print(',');
    logfile.print(sid.y());
    logfile.print(',');
    logfile.print(f0Value);
    logfile.print(',');
    logfile.println(f1Value); 
    
    delay( 50 );
  }    

    logfile.flush();

  }

}

There's a lot of overhead when writing to an SD card. When you just did one logfile.print followed another three, it was probably okay. As soon as you start looping, it's going to trip on itself. The problem is that SD card writes are done in blocks, typically 256 words, regardless of whether it's one byte or 512. The overhead for each write is the same. The trick is to pack all the logfile.print statements into one buffer and print that at the end of each loop.