Arduino Can't Run Forever

Hi guys,

I am in the final stages of developing a code for arduino mega 2560 as a datalogging device for a spectrometer. I’ve been having some issues with a part of the code. A little background: after clicking a button on an LCD, the Arduino enters a while(1) loop forever. It is supposed first take the time from the RTC, then take data from the spectrometer and write the data to SD card. Once two minutes go by, it repeats the process. It uses an if statement to wait for a change in millis to equal 120000 (or 120 seconds, two minutes):

if (buttons & BUTTON_DOWN) {
      while (1) {
        currentMillis = millis() + 120000;
        if (currentMillis - previousMillis >= interval) {
          
          //code for triggering data two minutes ahead
          previousMillis = millis() + 120000;

          if (!SD.begin(4)) {
            Serial.println(F("SD card failed to initialize"));
            return;
          }

          //open file for Continuous mode
          myFileContinuous.open("field.txt", FILE_WRITE);
          Serial.println(F("Continuous File opened"));

          //Get time and date
          getTimeandDate();
          Serial.println(F("Time and Date Retrieved"));

          //Write Time and Data to file
          writeTimeandDateCont();

          //notify user that Arduino is scanning array
          lcd.clear();
          lcd.setBacklight(WHITE); //Turn on display if off
          lcd.print(F("Scanning"));

          buttonPressCont();

          //Notify user that arduino is done scanning
          lcd.clear();
          lcd.print(F("Scan Complete"));
          Alarm.delay(1000);

          //close file and wait two minutes to begin next scan
          myFileContinuous.close();
          
          //Turn display off to save power
          lcd.setBacklight(OFF);
        }
      }
    }

The buttonPressCont() function, which tells the datalogging function startTimeCont() how many times to scan the sensor, is below:

void buttonPressCont() {

  for (uint8_t i = 0; i < 6; i++) {
    //first value is discarded from each scan
    startTimeCont(0);
    Alarm.delay(1);

    for (int i = 0; i < PIXELS; i++) {
      startTimeCont(i);
      Alarm.delay(1);
    }
  }
}

Finally, the startTimeCont, which does the datalogging is below:

int startTimeCont(int pixel) {
  unsigned int adc;
  PORTE |= _BV(5); //start high
  PORTE |= _BV(4); //clock high
  delayMicroseconds(4); //delay for start pulse width
  PORTE &= ~_BV(4); //clock low
  PORTE &= ~_BV(5); //start low

  for (int i = 0; i < pixel; i++) { //clock goes from low to high to
    //shuffle through pixels, find the one we want
    PORTE |= _BV(4); //clock high
    delayMicroseconds(4);
    PORTE &= ~_BV(4); //clock low, need to read now
  }
  adc = ads1115.readADC_Differential_0_1() + 21000;
  myFileContinuous.println(adc);


  for (int i = 0; i <= (PIXELS - pixel); i++) {
    PORTE |= _BV(4); //clock high
    delayMicroseconds(4);
    PORTE &= ~_BV(4); //clock low
  }
}

Everything works as expected, for several hours, taking data every two minutes, writing the time and data to the SD card. Then at around the two hour mark, plus or minus around four minutes, since first running the code, it gets stuck. I filled the code up with Serial.prints to find out where the problem might be, which led me to this:

SD card failed to initialize

then the serial printed this:

Continuous File opened

so after executing (or not):

myFileContinuous.open("field.txt", FILE_WRITE);

It ran into a problem opening the SD card. Why would this happen all of a sudden around the same time after running the code (~2 hours). Do you think it needs more time to initialize or maybe its overheating?

Some details about where/how its running:

75F office
powered by USB
running LCD, ASD 1115 (ADC), Ds3231 RTC and ethernet shield for sending off data every few days.

Thanks!

Your millis() code is highly irregular. You should clean it up by aligning it with the methods used in Blink Without Delay. Working with future time stamps is a recipe for disaster.

It ran into a problem opening the SD card

I'm not really surprised. Sd.begin() should happen ONCE, in setup(), regardless of how many files you intend to open in setup() or loop(). Calling SD.begin() multiple times is not really a good thing to do.

Thanks for the input guys! Good catch PaulS that was negligent on my part. And I agree aarg I'll work on that timing situation.

after clicking a button on an LCD, the Arduino enters a while(1) loop forever. It is supposed first take the time from the RTC, then take data from the spectrometer and write the data to SD card. Once two minutes go by, it repeats the process. It uses an if statement to wait for a change in millis to equal 120000 (or 120 seconds, two minutes):

Yeah, don't do this. The transformation is

void loop() {
  A();
  while(1) {
    B();
  }
  C();
}

to

enum State { stateA, stateB, stateC } state;

void setup() {
  state = stateA;
}

void loop() {
  switch(state) {
  case stateA:
    A();
    state = stateB;
    break;
  case stateB:
    B();
    if(some break condition) {
      state = stateC;
    }
    break;
  case stateC:
    C();
    state = stateA;
    break;
  }
}

it's more code, yes, and not as simple. But it's important that the loop return frequently so that hardware can do its thing. And although its not as simple for the simple case, once you start hooking up multiple things that interact, it becomes simpler to treat them as a number of separate state machines that interact asynchronously.

Also:

  • millis() runs off the resonator on the arduino board, which is not accurate. Your RTC will give correct readings, but they won't be 2 min apart
  • two minutes from the start of the reading to the start of the next, or two minutes from the end of the reading? Presumably the spectrometer reading takes time.

Then at around the two hour mark, plus or minus around four minutes, since first running the code, it gets stuck

Hmm - two hours.

PaulMurrayCbr, thank you for the tip. I had not seen such code until now. I will get to implementing that. Thank you all for the responses.