Making arduino execute functions based on real-time changes, without a laptop

I written a program in which a series of actions will be triggered if the difference between “newValue” and “oldValue” is greater than x.
oldValue and newValue are both being printed on the Serial Monitor in real-time, and newValue will increase as an object moves closer to a sensor connected to the arduino (it’s basically a proximity detector). oldValue reads and takes on the value of newValue every 200 ms.

The program runs fine if the arduino IDE and the Serial Monitor are open on the laptop, however once I close the Serial Monitor, the TX light on the arduino will no longer flash and the program will seem to stop working after a while – it will not execute said series of actions even as I move an object closer to the sensor, i.e. what normally triggers the sensor when the Serial Monitor is open does not work when the Serial Monitor is closed. Any idea why this happens, and how do I fix it?

Any help would be greatly appreciated. Thanks!

Code for reference

#include <LiquidCrystal.h>
#include <elapsedMillis.h>
#include <CapacitiveSensor.h>


// == Capacitive Sensor Framework ==
CapacitiveSensor capSensor_12_13 = CapacitiveSensor(12,13);
elapsedMillis CapStimer;
#define CapSinterval 2000
long oldValue;
long newValue;

const int numReadings = 10;
int readings[numReadings];
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int storedValue;


// == LCD Framework ==
LiquidCrystal lcd(10,9,8,7,6,5);


// == LED Framework ==
const int LEDPin = A2;
elapsedMillis timerLED;               //measures duration of LED state
#define intervalLED1 500             //how long LED is on/off
#define intervalLED2 100


// == Music Framework ==
const int SpeakerPin = 11;
int note;               // to indicate which note is being played. Value of 0 rep first note
int note2;
elapsedMillis timerMUSIC;             //measures how long the sound has been playing
#define intervalMUSIC1 500            //how long the freq is played
#define intervalMUSIC2 100


// == Tri-colour LED Framework ==
const int ledPinR = 4;
const int ledPinG = 3;
const int ledPinB = 2;
int brightR;
int brightG;
int brightB;
int triLEDrepeat;
elapsedMillis timerTriLED;
#define intervalTriLED 50


// == Tilt Sensor Framework ==
int currentState = LOW;
int previousState = LOW;
int count = 0;
int TSPin = A0;


// == Timer Framework ==
elapsedMillis timerAlarm;
elapsedMillis timerAlarm2;

//____________________________________________________________________________________


void setup() {
  Serial.begin(9600);

  // ~~ LCD Set-up ~~
  lcd.begin(16,2);
  lcd.print("Object secure");

    
  // ~~ LED Set-up ~~
  pinMode(LEDPin, OUTPUT);
  digitalWrite(LEDPin, LOW);
  timerLED = 0;


  // ~~ Music Set-up ~~
  timerMUSIC = 0;
  note = 0;
  note2 = 0;


  // ~~ Tri-colour LED Set-up ~~
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinG, OUTPUT);
  pinMode(ledPinB, OUTPUT);


  // ~~ Tilt Sensor Set-up ~~
  pinMode(TSPin, INPUT);
  timerAlarm = 0;
  timerAlarm2 = 0;

}   // END SET-UP

//____________________________________________________________________________________


void loop() {
  // Finding Average CapSensor Reading:
  total = total - readings[readIndex];                         // subtract the last reading
  readings[readIndex] = capSensor_12_13.capacitiveSensor(30); // read from the sensor
  total = total + readings[readIndex];                       // add the reading to the total
  readIndex = readIndex + 1;                                // advance to the next position in the array
  if (readIndex >= numReadings) {                          // if the end of the array is reached,
    readIndex = 0; }                                      // wrap around to the beginning:
  average = total / numReadings;                         // calculate the average:
 
  newValue = average;
  if (CapStimer > CapSinterval) {             // records new values
    CapStimer -= CapSinterval;               // every x ms
    oldValue = average;
 }
  Serial.println(oldValue);
  Serial.print("\t");
  Serial.println(newValue);
 

  //  C A P A C I T I V E  S E N S O R
  if ( ((millis()) >= 5000) &&  ((newValue - oldValue) >= 25) ){
    timerLED = 0;
    timerMUSIC = 0;    
    timerAlarm = 0;
    timerAlarm2 = 0;
    timerTriLED = 0;
    
    // When object touched | LCD
    lcd.home();
    lcd.print("WARNING:        ");
    lcd.setCursor(0,1);
    lcd.print("Intruder Alert! ");

    while (timerAlarm <= 3000) {
    
        // When object touched | LED
        if (timerLED > intervalLED1) {
          timerLED -= intervalLED1;         //reset timer
          digitalWrite(LEDPin, !digitalRead(LEDPin)); }
        
        // When object touched | Music
        switch(note)
        {
        case 0:       //for first note
            tone (SpeakerPin,262,250);
            break;
        case 1:      //for second note
            tone (SpeakerPin,310,250);
            break;
        }
        if (timerMUSIC >= intervalMUSIC1)
        {
           timerMUSIC -= intervalMUSIC1;
           note = !note; }
      
        } // CLOSING "WHILE" FUNCTION
 
    digitalWrite(LEDPin, LOW);
    lcd.clear();
    lcd.home();
    delay(1);
    lcd.print("Intruder alarm");
    lcd.setCursor(0,1);
    lcd.print("was sounded."); }



  //  T I L T  S E N S O R
  currentState = digitalRead(TSPin);
  if ( ((millis()) >= 1000) && (currentState == HIGH) && (previousState == LOW)) {
    count++;
    // Serial.println(count);         // TILT SENSOR COUNTER
    timerLED = 0;
    timerMUSIC = 0;
    timerAlarm = 0;
    timerAlarm2 = 0;
    timerTriLED = 0;

    while (timerAlarm2 <= 5000) {
    
      // When object moved | LCD    
      lcd.home();
      lcd.print("WARNING!!!      ");
      lcd.setCursor(0,1);
      lcd.print("Object stolen!! ");

      // When object moved | LED
      if (timerLED > intervalLED2) {
        timerLED -= intervalLED2;
        digitalWrite(LEDPin, !digitalRead(LEDPin)); }

      // When object moved | Music
      switch(note2) {
        case 0:
          tone (SpeakerPin, 3000,250);
          break;
        case 1:
          tone (SpeakerPin, 2000, 250);
          break;
      }
      if (timerMUSIC >= intervalMUSIC2) {
        timerMUSIC -= intervalMUSIC2;
        note2 = !note2;
      }


    // When object moved | Tri-colour LED
      brightR=random(2);
      brightG=random(2);
      brightB=random(2);
      if (timerTriLED >= intervalTriLED)
      {
        timerTriLED -= intervalTriLED;
        digitalWrite(ledPinR, brightR);
        digitalWrite(ledPinG, brightG);
        digitalWrite(ledPinB, brightB);
      }
    

    } // CLOSING "WHILE" LOOP
    digitalWrite(LEDPin, LOW);
    digitalWrite(ledPinR, LOW);
    digitalWrite(ledPinG, LOW);
    digitalWrite(ledPinB, LOW);
    lcd.clear();
    lcd.home();
    lcd.print("WARNING: OBJECT");
    lcd.setCursor(0,1);
    lcd.print("WAS STOLEN!!");
    delay(100);
  } // CLOSING "IF" FUNCTION

  previousState = currentState;
  delay(50);


}   // END LOOP

Randomystick: and the program will seem to stop working after a while

That's probably a clue.

You only have a couple of Serial.print()s in that code. Comment them and Serial.begin() out. See if the behavior changes.

if ( ((millis()) >= 1000)....

This will only be false for one second after the Arduino is switched on or reset and will then be true for the next ~49 days. It will then be false for 1 second every ~49 days. I don't think that's what you intended.

[quote author=James C4S link=msg=2531971 date=1450812230] That's probably a clue.

You only have a couple of Serial.print()s in that code. Comment them and Serial.begin() out. See if the behavior changes. [/quote]

That seemed to do the trick. :) Granted, I can't see the values of oldValue and newValue anymore, but it works perfectly fine now, even without the arduino IDE open. Thank you so much! :D

Also, I really appreciate your blog, baldengineer.com. It's informative, well-written and very easy to understand. :) It was where I learnt how to replace all my delay()s with millis() and it helped me a lot. Thanks!

Henry_Best: This will only be false for one second after the Arduino is switched on or reset and will then be true for the next ~49 days. It will then be false for 1 second every ~49 days. I don't think that's what you intended.

That was actually what I intended it to do. For some unknown reason, the currentState = HIGH && previousState == LOW condition will be fulfilled in the instant where the code is uploaded onto the arduino board, triggering a false alarm. I put that in as a buffer for the circuit to "stabilise" itself out so that it doesn't ring the moment the upload is complete.

Randomystick: That seemed to do the trick. :) Granted, I can't see the values of oldValue and newValue anymore, but it works perfectly fine now, even without the arduino IDE open. Thank you so much! :D

Hmm... that wasn't my intended outcome. ;) Are you using a Leonardo?

Randomystick: Also, I really appreciate your blog, baldengineer.com. It's informative, well-written and very easy to understand. :) It was where I learnt how to replace all my delay()s with millis() and it helped me a lot. Thanks!

Cool, you're welcome.

Randomystick: That was actually what I intended it to do. For some unknown reason, the currentState = HIGH && previousState == LOW condition will be fulfilled in the instant where the code is uploaded

Well, you don't know for certain it was the "instant code is uploaded." However, it was happening before you wanted it to, for seemingly unknown reasons.

You have defined the internal pull-up resistors in your code. Based on your logic, are you using external pull-down resistors ?

If not, I wouldn't be surprised if you're having seemingly random events occur...