Bizzare Bug

Im having trouble with my code, it seems to be executing a line of code it shouldnt and crashing, can anyone help explain it?

void loop(){
  //Use Screen Display so we only update the LCD every 1.5 Seconds
  ScreenDisplay++;
  GotSignal = checkGPS(); 
  if(GotSignal){
    //If we have a Signal read the GPS
    readGPS();
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since the screen updated
      //Reset the count, increase the ScreenChange Count and Display
      ScreenDisplay = 0;
      ScreenChange++;
      updateDisplay();
    }
    //Write to file here
    if (CardInit){
      lcd.setCursor(10,1);
      lcd.print("Ind"); 
      /*
      logfile = SD.open(filename, FILE_WRITE); 
      */
      logfile.println(GPSlat); logfile.print(",");
      logfile.print(GPSlon); logfile.print(",");
      logfile.close();
    }
  }else{
    //If We have no signal
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since screen refresh
      //Reset count increase the amount of dots and show animation
      ScreenDisplay = 0;
      DotCount++;
      showSearching();
    }
    //No need to write to file
  }
 //Pause half a second 
 delay(500); 
}

if you see the commented out line logfile = open, if i include that line the arduino crashes when it comes round to the loop, if i dont it runs fine, it is never going inside the if statement though as the lcd.print(ind) is not being executed.

Im seriously confused.

Without seeing ALL of your code, all we can offer is sympathy.

didn’t know if it would let me post it all

here you go:

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <Wire.h>
#include <SD.h>
#define chipSelect 10
#define powerpin 4
LiquidCrystal_I2C lcd(0x27,16,2); //set the LCD address to 0x27 for a 16 chars and 2 line display
File logfile;
TinyGPS gps;
SoftwareSerial nss(2, 7);
int ScreenDisplay,ScreenChange,DotCount;
boolean GotSignal,CardInit;
double GPSlat,GPSlon,GPSspeed,GPSalt,GPScour;
char GPStype[2];
int GPSday, GPSmonth, GPSyear, GPShour, GPSminute, GPSsecond, GPShund,GPSsat;
char filename[] = "GPSDAT00.CSV";

/*
Initial Setup of the program
*/

void setup() 
{
 //Initiate the LCD and turn on the backlight
 lcd.init();
 lcd.backlight();
 lcd.setCursor(0,0);
 lcd.print("GPS Data Logger");
 //Initialise the GPS module
 nss.begin(4800);
 pinMode(powerpin, OUTPUT);
 digitalWrite(powerpin, LOW);
 //Check for SD Card
 if (!SD.begin(chipSelect)) {
    lcd.setCursor(0,1);
    lcd.print("No SD Card!");
    CardInit = false;
 }else{
    lcd.setCursor(0,1);
    lcd.print("Card Initialised!");
    CardInit = true;
 }
 delay(1000);
 lcd.clear();
 //Find a free filename to use
 for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
 }
}

/*
Procedure to update and rotate the display
*/

void updateDisplay(){
  if(ScreenChange > 19){
  //If its been 20seconds Change the Screen  
    if(ScreenChange==20){
      //If it is 20seconds clear the screen and print the template
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Course: ");
      lcd.setCursor(0,1);
      lcd.print("Satelites: ");
    } 
    //Update Values
    lcd.setCursor(8,0);
    lcd.print(GPScour);
    lcd.setCursor(11,1);
    lcd.print(GPSsat);
    //If it is 30seconds reset the count
    if(ScreenChange==30){ScreenChange = 0;}
  }else{
    if (ScreenChange > 9){
      //If its been 10seconds Change the Screen
      if(ScreenChange == 10){
        //If it is 10seconds clear screen and print template
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Speed: ");
        lcd.setCursor(0,1);
        lcd.print("Alt: ");
      }
      //Update values
      lcd.setCursor(7,0);
      lcd.print(GPSspeed);
      lcd.setCursor(5,1);
      lcd.print(GPSalt); 
    }else{
      //If its the first time
      if(ScreenChange == 1){
        //if it is the first display, clear screen and print template
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Lat: ");
        lcd.setCursor(0,1);
        lcd.print("Lon: ");  
      }
      //Update values
      lcd.setCursor(5,0);
      lcd.print(GPSlat);
      lcd.setCursor(5,1);
      lcd.print(GPSlon); 
    } 
  }
}

/*
Procedure to show a searching animation
*/

void showSearching(){
  char SearchStr[13];
  //Set String to just Searching
  strcpy(SearchStr,"Searching");
  if (DotCount > 4){
    //If its higher than 4 Clear it
    DotCount = 0;
    lcd.clear();
  }else{
    //Print the amount of dots after the string
    for(int i=0; i < DotCount; i++){
      strcat(SearchStr,".");
    } 
  }
  //Print it to the Screen
  lcd.setCursor(0,0);
  lcd.print(SearchStr);
  lcd.setCursor(0,1);
  lcd.print("Found : ");
  GPSsat = gps.satsused();
  lcd.print(GPSsat);
}

/*
Check GPS Status
*/
boolean checkGPS(){
  while (nss.available()){
    if(gps.encode(nss.read())){
      if (gps.fixtype() == TinyGPS::GPS_FIX_NO_FIX){
        return false; 
      }else{
        return true; 
      }
    }
  }
}

/*
Procedure to read gps data into global variables
*/
void readGPS(){
  float l_lat,l_lon;
  unsigned long age, date, time;
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.f_get_position(&l_lat, &l_lon, &age);
  GPSspeed = gps.f_speed_mph();
  GPScour = gps.f_course();
  GPSalt = gps.f_altitude();
  gps.get_datetime(&date,&time,&age);
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  GPSyear = year;
  GPSmonth = month;
  GPSday = day;
  GPShour = hour;
  GPSminute = minute;
  GPSsecond = second;
  GPShund = hundredths;
  if (gps.fixtype() == TinyGPS::GPS_FIX_2D){ strcpy(GPStype,"2D");}else{ strcpy(GPStype,"3D");}
}


/*
Loop function to run all the programs
*/

void loop(){
  //Use Screen Display so we only update the LCD every 1.5 Seconds
  ScreenDisplay++;
  GotSignal = checkGPS(); 
  if(GotSignal){
    //If we have a Signal read the GPS
    readGPS();
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since the screen updated
      //Reset the count, increase the ScreenChange Count and Display
      ScreenDisplay = 0;
      ScreenChange++;
      updateDisplay();
    }
    //Write to file here
    if (CardInit){
      lcd.setCursor(10,1);
      lcd.print("Ind"); 
      /*
      logfile = SD.open(filename, FILE_WRITE); 
      */
      logfile.println(GPSlat); logfile.print(",");
      logfile.print(GPSlon); logfile.print(",");
      logfile.close();
    }
  }else{
    //If We have no signal
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since screen refresh
      //Reset count increase the amount of dots and show animation
      ScreenDisplay = 0;
      DotCount++;
      showSearching();
    }
    //No need to write to file
  }
 //Pause half a second 
 delay(500); 
}

You might need to find the FreeMemory (or MemoryFree, I can't remember) function and see whether you are running out of memory.

One question. If you don't open logfile, which is commented out, then how do you write to it and close it?

void loop(){
  //Use Screen Display so we only update the LCD every 1.5 Seconds
  ScreenDisplay++;
  GotSignal = checkGPS(); 
  if(GotSignal){
    //If we have a Signal read the GPS
    readGPS();
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since the screen updated
      //Reset the count, increase the ScreenChange Count and Display
      ScreenDisplay = 0;
      ScreenChange++;
      updateDisplay();
    }
    //Write to file here
    if (CardInit){
      lcd.setCursor(10,1);
      lcd.print("Ind"); 
      /*
      logfile = SD.open(filename, FILE_WRITE); 
      */
      logfile.println(GPSlat); logfile.print(",");
      logfile.print(GPSlon); logfile.print(",");
      logfile.close();
    }
  }else{
    //If We have no signal
    if(ScreenDisplay > 2){
      //If its been 1.5 Seconds since screen refresh
      //Reset count increase the amount of dots and show animation
      ScreenDisplay = 0;
      DotCount++;
      showSearching();
    }
    //No need to write to file
  }
 //Pause half a second 
 delay(500); 
}

if you see the commented out line logfile = open, if i include that line the arduino crashes when it comes round to the loop, if i dont it runs fine, it is never going inside the if statement though as the lcd.print(ind) is not being executed.

Im seriously confused.
[/quote]

What is the value of CardInit? Is GotSignal ever true?

It will never go into that function to write the lines as card init is never true, i have checked card init is always false so i just left those lines as i wanted to see the specific line it failed on.

Got signal can be true if the GPS finds satelites but that is not happening just now as im indoors and it crashes after one itteration of showSearching()

I ran Memoryfree, i get 495 when the line is not present or 466 when it is present just before it crashes.

You have already opened the file in setup(). I don't know what would happen if you opened it again, but I doubt it's going to be pretty.

In the second call to open it, you don't have the logic to deal with existing files.

What happens when all 100 possible file names already exist, or something else prevents you from opening the file? Your subsequent logic would assume that you have opened it since the SD card is present. It would be better to check for a valid file handle rather than for the presence of the card.

You say the code section with the second initialisation is never executed. Are you inferring that from the lcd.print statements in setup()?

The code first checks if there is an sd card, as this is optional.

Then it checks for a valid filename, that filename is passed through the program and each time the data is written the file is open and closed. This is because if you write and dont close the file, should the device be powered down you loose the data.

But...

There is no sd card in the device when it fails, cardinit is always false, so it will never go into that loop to try and write to it, i haven't finished writting the file handling code as its not needed at the moment and it should not be getting used as the booleans should prevent it.
But the code seems to be accessing it????

No i mean in the loop comand where the line is commented out, in fact both card initialisation scripts are bypassed, yet the code makes it fall over.

Hmmm actually the filename checking code should be inside a cardinit if loop, so it is trying to open a file that can't exist in the setup code, but yet it always goes way past that

Why not each time open the file for append? If you lose power before it closes the FAT should report the old file length, no? Maybe not, it's been so damn long, I seem to remember a time and OS when flushing the buffers was all it took.