void loop() - Any size limitation ?? ( SOLVED - Ref #66)

Please check this code below. Its a Mega 2560 board. It only runs when the last segment is commented out as shown. If I remove the comment, and irrespective of whether I press the START button or not, the code keeps executing the void setup() repeatedly. As if someone pressed the reset button ...

There is no need to worry about what's inside the commented code segment - if I don't press START, it anyway will not execute. But still the Arduino keeps repeating the setup().

So I am wondering if there is any size limitation for loop() ? What else is the issue ??

//=================== INCLUDE ====================

// Include Libraries :
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include "Wire.h"
#include <phi_interfaces.h>
#include <EEPROM.h>
#include <SD.h>

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//================== DEFINES ======================
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

// Define the LCD pins to use and Initialize an instance
LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7); // 0x27 is the I2C bus address

// DEFINE THE HARDWARE INPUTS AND OUTPUT PINS

#define StartPB 31                                         // Mega2560 mapping
#define IncrPB 33
#define DecrPB 35
#define EnterPB 37
#define total_buttons 4
char mapDIN[] = {'S', 'I', 'F', 'E'};                      // This is a list of names for each button.
byte pinDIN[] = { StartPB, IncrPB, DecrPB, EnterPB};       // The digital pins connected to the 4 buttons.
phi_button_groups MyDIN(mapDIN, pinDIN, total_buttons);
multiple_button_input* pad1 = &MyDIN;

int BuzzerOut = 14;                                         // Output pin defines...
int BTState   = 15;
int FltLedOut = 16;
const int chipSelect = 4;                                   // SD card select on shield
const int etherSelect = 10;                                 // Ethernet select on shield
const int rfidSelect = 53;                                  // RFID select on MEGA


// LIST ALL GLOBAL VARIABLES..

char LCDmsg[20];                                           // Mega2560
unsigned int ScanMs = 50;
char ValidDIN = '0';
boolean newData = false;
const byte numChars = 85;
char receivedChars[numChars];                              // an array to store the received data
char sdFileName[13];
byte sdFileNo;
byte tempSDFileNo;
int eepAddress = 5;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
char tempchar[5];
char Yr_Array[5];
char Mo_Array[5];
char Dt_Array[5];
char Hr_Array[5];
char Mi_Array[5];
char CurLoc, NCurLoc;

int static timeOut = 0;
int static recordCount = 0;
int noOfRecords = 0;
char readCount[4];

// Define Gate Flags to block segments by choice.
boolean RTC_Disp_Gate = HIGH;
boolean RTC_Set_Gate = 0, RTC_Set_Gate01 = 1, RTC_Set_Gate02 = 0, HomeDisp_Gate = 1, HomeDisp_3L_Lock = 1; ;
boolean RTC_Latch = 1, Ser_Rd_Latch = 1, Ser_Rd_Gate = 0, validRecord_Gate = 0;

// Char Arrays for Grease data display..
char RFID[11];
/*char grQty[4];
  char routeName[16];
  char routeNo[4];
  char bearingRef[20];
  char greaseType[12];*/



//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//================= SETUP =========================
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void setup()
{
  // START SERIAL FOR DEBUGGING
  Serial.begin(9600);
  // Usage : Serial.println(variable);

  // START THE I2C INTERFACE
#define DS3231_I2C_ADDRESS 0x68             // 0x68 is the RTC address
  Wire.begin();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xE);                            // Address the Control Register
  Wire.write(0x00);                           // Write 0x0 to control Register
  Wire.endTransmission();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xF);                            // Address the Status register
  Wire.write(0x00);                           // Write 0x0 to Status Register
  Wire.endTransmission();

  // SETUP THE OUTPUT PIN and SPI select pins
  pinMode(BuzzerOut, OUTPUT);
  pinMode(BTState, OUTPUT);
  pinMode(FltLedOut, OUTPUT);
  pinMode(chipSelect, OUTPUT);
  pinMode(etherSelect, OUTPUT);
  pinMode(rfidSelect, OUTPUT);

  digitalWrite( etherSelect, HIGH);           // Permanently disable EThernet interface

  // START THE LCD INTERFACE

  lcd.begin(20, 4);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  lcd.print(F( "VAP LUBE MANAGEMENT."));
  lcd.setCursor(0, 1);
  lcd.print(F( "   Version : 1.00   "));
  lcd.setCursor(0, 2);
  lcd.print(F( "Checking the SD card"));
  lcd.setCursor(0, 3);
  lcd.print(F( "Interface.. Wait...."));
  delay (2000);
  digitalWrite( rfidSelect, HIGH);
  if (!SD.begin(chipSelect)) {
    lcd.clear();
    lcd.print(F( "SD Card fail. Check!"));
    return;                                               // No card .. just return..
  }
  lcd.clear();
  lcd.print(F( "SD Card check pass!!"));
  delay(1000);

  // SETUP THE OUTPUT PIN and SPI select pins
  pinMode(BuzzerOut, OUTPUT);
  pinMode(BTState, OUTPUT);
  pinMode(FltLedOut, OUTPUT);

}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//================ SCAN LOOP ======================
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

void loop()
{
  // ENDLESS LOOP EXECUTION STARTS HERE:

  // Read the Push buttons  for every scan..
  ValidDIN = MyDIN.getKey();

  if (HomeDisp_Gate) displayHome();                        //Upddate the Home Screen with date time once every second

  // =======================================

  // RTC CLOCK SETTING ROUTINE
  if ( ValidDIN == 'I' && RTC_Latch ) {
    RTC_Latch = 0;
    RTC_Set_Gate = 1;
    HomeDisp_Gate = 0;
    HomeDisp_3L_Lock = 0;
    Ser_Rd_Latch = 0;
    ValidDIN = '0';                                         // Flush the ValidDIN variable...
  }

  if (RTC_Set_Gate) Set_TimeOfRTC3231();

  // =======================================

  // READ SERIAL DATA AND STORE TO SD CARD
  if ( ValidDIN == 'F' && Ser_Rd_Latch ) {
    Ser_Rd_Latch = 0;
    Ser_Rd_Gate = 1;
    HomeDisp_Gate = 0;
    timeOut = 0;
    lcd.clear();

    // Code to generate new number for greaseplanxxx.csv file.

    sdFileNo = EEPROM.read (eepAddress);                   // Get the current file number stored in EEPROM
    tempSDFileNo = sdFileNo;                               // Save the current file no to restore if SD write Timesout
    sdFileNo ++ ;                                          // Increment it to generate the next number
    if (sdFileNo > 125) sdFileNo = 1;                      // Reset if file number is more than 200
    EEPROM.write (eepAddress, sdFileNo);                   // Write the generated number to EEPROM
    sprintf(sdFileName, "GPlan%03d.csv", sdFileNo);        // Generate the new File name to get XLS data...
    lcd.setCursor(0, 0);
    lcd.write(sdFileName);
    lcd.setCursor(0, 3);
    lcd.print(F( "Awaiting Data......."));
    recordCount = 0;                                       // Reset Record Count...
  }
  if ( Ser_Rd_Gate && timeOut > 10000 ) {                 // Serial data not received in 10 secs ... time out.
    Ser_Rd_Latch = 1;
    Ser_Rd_Gate = 0;
    HomeDisp_Gate = 1;
    HomeDisp_3L_Lock = 1;
    timeOut = 0;
    lcd.clear();
    EEPROM.write (eepAddress, tempSDFileNo);             // Reset the generated number to EEPROM
  }
  else {
    if (Ser_Rd_Gate) ReadAndStoreToSD();                 // Wait for serial data...
    //timeOut += ScanMs;                                 //  Have bypassed this... may not be required
  }
  //======================================



 // Program runs normally only if this segment below is commented out..
  /*
  if ( ValidDIN == 'S' ) {                               // User has pressed Start....
      lcd.clear();
      sdFileNo = 120;
      File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
          dataFile.seek(i);
          RFID[i - 6] = dataFile.read();
          dataFile.close();
        }
        sprintf( LCDmsg, "%s", RFID);
        lcd.print(LCDmsg);
        validRecord_Gate = 0;
      }
      else {
        lcd.clear();
        sprintf(sdFileName, "    GPlan%03d.csv     ", sdFileNo); // Use the file name to generate an error report..
        lcd.write(sdFileName);
        lcd.setCursor(0, 1);
        lcd.print(F("  SD File Error !!  "));
        lcd.setCursor(0, 2);
        lcd.print(F(" Reset and Verify.."));
        while (1);                                            // Hold the message...and wait for reset.
      }
    }
  */


  
  delay (ScanMs);

}// End of main loop.

//================ SCAN LOOP END =================

Only the size of the Flash of the device - but then it won't download. More likely you are running out of RAM.

How are you powering the SDcard? They can take quite high currents.

Yes most definitely its some kind of memory issue. Flash definitely is not an issue as the full program is less that 23 Kb and the Mega has 256 Kb.

If its the 8kb SRAM that's the issue what exactlky is the option ? And I am yet to reach the end of the program - another 25% is left to be coded :frowning:

What can be done now ??

( And I am powering the whole kit with a 9V adaptor rated for about 1A )

You open the file once, then you seek, read and close it 10 times.
Maybe the library crashes on that kind of usage.

      File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
          dataFile.seek(i);
          RFID[i - 6] = dataFile.read();
          dataFile.close();
        }

Whandall:
You open the file once, then you seek, read and close it 10 times.
Maybe the library crashes on that kind of usage.

      File dataFile = SD.open("GPlan120.csv", FILE_READ);

if (dataFile) {
        for (int i = 6; i < 16; i++) {
          dataFile.seek(i);
          RFID[i - 6] = dataFile.read();
          dataFile.close();
        }

Worse than that. He opens the file, reads one byte, close the file, then read 9 more bytes. Very likely attempting to read the second byte, from a now closed file, is what causes the crash.

Regards,
Ray L.

I am glad to get fast responses... but then the whole code is inside a trap: if ( ValidDIN == 'S' ) { ...}

So if S button is not pressed this code should never execute and thus what is inside curly brackets should not matter ?

And as to opening closing 10 times / sec. In the actual code that will not happen as the condition was

if (ValidDIN == 'S' && validRecord_Gate ) {

...
...
validRecord_Gate = 0;

...
...
}

Anyway what I posted is only the main setup() and loop() parts and apart from this there are functions in separate tables for RTC and SD card functions.

I still have no clue why the processor keeps resetting.

You still close the file 10 times for every time you open it! The close command needs to be out of the for loop. Whether it causes the current crash or not, it is still a bad bug.

Yes noted. That code segment anyway needs lot of working and I will keep this point about closing it in mind. Thanks.

OK, you commented out the entire "if" segment and it works.
How about commenting out everything inside "if" - with exception of lcd.clear()?
And than do same for the "else" code.
Brute and unscientific but it could narrow the problem little further down.

Mogaraghu:

//=================== INCLUDE ====================

char sdFileName[13];

[...]
       sprintf(sdFileName, "    GPlan%03d.csv     ", sdFileNo); // Use the file name to generate an error report..
       lcd.write(sdFileName);

Your sprintf() seems to write a string longer than the buffer, and lcd.write() if I remember right is for writing only a byte. May it's not your main problem, but give it a try!

Cheers, Ale.

So by the process of eliminating line by line the offending last code segment, I have located the culprit. It is this statement :

File dataFile = SD.open("GPlan120.csv");

I know it sounds crazy but then that's what it is. If I comment out the above line the code runs fine. But what I am not able to understand is the processor resets even when it has no chance to execute the above statement as it is with in a IF condition and I ensure that the condition evaluates false.

Are we looking at a compiler level bug ??

Well, add a free memory test to the end of setup() and see how much memory you're really using (when in the commented-out-and-working state.) If you're close to the limit, then think about trimming down some of those large arrays. Or get a Teensy.

Free Memory test at the end of setup() reports 6585 with the offending code segment and 6598 without it. So I really don't think its a memory issue.

The very fact that the code runs normally as soon as I comment out,

File dataFile = SD.open("GPlan120.csv",FILE_READ);

says something about the issue. Wish I knew what the message is....

Mogaraghu:
So by the process of eliminating line by line the offending last code segment, I have located the culprit. It is this statement :

File dataFile = SD.open("GPlan120.csv");

I know it sounds crazy but then that's what it is. If I comment out the above line the code runs fine. But what I am not able to understand is the processor resets even when it has no chance to execute the above statement as it is with in a IF condition and I ensure that the condition evaluates false.

Are we looking at a compiler level bug ??

So, there's a few things here.

  1. We are 99.99999% definitely not looking at a complier bug. It is almost never a compiler bug, no matter how much we think it is.

  2. Just commenting out that line would result in a compile error, so I'm not sure exactly what you did.

  3. The code in this area looks like this:

      File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
          dataFile.seek(i);
          RFID[i - 6] = dataFile.read();
          dataFile.close();
        }

so, it's not necessarily the line itself that causes the problem since the "if" only gets entered if the line is executed successfully. In other words, it could be that line, or anywhere inside the "if".

My guess is as already stated, the dataFile.seek() will fail and probably throw an exception if the file has been closed. So, change the code to this:

      File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
          dataFile.seek(i);
          RFID[i - 6] = dataFile.read();
        }
        dataFile.close();

and it will probably fix your problem.

Just commenting out that line would result in a compile error, so I'm not sure exactly what you did.

OK let me clarify - that line plus all SD card references were commented out.

While all of you are all focusing on the bugs inside the if(ValidDIN == 'S') {}, my main contention is that the processor keeps resetting and keeps repeating the setup() code even when the above if condition is NOT true.

And it is inside this "if" condition, I have the SD Card related code and the resetting does not happen when I comment out that.

( I also agree that 99.999999 % compiler bugs are rare but till I find my own problem this is a escape route ?!)

Mogaraghu:

Just commenting out that line would result in a compile error, so I'm not sure exactly what you did.

OK let me clarify - that line plus all SD card references were commented out.

While all of you are all focusing on the bugs inside the if(ValidDIN == 'S') {}, my main contention is that the processor keeps resetting and keeps repeating the setup() code even when the above if condition is NOT true.

And it is inside this "if" condition, I have the SD Card related code and the resetting does not happen when I comment out that.

( I also agree that 99.999999 % compiler bugs are rare but till I find my own problem this is a escape route ?!)

We are focussing on the SD card problem because that will almostly certainly cause a crash, and you said if you commented out the SDCard code, it doesn't crash. Am I missing something here? If so, post the code that does not have an SDCard read that you say crashes anyway.

With the three commented lines the code runs fine...

 if ( ValidDIN == 'S' && validRecord_Gate ) {                               // User has pressed Start....
      lcd.clear();
      sdFileNo = 120;
  // File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (1 == 1) {
        for (int i = 6; i < 16; i++) {
  // dataFile.seek(i);
         RFID[i - 6] = 'W';
        }
  // dataFile.close();
        sprintf( LCDmsg, "%s", RFID);
        lcd.print(LCDmsg);
        validRecord_Gate = 0;
      }
      else {
        lcd.clear();
        sprintf(sdFileName, "    GPlan%03d.csv     ", sdFileNo); // Use the file name to generate an error report..
        lcd.write(sdFileName);
        lcd.setCursor(0, 1);
        lcd.print(F("  SD File Error !!  "));
        lcd.setCursor(0, 2);
        lcd.print(F(" Reset and Verify.."));
        while (1);                                            // Hold the message...and wait for reset.
      }
    }

what about if you do this:

...
      sdFileNo = 120;
      File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
  // dataFile.seek(i);
         RFID[i - 6] = 'W';
        }
        dataFile.close();
...

does it crash?

I tried the suggestion given by you.

And also the one given below : And unfortunately both keep resetting.

....
     sdFileNo = 120;
      File dataFile;
  //` File dataFile = SD.open("GPlan120.csv", FILE_READ);
      if (dataFile) {
        for (int i = 6; i < 16; i++) {
  // dataFile.seek(i);
         RFID[i - 6] = 'W';
        }
        dataFile.close();
.....