Arduino sketch randomly not responding in the middle of running?

Hello all,

I've been having a very bizarre issue with a project of mine that for the life of me I cannot figure out.

I'm using an Arduino Uno R3 on IDE 1.6.7 to read from a photocell and manipulate mini servos based on the readouts from the photocell (essentially, it automates shiny Pokémon hunting on a 3DS). In an effort to keep this accessible for those who don't play Pokémon, I will try to keep this limited to just the functions and circuitry related to the arduino and not what it is making the game do.

The servos are utilized in sequence, attaching one servo, writing positions to it to press a button on the 3DS, and then detaching the servo (this was originally for the purpose of not drawing too high mA at once from the board, but now the servos are powered via 5v wall wart, meaning that the only connections the servos have to the board are through the connected grounds of the wall wart and the arduino and the PWM pins used to control them).

The sketch manipulates two servos (alternating pressing the up and down buttons on 3DS) in sequence until the bottom screen goes dark (indicating a battle is starting in-game), in which case it measures starting from when the screen goes dark to when it becomes light again and, based on how long the screen was dark for (using the values given from the photocell), either terminates the sequence, or presses a few buttons using other servos to end the battle in-game and restart the sequence.

The issue I'm having is that for literally no discernible reason whatsoever, the sequence will just randomly stop- the cycle will run anywhere from 3-25 times without any issue whatsoever, then will simply just bail on it.
I very highly doubt it is a memory issue, as I have similar sketches with way more variables (both globally and locally) and overall sketch size that run just fine (in fact, this sketch is just an isolated part of a much larger master sketch containing other similar modes that also happen to run just fine).
Serial is still active and connected when this happens, as I am able to run other functions as well as restart this one, and see the serial readouts that happen when said functions are run (though when this sequence randomly decides to end, the serial readouts from that point in the cycle are not shown).
I thought it must have been a power issue even though I was only running one mini servo at a time, but now that I've been powering the servos via 5v (0.7 A) wall wart and am still only actually powering one servo at any given time, I'm absolutely clueless as to what this might be.
Previous to the addition of the wall wart, I found that disabling the functions I use to hold (as opposed to simply pressing) the buttons down increased the life of the sketch somewhat, but I would still eventually come back to find the same crash later.

Link to my code:

Hopefully it isn't too messy or too much, and I will try to trim it down further to make it more readable, but I perfectly understand if it is too much of a pain to look through. I just don't have a clue what's going on or where else to turn for answers :-[

Edit: If it would be helpful, I can post a video of it in action (which hopefully would help pinpoint where the issue is).

When it "crashes" or "stops responding", is the Arduino going through a reset sequence (as if the reset button was pressed), re-running setup() etc. or is it simply hanging for a period ?

Statements like while here in your code may cause hangs:

unsigned long blackScreen()
{
  int photocellValue = analogRead(0);
  while (photocellValue <= 100)
  {
    photocellValue = analogRead(0);
  }
  time2 = millis();
  return time2 - time1;
}

Link to my code:
#include <Servo.h>Servo servo1a, servo2x, servo3r, servo4d, servo5u, servo - Pastebin.com

Why did you put your code in the rubbish bin? Surely you don't expect us to be reaching in the rubbish bin to get your code.

Use Reply, not the Quick Reply field, and use the Additional Options link (yeah, I know, it doesn't look like a link; not my idea to use this crappy design) to attach your code HERE.

+1
If you post properly, I might look at it.

@6v6gt: In truth, I have no idea. it doesn't seem to be resetting or running setup again (as the sketch prints multiple lines to serial from void setup() ), the sequence appears to just randomly stop looping. It would seem as though it is hanging, but indefinitely rather than for a short time. The puzzling thing is that I have another piece of code that is extremely similar all-around that uses the exact same BlackScreen function in the same way, and it runs without any issues whatsoever.

@PaulS @aarg : Oh. My bad. Insert forum noob excuse here.

Pasting my code using them there fancy code tags causes me to exceed char limit tho. What do?

Edit: attached as .ino, hopefully this works.
Edit2: Not that it really helps anything, but I did just barely purchase an Arduino Leonardo and the issues persist.

wild-only-debug.ino (9.97 KB)

I suggest that you add a number of Serial.print statements everywhere so you can see the flow of the program.

e.g.

void wpCheckScreen()
{
  int photocellValue = analogRead(0);
  Serial.print("wpCheckScreen -> photocellValue: "); Serial.println(photocellValue);
  if (photocellValue <= 100)
  {
    Serial.print("wpCheckScreen -> photocellValue lte 100");
    ...
    ...

Where lte stands for less-than-or-equal-to :wink:

As rubbish bins go, yours was pretty good. I could at least read it on an iPad with Safari. Not, however, the .ino attachment. But anyway.

If the Arduino goes through a reset cycle, you'll see that the pin13 led flashes.

You also said this:

I very highly doubt it is a memory issue, as I have similar sketches with way more variables (both globally and locally) and overall sketch size that run just fine (in fact, this sketch is just an isolated part of a much larger master sketch containing other similar modes that also happen to run just fine).

The compiler tells you what resources your program consumes e.g. :

Sketch uses 5,566 bytes (18%) of program storage space. Maximum is 30,720 bytes.
Global variables use 371 bytes (18%) of dynamic memory, leaving 1,677 bytes for local variables. Maximum is 2,048 bytes.

You have a large number of strings, particularly in your parameters for Serial.print(). If you are running out of RAM., you can use the F() macro to move such strings out of RAM into the program memory. Below is an example using F(), which also throws out a warning if the program is stuck in an infinite loop, but limited to one warning every 10,000 iterations:

unsigned long blackScreen()
{
  long lCount = 0 ;
  int photocellValue = analogRead(0);
  while (photocellValue <= 100)
  {
    if ( (++lCount) % 10000 == 0 ) Serial.println (F("in blackScreen 10,000 iteratations" )) ;
    photocellValue = analogRead(0);
  }
  time2 = millis();
  return time2 - time1;
}
const byte pin3 = 3;
const byte pin5 = 5;
const byte pin6 = 6;
const byte pin9 = 9;
const byte pin10 = 10;
const byte pin11 = 11;

Seeing pin11 in the code is no better than seeing 11 in the code. There is something attached to the pin. The name of the variable should reflect what is attached to the pin, NOT the value that is stored in the variable.

unsigned long time1, time2, longestTime, initTime, runningTime;

Something happened at time1. The name should reflect what happened, not just the fact that the value is related to time.

void hitA()
{
  servo1a.attach(pin3);
  servo1a.write(30);
  delay(175);
  servo1a.write(0);
  delay(300);
  servo1a.detach();
}

Why do you keep attaching and detaching the servos? Attach them in setup() and leave them attached!

sterretje:
I suggest that you add a number of Serial.print statements everywhere so you can see the flow of the program.

e.g.

void wpCheckScreen()

{
 int photocellValue = analogRead(0);
 Serial.print("wpCheckScreen -> photocellValue: "); Serial.println(photocellValue);
 if (photocellValue <= 100)
 {
   Serial.print("wpCheckScreen -> photocellValue lte 100");
   ...
   ...



Where *lte* stands for less-than-or-equal-to ;)

Okay, thank you, I will add this.

6v6gt:
You have a large number of strings, particularly in your parameters for Serial.print(). If you are running out of RAM., you can use the F() macro to move such strings out of RAM into the program memory. Below is an example using F(), which also throws out a warning if the program is stuck in an infinite loop, but limited to one warning every 10,000 iterations:

unsigned long blackScreen()

{
 long lCount = 0 ;
 int photocellValue = analogRead(0);
 while (photocellValue <= 100)
 {
   if ( (++lCount) % 10000 == 0 ) Serial.println (F("in blackScreen 10,000 iteratations" )) ;
   photocellValue = analogRead(0);
 }
 time2 = millis();
 return time2 - time1;
}

This is a great idea, thank you. I will implement it and update with how it goes.

PaulS:
Seeing pin11 in the code is no better than seeing 11 in the code. There is something attached to the pin. The name of the variable should reflect what is attached to the pin, NOT the value that is stored in the variable.

If you can't tell, I'm still very new to all this, so that was something leftover when I was trying to figure out how this whole thing worked. Thanks for the tip though.

PaulS:
Something happened at time1. The name should reflect what happened, not just the fact that the value is related to time.

Same thing here. Tbh, I pretty much just adapted that function from another piece of code I found and forgot about it since it hasn't given me any problems.

PaulS:
Why do you keep attaching and detaching the servos? Attach them in setup() and leave them attached!

I originally did this as a cautionary measure. I thought that having 5 idling servos + one active servo all being powered at once would draw too much power because my wall wart is only rated at 0.7A and I have no idea how much the servos draw at peak (or while idling), although like I said, I barely have any clue what I'm doing here so it could just as easily be fine. It certainly did cause issues while I was powering it with just the board, but then again, you're only supposed to draw 20 mA per pin or whatever it is.

Edit: So I've done some testing, and it hung a few times in a row right after it set wpProceed to true (as indicated by a Serial.println I added there). Suspecting it might have been an issue with delay after wpRetry runs (as the 3DS screen goes black for a short time at this point in the sequence), I added a 1 second delay to the beginning of 'void wpEncounter()', which thus far has prevented hanging at that specific point. I added the edits to blackScreen, still seems to run just fine- it prints the message 2-3 times and then the screen goes light again, at which point it triggers wpRetry and continues as normal. When it hangs, it seems as though blackScreen is never actually being triggered (as no "in blackScreen 10,000 iterations" appear). Specifically, it will repeat the holdUp and holdDown functions until the screen goes dark (as normal), but then blackScreen is never triggered.
I added this:

else 
  {
    Serial.println("Screen blackout not detected.");
    sadbuzzer();
  }

To the end of wpCheckScreen to test if perhaps it wasn't seeing the photocell drop below 100, and it didn't trigger when it hung (though I'm not sure this would be an effective test anyway).
It still seems to be occurring at random times (between 3 and 25 cycles, though one attempt reached 55). Sorry for the monstrous post lol.

I thought that having 5 idling servos + one active servo all being powered at once would draw too much power because my wall wart is only rated at 0.7A and I have no idea how much the servos draw at peak (or while idling)

First, you need to learn how much current they draw. In the absence of any data to the contrary, figure 1 Amp per servo.

If that is the (likely) case, a 700 mA power supply is completely inadequate. Get a 3 Amp (or more) supply, and leave the servos attached (they use a lot less current holding a position than they do moving to a position).

You changed your code. It did not solve the problem. You need to post the modified code, so we are all working on the same page.

I can only think of a few more things to look at:
When it goes into this 'hung' state, can you enter input into the serial console ?
Does it make a difference if you (a) shine a light on or (b) cover the light sensors when it is in this state ?
Have you a debug Serial.println statement before the last '}' in function loop() ?

PaulS:
You changed your code. It did not solve the problem. You need to post the modified code, so we are all working on the same page.

Oops. Forgot to attach new code lol. I'll attach it to this one

6v6gt:
When it goes into this 'hung' state, can you enter input into the serial console ?

Yes, I can, which is why this is so completely baffling to me.

6v6gt:
Does it make a difference if you (a) shine a light on or (b) cover the light sensors when it is in this state ?

I'll do more testing to confirm, but I've tried a few times and it hasn't seemed to.

6v6gt:
Have you a debug Serial.println statement before the last '}' in function loop() ?

Added it, still prints the message repeatedly when it hangs.

wild-only-debug-edited.ino (10.3 KB)

Added it, still prints the message repeatedly when it hangs

So, it is not hanging completely, it is In a continuous loop.
You should now print out the values of some loop control variables to help understand why.

Edit:

You could also improve your existing debug messages to help pinpoint why/where it is getting stuck in a loop. For example, here by adding a debug statement immediately it enters a routine:

void wpCheckScreen()
{
  Serial.println("Entering wpCheckScreen() "); 
  delay(500);
  int photocellValue = analogRead(0);
  if (photocellValue <= 100)
  . . .
  . . .
}

or even better, also print out a few important variables which determine the paths through the routine:

void wpCheckScreen()
{
  Serial.print("Entering wpCheckScreen(). photocell A0 = "); 
  Serial.println( analogRead(0) ) ;
  delay(500);
  int photocellValue = analogRead(0);
  if (photocellValue <= 100)
  . . .
  . . .
}

Your debug statement at the end of the loop() could also be expanded:

. . . 
. . .
      wpRetry = false;
      wpProceed = true;
      Serial.println("Next encounter!");
    }
    delay(1250);
  }
  Serial.println("Looped.  wpCS:" );
  Serial.print(wpCS) ;
  Serial.print("; wpRetry:" );
  Serial.print(wpRetry) ;
  Serial.print("; wpProceed:" );
  Serial.println(wpProceed) ;
}

@6v6gt This is all excellent. I will add this and update with how it goes.

Edit: Okay. So, I added both of @6v6gt's suggestions, as well as adding the serial prints of the wp____ booleans to the areas of the code in which they are changed/triggered.

Here's what I've found.

Somehow, void wpEncounter() (triggered by boolean wpProceed) isn't triggering wpCS despite having detected that the photocell has dropped below 100. That, or it is turning it back off before it would be able to tun, although I don't understand why it's happening either way.

Here's what the serial monitor looks like when the hang occurs:

----------------------------------- ***<--- beginning of normal cycle***
wpCS:
0; wpRetry:1; wpProceed:0
Next encounter!
Looped.  wpCS:
0; wpRetry:0; wpProceed:1
wpCS:
1; wpRetry:0; wpProceed:0
Entering wpCheckScreen(). photocell A0 = 42
Running for 3 min. (204 sec.)
10,000 blackScreen loops.
10,000 blackScreen loops.
10,000 blackScreen loops.
Screen blackout time: 10777 ms.
Longest screen blackout: 11071 ms.
Wild Encounters: 9
----------------------------------- ***<--- end of normal cycle***
wpCS:
0; wpRetry:1; wpProceed:0
Next encounter!
Looped.  wpCS:
0; wpRetry:0; wpProceed:1
wpCS:
0; wpRetry:0; wpProceed:0  ***<--- Hang has occurred***
Looped.  wpCS:
0; wpRetry:0; wpProceed:0
Looped.  wpCS:
0; wpRetry:0; wpProceed:0
Looped.  wpCS:
0; wpRetry:0; wpProceed:0

. . .

. . .

The only thing I can think of is that the <= 100 value might be too strict, even though the other code I have works fine with this parameter and wpEncounter exits successfully under this parameter (which pretty much means that isn't the reason). Any ideas?

Once again, code (with debug prints) is attached to this post.

wild-only-debug-edited.ino (11.6 KB)

Sorry for double post, but I wanna bump this (hopefully not some grave offense but I don't think anyone saw my edit :frowning: )

Some more things I've tried:

Covering/shining a light on the photocell doesn't seem to make a difference (as I expected).

I tried changing 100 to 125 and it made no difference so I changed it back.

Beyond that, though, I'm pretty much out of ideas other than that I guess I'll try having a serial print of the photocell value everywhere that it is used and see what crops up.

If wpEncounter() is entered when analogRead(0) <= 100, nothing happens so wpCS remains false.
Therefore, your loop just continues endlessly and wpEncounter() is never called again (to possibly correct the situation).

Thanks for your response.

Hopefully I am understanding what you're saying correctly. But the issue is not that wpEncounter() is not being run- the hang occurs right as wpEncounter should trigger wpCS in:

if (analogRead(0) < 125)
    {
      wpProceed = false;
      wpCS = true;
      wpTimeout = 0;
      wpTimeoutCheck = 0;
      break;
    }

Additionally, I've made sure that wpEncounter() is never run until the photocell reads well above 200.

One thing I noticed, all your debug statements are identical because they are cut and pasted into several different places. So although the values are printed out, there is no clue as to which part of the program generated it. You should fix that and post a new debug dump.

I believe the code in post #16 is new code since you posted a full sketch in post #13, but anyway it looks like a modification of this :

    if (analogRead(0) < 100)
    {
      wpProceed = false;
      wpCS = true;
      time3 = 0;
      time4 = 0;
      break;
      // for debugging
      . . .

This code will never be executed if the call to wpEncounter() is made when analogRead(0) is less than (or equal to) 100. This is because the code above is in a while loop, where the loop condition is while (analogRead(0) > 100) .
Therefore, the sketch will loop continuously because wpProceed, wpCS, and wpRetry are all false.

I suggest you add the following lines to the top of wpEncounter() and you will (almost certainly) see that the infinte loop (hang) occurs when wpEncounter() is called when the value of analogRead(0) is less than 100.

Serial.print("Entering wpEncounter(). photocell A0 = ");
Serial.println( analogRead(0) ) ;

Whats all the confused code around time3 and time4? That will start the sketch behaving differently
after 300 seconds of running. time3 is sometimes set to 0, sometimes to millis(), ditto for time4.