Program Stops Running Intermittently

I have the strangest problem that I can’t seem to debug or solve whatsoever. It even stumped my professor. Some fresh eyes are definitely needed here.

I am making a device that stores gps data on an sd card every few seconds. The gps data is appended to a string every second until we reach the limit (512 bytes) for a print via SD library. While this is going on, I am using an IMU to affect the strip brightness. Things will be a bit more complicated, but the code cannot make it through the setup code before freezing.

Hardware:
Teensy 2.0
Adafruit GPS Breakout
Adafruit BNO055 IMU
SD card breakout
Neopixel WS2812B

Sketch uses 30,800 bytes (95%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,553 bytes (60%) of dynamic memory, leaving 1,007 bytes for local variables. Maximum is 2,560 bytes.

Running low on storage space, but should have plenty of dynamic memory left. I even used the freememory library to see how memory changes as the code starts to run

GPSLog02.csv opened
Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)
break

Opens the log file fine and prints the header. Breaks out of the openlogfile function, turns on the LED’s to red, but does not make it to “end setup” serial print.

//__________________________________________GPS________________________________________//
#include <TinyGPS++.h>
static const int GPSBaud = 9600;
TinyGPSPlus gps;
HardwareSerial Uart = HardwareSerial();
//__________________________________________GPS________________________________________//

//__________________________________________SD________________________________________//
#include <SPI.h>
#include <SD.h>
static const int chipSelect = 0;
char fileName[16];
String dataBatch = "";
int buffCount = 0;
//__________________________________________SD________________________________________//

//__________________________________________LED________________________________________//
#include "FastLED.h"
#define NUM_LEDS 10
#define DATA_PIN 4
CRGB leds[NUM_LEDS];
//__________________________________________LED________________________________________//

//__________________________________________BNO055________________________________________//
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#define BNO055_SAMPLERATE_DELAY_MS (100)
Adafruit_BNO055 bno = Adafruit_BNO055();
int accelTotal;
const int sampleSize = 24;
int accelTotals[24];
int currentSample;
int accelAvg;
//__________________________________________BNO055________________________________________//

#define DEBUG
void setup() {
  Serial.begin(9600);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  Uart.begin(GPSBaud);
  delay(1000);
  SD.begin(chipSelect);
  delay(1000);
  openLogFile();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Red;
    FastLED.show();
  }
  delay(1000);
  debug("end setup");
}

void loop() {
  debug("loop");
  if (buffCount <= 4) {
    if (!gps.location.isUpdated()) {
      printInt(gps.satellites.value(), 2);
      printComma();
      printFloat(gps.location.lat(), 10, 6);
      printComma();
      printFloat(gps.location.lng(), 11, 6);
      printComma();
      printDateTime(gps.date, gps.time);
      printComma();
      printFloat(gps.altitude.feet(), 7, 2);
      printComma();
      printFloat(gps.speed.mph(), 6, 2);
      printLine();
      buffCount++;
    }
    if (buffCount == 4) {
      File logFile = SD.open(fileName, FILE_WRITE);
      Serial.println(dataBatch);
      logFile.print(dataBatch);
      logFile.close();
      dataBatch = F("");
      buffCount = 0;
    }
    smartDelay(1000);
  }
}

static void smartDelay(unsigned long ms) {
  unsigned long start = millis();
  do {
    while (Uart.available()) {
      gps.encode(Uart.read());
      checkAccelerometer();
      accelAverage();
      accelAvg = map (accelAvg, 10, 50, 1, 255);
      FastLED.setBrightness(accelAvg);
      FastLED.show();
    }
  } while (millis() - start < ms);
}

static void printInt(unsigned long val, int len) {
  char sz[32];
  sprintf(sz, "%ld", val);
  dataBatch += sz;
  smartDelay(0);
}

static void printFloat(float val, int len, int prec) {
  char sz[32];
  dtostrf(val, len, prec, sz);
  dataBatch += sz;
  smartDelay(0);
}

static void printDateTime(TinyGPSDate & d, TinyGPSTime & t) {
  char sz[32];
  sprintf(sz, "%02d/%02d/%02d", d.month(), d.day(), d.year());
  dataBatch += sz;

  dataBatch += F(",");

  sprintf(sz, "%02d:%02d:%02d", t.hour() , t.minute(), t.second());
  dataBatch += sz;
  smartDelay(0);
}

static void printComma() {
  dataBatch += F(",");
}

static void printLine() {
  dataBatch += F("\r\n");
}

void openLogFile () {
  for (unsigned int index = 0; index < 100; index++) {
    sprintf(fileName, "GPSLog%02d.csv", index);
    if (!SD.exists(fileName)) {
      Serial.print(fileName);
      Serial.print(" ");
      File logFile = SD.open(fileName, FILE_WRITE);
      debug("opened");
      if (logFile) {
        Serial.println(F("Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)"));
        logFile.println(F("Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)"));
        logFile.close();
        debug("break");
        break;
      }
    }
  }
}

void accelAverage() {
  if (currentSample == sampleSize) {
    currentSample = 0;
  }
  checkAccelerometer();
  accelTotals[currentSample] = accelTotal;

  for (int i = 0; i < sampleSize; i++) {
    accelAvg += accelTotals[i];
  }
  accelAvg = (accelAvg / sampleSize);

  currentSample++;
  if (accelAvg < 10) {
    accelAvg = 10;
  }
}

void checkAccelerometer() {
  accelTotal = 0;
  imu::Vector<3> acceleration = bno.getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER);
  float fx = sq(acceleration.x()); //add volatile if I use interrupts
  float fy = sq(acceleration.y());
  float fz = sq(acceleration.z());
  accelTotal = sqrt(fx + fy + fz);
}

void debug (char const * message) {
#ifdef DEBUG
  Serial.println(message);
#endif
}

IMG_1002-1.JPG

IMG_1001-1.JPG

You used the String class. It's crashing your system.

Are you saying that i'm getting memory overflow problems? Even before I actually call the string and add to it? Is there a better way to do what i'm trying to do with the SD card writes?

I took out the string and approached the SD prints a bit differently. Also switched from FastLED to adafruit’s neopixel library.

//__________________________________________GPS________________________________________//
#include <TinyGPS++.h>
static const int GPSBaud = 9600;
TinyGPSPlus gps;
HardwareSerial Uart = HardwareSerial();
//__________________________________________GPS________________________________________//

//__________________________________________SD________________________________________//
#include <SPI.h>
#include <SD.h>
static const int chipSelect = 0;
char fileName[16];
int buffCount = 0;
File logFile;
//__________________________________________SD________________________________________//

//__________________________________________LED________________________________________//
#include <Adafruit_NeoPixel.h>
#define NUMPIXELS 10
#define PIN 4
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//__________________________________________LED________________________________________//

//__________________________________________BNO055________________________________________//
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#define BNO055_SAMPLERATE_DELAY_MS (100)
Adafruit_BNO055 bno = Adafruit_BNO055();
int accelTotal;
const int sampleSize = 24;
int accelTotals[24];
int currentSample;
int accelAvg;
//__________________________________________BNO055________________________________________//

#define DEBUG
void setup() {
  Serial.begin(9600);
  pixels.begin();
  Uart.begin(GPSBaud);
  delay(1000);
  SD.begin(chipSelect);
  delay(1000);
  openLogFile();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 255, 0));
  }
  pixels.show();
  delay(1000);
  debug("end setup");
}

void loop() {
  debug("loop");

  if (!gps.location.isUpdated()) {
    debug("isUpdated");
    logFile = SD.open(fileName, FILE_WRITE);
    printInt(gps.satellites.value(), 2);
    printComma();
    printFloat(gps.location.lat(), 10, 6);
    printComma();
    printFloat(gps.location.lng(), 11, 6);
    printComma();
    printDateTime(gps.date, gps.time);
    printComma();
    printFloat(gps.altitude.feet(), 7, 2);
    printComma();
    printFloat(gps.speed.mph(), 6, 2);
    printLine();
    logFile.close();
    debug("file closed");
  }
  smartDelay(1000);
}

static void smartDelay(unsigned long ms) {
  unsigned long start = millis();
  do {
    debug("do while");
    while (Uart.available()) {
      debug("while Uart");
      gps.encode(Uart.read());
      checkAccelerometer();
      accelAverage();
      accelAvg = map (accelAvg, 10, 50, 1, 255);
    }
  } while (millis() - start < ms);
}

static void printInt(unsigned long val, int len) {
  debug("start printInt");
  char sz[32];
  sprintf(sz, "%ld", val);
  Serial.print(sz);
  logFile.print(sz);
  debug("printInt");
  smartDelay(0);
}

static void printFloat(float val, int len, int prec) {
  char sz[32];
  dtostrf(val, len, prec, sz);
  Serial.print(sz);
  logFile.print(sz);
  debug("printFloat");
  smartDelay(0);
}

static void printDateTime(TinyGPSDate & d, TinyGPSTime & t) {
  char sz[32];
  sprintf(sz, "%02d/%02d/%02d", d.month(), d.day(), d.year());
  Serial.print(sz);
  logFile.print(sz);

  Serial.print(F(","));
  logFile.print(F(","));

  sprintf(sz, "%02d:%02d:%02d", t.hour() , t.minute(), t.second());
  Serial.print(sz);
  logFile.print(sz);
  smartDelay(0);
}

static void printComma() {
  logFile.print(F(","));
  Serial.print(F(","));
}

static void printLine() {
  Serial.print(F("\r\n"));
  logFile.print(F("\r\n"));
}

void openLogFile () {
  for (unsigned int index = 0; index < 100; index++) {
    sprintf(fileName, "GPSLog%02d.csv", index);
    if (!SD.exists(fileName)) {
      Serial.print(fileName);
      Serial.print(" ");
      File logFile = SD.open(fileName, FILE_WRITE);
      debug("opened");
      if (logFile) {
        Serial.println(F("Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)"));
        logFile.println(F("Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)"));
        logFile.close();
        debug("break");
        break;
      }
    }
  }
}

void accelAverage() {
  if (currentSample == sampleSize) {
    currentSample = 0;
  }
  checkAccelerometer();
  accelTotals[currentSample] = accelTotal;

  for (int i = 0; i < sampleSize; i++) {
    accelAvg += accelTotals[i];
  }
  accelAvg = (accelAvg / sampleSize);

  currentSample++;
  if (accelAvg < 10) {
    accelAvg = 10;
  }
}

void checkAccelerometer() {
  accelTotal = 0;
  imu::Vector<3> acceleration = bno.getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER);
  float fx = sq(acceleration.x()); //add volatile if I use interrupts
  float fy = sq(acceleration.y());
  float fz = sq(acceleration.z());
  accelTotal = sqrt(fx + fy + fz);
}

void debug (char const * message) {
#ifdef DEBUG
  Serial.println(message);
#endif
}

Still only getting so far in the code.

GPSLog13.csv opened
Satellites,Latitude,Longitude,Date,Time (UTC),Altitude (Feet),Speed (MPH)
break
end setup
loop
isUpdated

Why don’t I make a example SD logging application for NeoGPS?

Venting aside, this is a very common problem. Ultimately you are Trying To Do Too Much At The Wrong Time™.

In your case, smartDelay (which isn’t), combined with opening and closing the SD file for every new location report will never work. Eliminating String was absolutely required, so good on ya’ for getting that out of the way.

Rather than retype the same sad story, please take a look at my library and the troubleshooting links above. Even if you don’t use it, it could help you understand the issues and (perhaps) restructure your sketch in a way that might work. I wrote NeoGPS because I was having the same problems you are having.

There are several other issues with your sketch, but you should get the larger issues out of the way first.

Cheers,
/dev

/dev:
Why don’t I make a example SD logging application for NeoGPS?

Venting aside, this is a very common problem. Ultimately you are Trying To Do Too Much At The Wrong Time™.

In your case, smartDelay (which isn’t), combined with opening and closing the SD file for every new location report will never work. Eliminating String was absolutely required, so good on ya’ for getting that out of the way.

Rather than retype the same sad story, please take a look at my library and the troubleshooting links above. Even if you don’t use it, it could help you understand the issues and (perhaps) restructure your sketch in a way that might work. I wrote NeoGPS because I was having the same problems you are having.

There are several other issues with your sketch, but you should get the larger issues out of the way first.

Cheers,
/dev

Thanks for the info about your library. I see the problem, but I have an earlier version of my sketch (v1) that combines all of the things I’m trying to do and it works just fine.

//__________________________________________GPS________________________________________//
#include <TinyGPS++.h>
static const int GPSBaud = 9600;
TinyGPSPlus gps;
HardwareSerial Uart = HardwareSerial();
//__________________________________________GPS________________________________________//

//__________________________________________SD________________________________________//
#include <SPI.h>
#include <SD.h>
static const int chipSelect = 0;
char fileName[16];
String dataBatch = "";
int buffCount = 0;
//__________________________________________SD________________________________________//

//__________________________________________BNO055________________________________________//
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#define BNO055_SAMPLERATE_DELAY_MS (100)
Adafruit_BNO055 bno = Adafruit_BNO055();
int accelTotal;
int sampleSize = 24;
int accelTotals[24];
int currentSample;
int accelAvg;
//__________________________________________BNO055________________________________________//

//__________________________________________LED________________________________________//
#include "FastLED.h"
#define NUM_LEDS 10
#define DATA_PIN 4
CRGB leds[NUM_LEDS];
//__________________________________________LED________________________________________//



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

  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  bno.begin();
  delay(1000);
  bno.setExtCrystalUse(true);

  Uart.begin(GPSBaud);

  Serial.println(F("Initializing SD card..."));
  SD.begin(chipSelect);
  openLogFile();
  Serial.println(fileName);

  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Blue;
    FastLED.show();
  }
  delay(1000);
  File logFile = SD.open(fileName, FILE_WRITE);
}

void loop() {
  if (buffCount <= 2) {
    if (gps.location.isValid()) {
      dataBatch += gps.satellites.value();
      dataBatch += F(",");
      dataBatch += gps.location.lat();
      dataBatch += F(",");
      dataBatch += gps.location.lng();
      dataBatch += F(",");
      printDateTime(gps.date, gps.time);
      dataBatch += F(",");
      dataBatch += gps.altitude.feet();
      dataBatch += F(",");
      dataBatch += gps.speed.mph();
      dataBatch += F("\r\n");
      buffCount++;
    }
    if (buffCount == 2) {
      File logFile = SD.open(fileName, FILE_WRITE);
      logFile.print(dataBatch);
      Serial.print(dataBatch);
      logFile.close();
      dataBatch = F("");
      buffCount = 0;
    }
  }
  smartDelay(1000);
}

static void smartDelay(unsigned long ms) {
  unsigned long start = millis();
  while (millis() - start < ms) {
    gps.encode(Uart.read());
    accelAverage();
    accelAvg = map (accelAvg, 10, 50, 1, 255);
    FastLED.setBrightness(accelAvg);
    FastLED.show();
  }
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t) {
  File logFile = SD.open(fileName, FILE_WRITE);
  if (!d.isValid()) {
    dataBatch += F("**********");
  }
  else {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d", d.month(), d.day(), d.year());
    dataBatch += sz;
  }
  dataBatch += ",";

  if (!t.isValid()) {
    dataBatch += F("********");
  }
  else {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d", t.hour() , t.minute(), t.second());
    dataBatch += sz;
  }
}
//
//static void printDateTime(TinyGPSDate & d, TinyGPSTime & t) {
//  if (d.isValid()) {
//    char sz[10];
//    sprintf(sz, "%02d/%02d/%02d", d.month(), d.day(), d.year());
//    dataBatch += sz;
//    dataBatch += ",";
//  }
//
//  if (t.isValid()) {
//    char sz[10];
//    sprintf(sz, "%02d:%02d:%02d", t.hour() , t.minute(), t.second());
//    dataBatch += sz;
//  }
//}

void openLogFile () {
  for (unsigned int index = 0; index < 100; index++) {
    sprintf(fileName, "GPSLog%02d.csv", index);
    if (!SD.exists(fileName)) {
      File logFile = SD.open(fileName, FILE_WRITE);
      if (logFile) {
        //Serial.println(F("Sats,Latitude,Longitude,Date,Time,Altitude,Speed"));
        logFile.println(F("Sats,Latitude,Longitude,Date,Time,Altitude,Speed"));
        logFile.close();
        break;
      }
    }
  }
}

void accelAverage() {
  if (currentSample == sampleSize) {
    currentSample = 0;
  }
  checkAccelerometer();
  accelTotals[currentSample] = accelTotal;

  for (int i = 0; i < sampleSize; i++) {
    accelAvg += accelTotals[i];
  }
  accelAvg = (accelAvg / sampleSize);

  currentSample++;
  if (accelAvg < 10) {
    accelAvg = 10;
  }
}

void checkAccelerometer() {
  accelTotal = 0;
  imu::Vector<3> acceleration = bno.getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER);
  accelTotal = sqrt(sq(acceleration.x()) + sq(acceleration.y()) + sq(acceleration.z()));
}

Welp... after hours of debugging and starting over from scratch multiple times I compared the version in post #5 of this thread (v1) with v5 of the code and I found I wasn't doing a very important step in setup.

  bno.begin();
  delay(1000);
  bno.setExtCrystalUse(true);

Everything works. facepalm