How can an Arduino crash?

Hy

The title maybe a bit strange but I got following problem:

My device has some LEDs with an GPS and GSM modem. The LEDs just light up when the GPS has a Fix otherwise they switch off. With a call to the Arduino I get the actual GPS position. Now after testing it for several month!!! The Arduino got stuck the first time. That means that even if I put int into a room the LEDs for the GPS fix still stays on and when I call it I won't get anything.

So I checked my code and there is no while loop where the program could stop.

So I'm asking myself how this could happen. What are other possibilities???

thx Andy

So I checked my code and there is no while loop where the program could stop.

So I'm asking myself what code that was.

I can't show the code but there are only to while loops for checking whether there is serial data or not so one is while (Serial1.available()) the other with serial2. So this shouldn't create that kind of stop...

If you can see the code and can't find the problem how do you expect anyone who can't see the code to spot it. Ah it might be on line 63, but that's just a guess.

I know, but I just asked if there is a possibility that the program stops without a loop that is running mad.

Could it be an Available Memory problem (to large char's)? but my tests showed it does just reset itself...

Yes it could be any of those things, it could also be electro magnetic interference, it could be intermittent connections, it could be faulty inputs causing the loops you have to hang. It could also be many things that I will only think of tonight. It could be it is not crashing but working in a mode you didn't expect.

How did you test your code? And why do you think it could only be stuck in a "while loop"? There are many other means for a CPU to get stuck.

I tested the device several or better many many times and it old worked very well until today where it got stuck... The while loop is the only thing I do know directly so that was also the reason why asked you here what other problems could occur...

One thing that can cause a crash or other unexpected behaviour is memory fragmentation, leading eventually to allocation failures. Are you using string objects or or other dynamic memory allocation? Are any of the libraries you use doing so? Having said that, if your system runs continuously for months at a time, it would need to be a very infrequently executed piece of allocation code to take so long to crash - perhaps an obscure error condition in one of your libraries.

I have a similar issue with a wifi shield transmitting temperature and humidity data. I think my record between crashes is about four days though. I need to tear into the async labs library at this point. You may need to do the equivalent for one of yours.

for the GPS decoding I use the "tinygps" library. Mine isn't running continuously just for about ~10hours and gets afterwards switched off...

GekoCH: for the GPS decoding I use the "tinygps" library.

Does that have "while loops" in it? Does it allocate memory?

I know, but I just asked if there is a possibility that the program stops without a loop that is running mad.

Yes. This will do it:

exit (0);

Also a brown-out might make it continually reset. It might have gone to sleep and not woken up. Memory might be corrupted. The default "main" function calls the "loop" function repeatedly. So there is another loop.

Strictly speaking it can't crash, it is just doing something you aren't expecting.

Also does it use I2C? That has been known to hang (it has loops inside it).

I can't show the code ...

Why not?

More class mates registered in the Arduino forums?

I would run a simple test of the wireless part to confirm it is even communicating. Maybe there is something nearby, like a wireless router, that is interfering.

The code is just too big but here is a part of my GSM data parsing.

void readGSM(int val){

  while(Serial1.available() > 0){
    if(unlock_sms==0){
      ReadSerial[0]=Serial1.read();
      if(debug > 1)
        Serial.print( ReadSerial[0]);

      if(ReadSerial[0]=='\n' || ReadSerial[0]=='*' || ReadSerial[0] == '+'){
        unlock_sms=1;
      }
    }
    else{
      ReadSerial[counter]=Serial1.read();
      if(debug > 1)
        Serial.print(ReadSerial[counter]);
      if(ReadSerial[counter] == '\r'){
        unlock_sms=0;

        if (strncmp(ReadSerial, "+CMTI:",6) == 0){
          char *parseptr_read = ReadSerial+7;
          parseptr_read = strchr(parseptr_read, ',') + 1;
          char *token = strtok_r(parseptr_read, ",", &brkb);
          int value = atol(token);

          send_serial("AT+CMGF=1");
          delay(50);
          Serial1.print("AT+CMGR=");
          Serial1.println(value);
        }


        if (strncmp(ReadSerial, "CMGR:",5) == 0){
          char *parseptr_read = ReadSerial+6;
          parseptr_read = strchr(parseptr_read, ',') + 2;
          //sms_number = strtok_r(parseptr_read, "\"", &brkb);
          //Serial.println(sms_number);

          int cou=0;
          int cou1 = 0;

          int x = 0;
          unsigned long milliSMS = millis();
          while(x < 20 && millis() <= (milliSMS + 200)){
            sms_number[x] = 0;
            x++;
          }

          milliSMS = millis();

          while(parseptr_read[cou1] != '"' && millis() <= (milliSMS + 1000)){
            if(parseptr_read[cou1] == '+'){
              sms_number[cou] = '0';
              cou++;
              sms_number[cou] = '0';
            }
            else{
              sms_number[cou] = parseptr_read[cou1];
            }
            cou++;
            cou1++;
          }
          if(debug > 0){
            Serial.println();
            Serial.print("-> SMS from: ");
            Serial.println(sms_number);
          }
        }

        if (strncmp(ReadSerial, "NORMAL POWER DOWN",17) == 0) {
          Serial.println("-> GSM OFF");
        }

        if (strncmp(ReadSerial, "+CFUN: 1",8) == 0) {
        }

        if (strncmp(ReadSerial, "Call Ready",10) == 0) {
        } 

        if (strncmp(ReadSerial, "0",1) == 0){
          if(debug > 0)
            Serial.println("-> OK");
          if(val == 1)
            sms_send_best = 1;
        }
        if (strncmp(ReadSerial, "+CRING:",7) == 0 && calling < 1){
          if(debug > 0)
            Serial.println("-> ding dong");
        }

        if (strncmp(ReadSerial, "+CMS ERROR: 515",15) == 0){
          if(debug > 0)
            Serial.println("-> PS Busy....");
        }


        if (strncmp(ReadSerial, "+CLIP:",6) == 0){
          char *parseptr_read = ReadSerial+8;
          int cou=0;
          unsigned long milliSMS = millis();
          while(parseptr_read[cou] != '"' && millis() <= (milliSMS + 200)){
            calling_number[cou] = parseptr_read[cou];
            cou++;
          }
          if (calling == n_of_calling){
            send_serial("ATH");
            calling = 0;
            sms_senden = 2;
          }
          else{
            calling++;
          }
        }

        if (strncmp(ReadSerial, "3",1) == 0){
          Serial.println("-> NO CARRIER");
          calling = 0;
        }
        if (strncmp(ReadSerial, "4",1) == 0){
          Serial.println("-> ERROR");
        }
        if (strncmp(ReadSerial, "6",1) == 0){
          Serial.println("-> NO DIALTONE");
        }
        if (strncmp(ReadSerial, "7",1) == 0){
          Serial.println("-> BUSY");
        }
        if (strncmp(ReadSerial, "8",1) == 0){
          Serial.println("-> CONNECT OK / NO ANSWER");
        }

        for(int a=0; a<=counter; a++){
          ReadSerial[a]=0;
        }
        counter=0;
      }
      else{
        counter++;
        if (counter == (BUFFSIZ-1)){
          counter = 0;
          break;
        }
      }
    }
  }
}

maybe there is a better way…
The “ReadSerial” variable is a 120 Char so it might be too big…

GekoCH:
maybe there is a better way…

Almost certainly. I got confused looking at that, and I imagine you are too. How about first just reading the data into a buffer without trying to decode it? You are doing strcmp, but I don’t see any attempt to put a null-terminator in the buffer, so the compares will fail straight away.

And just explain this bit please?

          int x = 0;
          unsigned long milliSMS = millis();
          while(x < 20 && millis() <= (milliSMS + 200)){
            sms_number[x] = 0;
            x++;
          }

You are trying to fill a variable called sms_number with zeroes, but you want to make sure that the code doesn’t take more than 200 mS doing it? Why?

Hmm but I do read first the data into a buffer until a new line “\r” does show up. This gets then parsed by the code.

There is a mistake with the while(x < 20 && millis() <= (milliSMS + 200)) this routine is just to clear the buffer of
sms_number to store the new number. Actually I don’t need this one because it gets overwritten by the new number…

by the way the parsing works I can decode those message with this code…

Here's how you crash an Arduino.

char myBuffer[17] = "----------------";
char happyFace[] = ":-) ";
void loop() {
  static int bufPos; // static is only initialized once, so we don't clobber it every loop.
  strcpy(myBuffer+bufPos,happyFace); // copy the happyFace string (up to the terminating 0x00 at the end) into myBuffer, at offset bufPos
  lcd.clear(); // wipe the screen
  lcd.print(myBuffer); // print myBuffer - that is, display characters from myBuffer until a 0x00 is reached.
  bufPos += strlen(happyFace); // add the string length of happyFace (4 bytes here), excluding the 0x00, to the bufPos.
  delay(500); // wait half a second
}

Looks innocent, right? Uses a buffer to employ "appending" a string onto another string, through use of a buffer-counter (I guess I could use a *pointer, but my in-head compiler doesn't utilize that yet ;)). So every loop, you'll have another smiley on the screen. hehe, cute.

Except that... once you reach the end of the available space... the program compiled, right? It does just what it's told... it just keeps on truckin'. It's only 17 characters long, but bufPos is an int, so it's allowed to run off into oblivion, +22, +36, +59... and it'll still write it there. Oops. So if you happen to be writing to an out-of-range buffer pointer, you start clobbering over unpredictable memory areas, many of which are in use around it (holding counters, variables, etc). Happy face bunny starts going Godzilla on the memory map. Guess what? Program crashes... at first the program will behave erratically, storing bogus values in your log or jumping to random places in the code. Then, once it finally finds an infinite loop to cozily settle into (like a while() loop that never ends), it'll "crash".

That code is too confusing for me to look over right now, but I just wanted to point this buffer issue out, since I saw a lot of pointers, pointer-addition, pointer-assignment, etc., going on in there. Quite possible that your buffers are just getting scrambled up with out-of-range addresses...

Thx for the explenation. Thats why I use:

counter++;
        if (counter == (BUFFSIZ-1)){
          counter = 0;
          break;
        }

so if counter for the buffer is equal to the BUFFSIZ, the counter value gets back to 0 and the buffer won't get over its edge. The Message in the buffer will be worthless but in general i do send just SMS with 10 characters to the Arduino so every other SMS it gets will be rejected....

But can someone tell me how to parse the Information from a GSM Module. Not every sentence will start with a $ sign like the GPS they are different. Sometimes they start with "+" or "/n" or even "*"....

I had the right idea back there, I think.

Build up the buffer first in a simple, clear, easy-to-understand function. Then analyze it. Your code is so confusing with flags, numbers, tests, etc. that I can’t say whether or not it will work, or crash, or anything.

Don’t try to do everything (build buffer, analyze, handle overflow etc.) in one long piece of confusing code. It might be OK from your point of view if it works, but you have said it doesn’t.