Variable Freakout! 0 isn't less than 1,000?

I’m having the weirdest problem with this program, and it’s extremely intermittent. So, I wrote a program to time how long it takes between the Arduino setting a super pin 13 LED and the human smashing down on a large pulled-down microswitch. Sort of a response timer, if you will, actually for a small-scale study I’m doing. The communication protocol is that, in the setup() section, it spits out a “124”. When you press the pin 2 switch, the LED blinks 3 times and spits out “246” a second later. It then waits a pseudo-random amount from 2,000 to 10,000 milliseconds. After it’s up, interrupt 0 (pin 2, the switch) is set to trigger stopTimer on RISING. stopTimer does one thing: sets killLoop to true. The while loop that has, in the meantime, been incrementing cyclesGlobal once per millisecond, on the condition that cyclesGlobal < 1000 && killLoop != true, meaning that pressing the switch kills the loop. After the loop either times out or is killed, it does a phoneHome() sending a “135” to serial then reading out cyclesGlobal. It runs a cleanup() function which resets all the variables and detaches the interrupt. You can then press the switch again and restart the test. This is where things get weird. It spits a zero for a response time and completely skips the while loop. A debug if checking on the same things as the loop runs, and it starts to tell me that an int at 0 is not < 1000. I’ve used both the Arduino IDE and HyperTerminal to listen to the serial (tempted to say cereal). Interestingly enough, it seems to reset upon connecting either monitor, proven by seeing a 124. I’ve even tried to force a reset through the program by jumpering pin 4 and RESET then trying different HIGH/LOW combinations. It would either constantly reset, stay in a reset, or not reset when I wanted. Lovely. Any ideas? Thanks so much for listening to my noobdom. I’ll post the code here (sorry, no nice colored formatting):

int lightPin = 13;
int buttonPin = 2;
int resetPin = 4;
static int cyclesGlobal = 0;
boolean isTesting = false;
boolean killLoop = false;
void setup()
{
pinMode(lightPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(resetPin, OUTPUT);
digitalWrite(resetPin, HIGH);
Serial.begin(9600);
Serial.println(124, DEC);
}
void reset()
{
digitalWrite(resetPin, LOW);
digitalWrite(resetPin, HIGH);
}
void erraticSignal()
{
digitalWrite(lightPin, HIGH);
delay(200);
digitalWrite(lightPin, LOW);
delay(100);
digitalWrite(lightPin, HIGH);
delay(200);
digitalWrite(lightPin, LOW);
delay(100);
digitalWrite(lightPin, HIGH);
delay(200);
digitalWrite(lightPin, LOW);
delay(1000);
}
void alertStart()
{
Serial.println(246, DEC);
}
void lightOn()
{
digitalWrite(lightPin, HIGH);
}
void lightOff()
{
digitalWrite(lightPin, LOW);
}
void startTiming()
{
delay(200);
while(cyclesGlobal < 10000 && killLoop != true)
{
delay(1);
cyclesGlobal++;
}
phoneHome();
lightOff();
cleanup();
}

void phoneHome()
{

Serial.print(135, DEC);
Serial.println();
delay(100);
Serial.println(cyclesGlobal);
delay(1000);
}
void stopTimer()
{
killLoop = true;
}
void cleanup()
{
lightOff();
detachInterrupt(0);
cyclesGlobal = 0;
isTesting = false;
killLoop = false;
reset();
}
void spill()
{
//debug
/* Serial.println("Now spilling the beans...");
delay(200);
Serial.print("lightPin: ");
delay(200);
Serial.println(lightPin);
delay(200);
Serial.print("buttonPin: ");
delay(200);
Serial.println(buttonPin);
delay(200);
Serial.print("cyclesGlobal: ");
delay(200);
Serial.println(cyclesGlobal);
delay(200);
Serial.print("isTesting: ");
delay(200);
Serial.println(int(isTesting));
delay(200); */
Serial.print("killLoop: ");
delay(200);
Serial.println(long(killLoop));
delay(200);
}
void startTesting()
{

isTesting = true;


startWaiting();

attachInterrupt(0, stopTimer, RISING);
lightOn();
startTiming();
}
void startWaiting()
{
delay(random(2000, 10000));
}
void loop()
{
if (digitalRead(buttonPin) == HIGH)
{
if (isTesting != true)
{
erraticSignal();
alertStart();
startTesting();
}
}
}

/me

I'll post the code here (sorry, no nice colored formatting):

Well, surround it in [code]...[/code] tags or use the Arduino "copy for forum" menu command.

Just a guess, but you should use the volatile keyword on variables you expect some ISR to change behind your back. Or perhaps the variable is wrapping in value. Are you printing the value when you think it's not behaving?

Thanks for the tip. I'll try using [code] next time. What's an ISR? Also, I don't actually have the pde and project with me at the moment. Oh, and volatile seems promising. Perhaps the interrupt is messing with something?

On first reading, I thought you were updating the variable cyclesGlobal from your ISR (interrupt service routine, stopTimer()) but that’s not the case.

It just occurred to me, I am however updating killLoop from the ISR. What would declaring that volatile do?

Basically, a C compiler can do a lot of optimizations if it thinks it can guess how your program is behaving.

If you write a tight loop that uses a variable, but there's no code inside that loop that is changing that variable, the C compiler will think it's irrelevant and output machine instructions that don't even pay attention to the variable. The code is smaller and it behaves the same (unless you really ARE changing the variable somehow).

If you add the volatile keyword to the variable's declaration, the C compiler knows that it can't make such tricky optimizations. It has to assume that every time you mention the variable, it must actually load up the variable's value afresh. If it must load it afresh on every loop, then it must also check the value of it, and thus, it behaves correctly even if the ISR changes the variable magically in the middle of the loop. It runs slightly slower, but correctly, which is more important.

The only times you should consider volatile are when: another thread or ISR can change it behind your back, it represents input hardware registers that can change at any time, and so on. It's useless and counterproductive for normal variables.