switch case with timer help

Hi

Im making myself a arduino watering system, and i ran into some small problems. the code works just fine and doing what i want. Except one thing, if i want to interupt/stop the current state. How can i do this?

Here is my code

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long time = millis();
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

  recvOneChar();
  controlWater();
}

void recvOneChar() {

  if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

void controlWater() {
  if (newData == true) {

    switch (bluetoothData) {


      case '1': { // Start watering

          digitalWrite(13, HIGH);   // turn the water on
          Serial.println("Start watering");

        }
        break;

      case '2': { //Stop watering
          Serial.println("Stop watering");
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

      case '3': { //Water for 1 hours
          Serial.println("Water for 1 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(3600000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off

        }
        break;

      case '4': { //Water for 2hours
          Serial.println("Water for 2 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(7200000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off

        }
        break;

      case '5': { //Water for 3hours
          Serial.println("Water for 3 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(10800000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

    }
    newData = false;
  }
}

"Except one thing, if i want to interupt/stop the current state."

delay(10800000);

Then don't use delay()

Can you follow this?

/*
  GetRidOfDelay.ino
  LarryD
  Version YY/MM/DD
  1.00    17/02/01  Running code
 
*/
 
//LED wiring:
// +5V---220 ohm resistor---LED anode---LED cathode---Arduino pin
 
const byte heartBeatLED            = 13;    //used to see if the sketch is blocking
const unsigned long heartBeatDelay = 100UL;
const byte myLED                   = 12;    //wired so a LOW turns the LED on
 
//SRAM variables
unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long myLEDmillis;
unsigned long waitTime = 0;
unsigned long currentMicros;
 
byte LEDstate = 0;
 
//                          s e t u p ( )
//**********************************************************************
void setup()
{
  pinMode(heartBeatLED, OUTPUT);
 
  pinMode(myLED, OUTPUT);
  digitalWrite(myLED, HIGH);        //HIGH is LED off
 
} //                 E n d  o f  s e t u p ( )
 
//                          l o o p ( )
//**********************************************************************
void loop()
{
  currentMillis = millis(); //for milli second timing
  currentMicros = micros(); //for mirco second timing
 
  //***************************
  //HeartBeat LED, should toggle every heartBeatDelay milliseconds if code is nonblocking
  if (currentMillis - heartBeatMillis >= heartBeatDelay)
  {
    heartBeatMillis = heartBeatMillis + heartBeatDelay; //reset timing
 
    //Toggle heartBeatLED
    digitalWrite(heartBeatLED, !digitalRead(heartBeatLED));
  }
 
  //***************************
  //swap the comment marks // on the next two lines to see a comparison
 
  //usingDelay();
  usingMillis();
 
 
} //                    E n d  o f  l o o p ( )
 
//======================================================================
//                        F U N C T I O N S
//======================================================================
 
//                     u s i n g D e l a y ( )
//**********************************************************************
void usingDelay()
{
  digitalWrite(myLED, LOW);  //LOW  is LED on
  delay(2000);
  digitalWrite(myLED, HIGH); //HIGH is LED off
  delay(1000);
  digitalWrite(myLED, LOW);  //LOW  is LED on
  delay(500);
  digitalWrite(myLED, HIGH); //HIGH is LED off
  delay(250);
 
}//                E n d  o f  u s i n g D e l a y ( )
 
//                     u s i n g M i l l i s ( )
//**********************************************************************
void usingMillis()
{
  //is it time to process the next state code?
  if (currentMillis - myLEDmillis < waitTime)
  {
    //No, it is not time
    return;
  }
 
  //Yes, it is now time
  myLEDmillis = currentMillis;     //reset timing
 
  //state code
  switch (LEDstate)
  {
    case 0:
      digitalWrite(myLED, LOW);    //turn LED on
      LEDstate = 1;                //next state
      waitTime = 2000UL;           //setup the wait value
      break;
 
    case 1:
      digitalWrite(myLED, HIGH);   //turn LED off
      LEDstate = 2;                //next state
      waitTime = 1000UL;           //setup the wait value
      break;
 
    case 2:
      digitalWrite(myLED, LOW);    //turn LED on
      LEDstate = 3;                //next state      
      waitTime = 500UL;            //setup the wait value
      break;
 
    case 3:
      digitalWrite(myLED, HIGH);   //turn LED off
      LEDstate = 0;                //next state
      waitTime = 250UL;            //setup the wait value
      break;
 
  } //End of switch/case
 
}//                E n d  o f  u s i n g M i l l i s ( )
 
//======================================================================
//                        E N D  O F  C O D E
//======================================================================

.

1 Like

I see an unsigned long time variable declared but not used, did you copy code and then pared it down to reduce functionality and threw in delay yourself?

INTP:
I see an unsigned long time variable declared but not used, did you copy code and then pared it down to reduce functionality and threw in delay yourself?

I tried to use some timers, but i dint get it to work as i wanted. Just forgot to delete it.

larryd:
"Except one thing, if i want to interupt/stop the current state."

delay(10800000);

Then don't use delay()

So something like this? I tried on case 3, just for checking.

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long mywatermillis;
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

  currentMillis = millis(); //for milli second timing
  recvOneChar();
  controlWater();
}

void recvOneChar() {

  if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

void controlWater() {
  if (newData == true) {

    switch (bluetoothData) {


      case '1': { // Start watering

          digitalWrite(13, HIGH);   // turn the water on
          // wait for a second
          Serial.println("Start watering");

        }
        break;

      case '2': { //Stop watering
          Serial.println("Stop watering");
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

      case '3': { //Water for 1 hours

          Serial.println("Water for 1 hours");
          digitalWrite(13, HIGH);   // turn the water on
          //is it time to process the next state code?
          if (currentMillis - mywatermillis < 5000)
          {
            //No, it is not time
            return;
          }

          //Yes, it is now time
          digitalWrite(13, LOW);    // turn the water off
          Serial.println("Done watering");
          mywatermillis = currentMillis;     //reset timing

        }
        break;

      case '4': { //Water for 2hours
          Serial.println("Water for 2 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(7200000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off

        }
        break;

      case '5': { //Water for 3hours
          Serial.println("Water for 3 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(10800000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

    }
    newData = false;
  }
}

You may need to ditch the switch case since you'll need to run condition checks to use timing. I'm not sure what the limitations are within switch case, I could be wrong. But going to if statements might be more intuitive for letting the program loop and check instead of following the case and breaking each time.

To time, you set a variable such as startTime, when the pump turns on, equal to millis() that always returns the current count. Then your program is allowed to run until you interrupt it or if an interval variable such as elapsedTime, which will equal millis() minus startTime exceeds whatever duration you wanted- the number currently in delay.

You are getting close.

Can you follow this part of the sketch?

void usingMillis()
{
  //is it time to process the next state code?
  if (currentMillis - myLEDmillis < waitTime)
  {
    //No, it is not time
    return;
  }
 
  //Yes, it is now time
  myLEDmillis = currentMillis;     //reset timing
 
  //state code
  switch (LEDstate)
  {
    case 0:
      digitalWrite(myLED, LOW);    //turn LED on
      LEDstate = 1;                //next state
      waitTime = 2000UL;           //setup the wait value
      break;
 
    case 1:
      digitalWrite(myLED, HIGH);   //turn LED off
      LEDstate = 2;                //next state
      waitTime = 1000UL;           //setup the wait value
      break;
 
    case 2:
      digitalWrite(myLED, LOW);    //turn LED on
      LEDstate = 3;                //next state      
      waitTime = 500UL;            //setup the wait value
      break;
 
    case 3:
      digitalWrite(myLED, HIGH);   //turn LED off
      LEDstate = 0;                //next state
      waitTime = 250UL;            //setup the wait value
      break;
 
  } //End of switch/case
 
}//                E n d  o f  u s i n g M i l l i s ( )

This should be close:

My mistake, changes coming.

Phone call, I think this will work.

Do you understand how it works?

void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
  }

  //is it time to process the next state code?
  if (currentMillis - myLEDmillis < waitTime)
  {
    //No, it is not time
    return;
  }


  switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Start watering");
        waitTime = 0;
      }
      break;

    case '2':
      {
        //Stop watering
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        waitTime = 0;
      }
      break;

    case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        waitTime = 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on
        //delay(3600000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        //going to stop watering after time out
        bluetoothData = 2;
      }
      break;

    case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on
        //delay(7200000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        //going to stop watering after time out
        bluetoothData = 2;
      }
      break;

    case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);   // turn the water on
        waitTime = 3 * 60 * 60 * 1000ul;
        //delay(10800000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        //going to stop watering after time out
        bluetoothData = 2;
      }
      break;
      
  } //END of switch/case
  
} //END of function

larryd:
"Except one thing, if i want to interupt/stop the current state."

delay(10800000);

Then don't use delay()

So something like this? I tried on case 3, just for checking.

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long mywatermillis;
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

  currentMillis = millis(); //for milli second timing
  recvOneChar();
  controlWater();
}

void recvOneChar() {

  if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

void controlWater() {
  if (newData == true) {

    switch (bluetoothData) {


      case '1': { // Start watering

          digitalWrite(13, HIGH);   // turn the water on
          // wait for a second
          Serial.println("Start watering");

        }
        break;

      case '2': { //Stop watering
          Serial.println("Stop watering");
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

      case '3': { //Water for 1 hours

          Serial.println("Water for 1 hours");
          digitalWrite(13, HIGH);   // turn the water on
          //is it time to process the next state code?
          if (currentMillis - mywatermillis < 5000)
          {
            //No, it is not time
            return;
          }

          //Yes, it is now time
          digitalWrite(13, LOW);    // turn the water off
          Serial.println("Done watering");
          mywatermillis = currentMillis;     //reset timing

        }
        break;

      case '4': { //Water for 2hours
          Serial.println("Water for 2 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(7200000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off

        }
        break;

      case '5': { //Water for 3hours
          Serial.println("Water for 3 hours");
          digitalWrite(13, HIGH);   // turn the water on
          delay(10800000);              // wait for x second
          digitalWrite(13, LOW);    // turn the water off
        }
        break;

    }
    newData = false;
  }
}

larryd:
This should be close:

My mistake, changes coming.

Phone call, I think this will work.

Do you understand how it works?

void controlWater()

{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
  }

//is it time to process the next state code?
  if (currentMillis - myLEDmillis < waitTime)
  {
    //No, it is not time
    return;
  }

switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

digitalWrite(13, HIGH);  // turn the water on
        Serial.println("Start watering");
        waitTime = 0;
      }
      break;

case '2':
      {
        //Stop watering
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        waitTime = 0;
      }
      break;

case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        waitTime = 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);  // turn the water on
        //delay(3600000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

//going to stop watering after time out
        bluetoothData = 2;
      }
      break;

case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);  // turn the water on
        //delay(7200000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

//going to stop watering after time out
        bluetoothData = 2;
      }
      break;

case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);  // turn the water on
        waitTime = 3 * 60 * 60 * 1000ul;
        //delay(10800000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

//going to stop watering after time out
        bluetoothData = 2;
      }
      break;
     
  } //END of switch/case
 
} //END of function

Just tried this, but it does not turn the relayPin of after waitTime.

Just tried this, but it does not turn the relayPin of after waitTime.

How did you test the time out as it is set to 1, 2, 3 hours?

.

larryd:
How did you test the time out as it is set to 1, 2, 3 hours?

.

Just changed it to 10sec

Please show us your current sketch.

.

larryd:
Please show us your current sketch.

.

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myLEDmillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

  currentMillis = millis(); //for milli second timing
  recvOneChar();
  controlWater();
}

void recvOneChar() {

  if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}


void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
  }

  //is it time to process the next state code?
  if (currentMillis - myLEDmillis < waitTime)
  {
    //No, it is not time
    return;
  }


  switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Start watering");
        waitTime = 0;
      }
      break;

    case '2':
      {
        //Stop watering
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        waitTime = 0;
      }
      break;

    case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        waitTime = 10000ul;
        digitalWrite(13, HIGH);   // turn the water on
        //delay(3600000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        Serial.println("Watering done");
        //stop watering
        bluetoothData = 2;
      }
      break;

    case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on
        //delay(7200000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        //stop watering
        bluetoothData = 2;
      }
      break;

    case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);   // turn the water on
        waitTime = 3 * 60 * 60 * 1000ul;
        //delay(10800000);              // wait for x second
        //digitalWrite(13, LOW);    // turn the water off

        //stop watering
        bluetoothData = 2;
      }
      break;

  } //END of switch/case

} //END of function

A few problems 8)

bluetoothData = 2;
Should have been:
bluetoothData = '2';

Not able to check this here, but try:

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myRelayMillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

  currentMillis = millis(); //for milli second timing
  
  recvOneChar();
  controlWater();
}

void recvOneChar() {

  if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}


void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
  }

  //is it time to process the next state code?
  if (currentMillis - myRelayMillis < waitTime)
  {
    //No, it is not time
    return;
  }


  switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Start watering");
        myRelayMillis = millis();
        waitTime = 0;
      }
      break;

    case '2':
      {
        //Stop watering
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        myRelayMillis = millis();
        waitTime = 0;
      }
      break;

    case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        myRelayMillis = millis();
        waitTime = 10000ul;
        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Watering done");
        
        //stop watering
        bluetoothData = '2';
      }
      break;

    case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        myRelayMillis = millis();
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on

        //stop watering
        bluetoothData = '2';
      }
      break;

    case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);   // turn the water on
        myRelayMillis = millis();
        waitTime = 3 * 60 * 60 * 1000ul;

        //stop watering
        bluetoothData = '2';
      }
      break;

  } //END of switch/case

} //END of function

larryd:
A few problems 8)

bluetoothData = 2;
Should have been:
bluetoothData = '2';

Not able to check this here, but try:

#include <SoftwareSerial.h>// import the serial library

SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myRelayMillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;

void setup() {
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop() {

currentMillis = millis(); //for milli second timing
 
  recvOneChar();
  controlWater();
}

void recvOneChar() {

if (bluetooth.available() > 0) {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
  }

//is it time to process the next state code?
  if (currentMillis - myRelayMillis < waitTime)
  {
    //No, it is not time
    return;
  }

switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

digitalWrite(13, HIGH);  // turn the water on
        Serial.println("Start watering");
        myRelayMillis = millis();
        waitTime = 0;
      }
      break;

case '2':
      {
        //Stop watering
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        myRelayMillis = millis();
        waitTime = 0;
      }
      break;

case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        myRelayMillis = millis();
        waitTime = 10000ul;
        digitalWrite(13, HIGH);  // turn the water on
        Serial.println("Watering done");
       
        //stop watering
        bluetoothData = '2';
      }
      break;

case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        myRelayMillis = millis();
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);  // turn the water on

//stop watering
        bluetoothData = '2';
      }
      break;

case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);  // turn the water on
        myRelayMillis = millis();
        waitTime = 3 * 60 * 60 * 1000ul;

//stop watering
        bluetoothData = '2';
      }
      break;

} //END of switch/case

} //END of function

just tried it, but same as before. Does not stop timer.

Again, I cannot check this, but try try again:

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myRelayMillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;


void setup()
{
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop()
{

  currentMillis = millis(); //for milli second timing

  recvOneChar();
  controlWater();
}

void recvOneChar()
{
  if (bluetooth.available() > 0)
  {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}


void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
    myRelayMillis = millis();
  }

  //is it time to process the next state code?
  if (currentMillis - myRelayMillis < waitTime)
  {
    //No, it is not time
    return;
  }


  switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Start watering");

        waitTime = 5000;
      }
      break;

    case '2':
      {
        //Stop watering when timing is over
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off

        waitTime = 5000;
      }
      break;

    case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        myRelayMillis = millis();
        waitTime = 10000ul;
        digitalWrite(13, HIGH);   // turn the water on

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

    case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        myRelayMillis = millis();
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

    case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);   // turn the water on
        myRelayMillis = millis();
        waitTime = 3 * 60 * 60 * 1000ul;

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

  } //END of switch/case

} //END of function

larryd:
Again, I cannot check this, but try try again:

#include <SoftwareSerial.h>// import the serial library

SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myRelayMillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;

void setup()
{
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

void loop()
{

currentMillis = millis(); //for milli second timing

recvOneChar();
  controlWater();
}

void recvOneChar()
{
  if (bluetooth.available() > 0)
  {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
    myRelayMillis = millis();
  }

//is it time to process the next state code?
  if (currentMillis - myRelayMillis < waitTime)
  {
    //No, it is not time
    return;
  }

switch (bluetoothData)
  {
    case '1':
      {
        // Start watering

digitalWrite(13, HIGH);  // turn the water on
        Serial.println("Start watering");

waitTime = 5000;
      }
      break;

case '2':
      {
        //Stop watering when timing is over
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off

waitTime = 5000;
      }
      break;

case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        myRelayMillis = millis();
        waitTime = 10000ul;
        digitalWrite(13, HIGH);  // turn the water on

//Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        myRelayMillis = millis();
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);  // turn the water on

//Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);  // turn the water on
        myRelayMillis = millis();
        waitTime = 3 * 60 * 60 * 1000ul;

//Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

} //END of switch/case

} //END of function

Not working :sob:

I think we are close, I'll power up the equipment and try things here.
Hold on. . . .

Made some cosmetic changes.
However, I tried it here, things work with using simple button switches to change the cases as I don't have a Bluetooth module right now.

Try this again, make sure you upload it to the Arduino.

#include <SoftwareSerial.h>// import the serial library
SoftwareSerial bluetooth(3, 4); // RX, TX
const int relayPin =  13;
unsigned long currentMillis;
unsigned long myRelayMillis;
unsigned long waitTime = 0;
char bluetoothData; // the data given from mobile app
boolean newData = false;

//***************************************************
void setup()
{
  bluetooth.begin(9600);
  pinMode(relayPin, OUTPUT);
  Serial.begin (9600); //uncomment for debugging
}

//***************************************************
void loop()
{

  currentMillis = millis(); //for milli second timing

  recvOneChar();
  controlWater();
}

//***************************************************
void recvOneChar()
{
  if (bluetooth.available() > 0)
  {
    bluetoothData = bluetooth.read();
    newData = true;
  }
}

//***************************************************
void controlWater()
{
  if (newData == true)
  {
    //cancel the timer as a new command has come in
    waitTime = 0;
    newData = false;
    myRelayMillis = millis();
  }

  //is it time to process the next state code?
  if (currentMillis - myRelayMillis < waitTime)
  {
    //No, it is not time
    return;
  }


  switch (bluetoothData)
  {
//*************
    case '1':
      {
        //Start watering
        digitalWrite(13, HIGH);   // turn the water on
        Serial.println("Start watering");
        myRelayMillis = millis();
        waitTime = 5000;
      }
      break;

//*************
    case '2':
      {
        //Stop watering when timing is over
        Serial.println("Stop watering");
        digitalWrite(13, LOW);    // turn the water off
        myRelayMillis = millis();
        waitTime = 5000;
      }
      break;

//*************
    case '3':
      {
        //Water for 1 hour
        Serial.println("Water for 1 hour");
        myRelayMillis = millis();
        waitTime = 5000ul;  //testing
        //waitTime = 1 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

//*************
    case '4':
      {
        //Water for 2 hours
        Serial.println("Water for 2 hours");
        myRelayMillis = millis();
        //waitTime = 10000;  //testing
        waitTime = 2 * 60 * 60 * 1000ul;
        digitalWrite(13, HIGH);   // turn the water on

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

//*************
    case '5':
      {
        //Water for 3hours
        Serial.println("Water for 3 hours");
        digitalWrite(13, HIGH);   // turn the water on
        myRelayMillis = millis();
        //waitTime = 15000;  //testing
        waitTime = 3 * 60 * 60 * 1000ul;

        //Stop watering when timing is over
        bluetoothData = '2';
      }
      break;

  } //END of switch/case

} //END of function

//***************************************************