Exit from cycle needed

Hi I am working on my first real Arduino project. It is a 3 fluid washing machine.I have almost every thing working. My problem is I need to be able to exit the cycle at any point in case of problems. An emergency stop if you will in the program.
I am using an Arduino Uno now and will move the program to a Mega when it gets here. Also I am simulating the agitator motors with a servo until i get my dc motor controller in.
Your thoughts please.

/* 3 8-ohm speaker on digital pin 7
/* Stir motors on pins 3 and 4 (servo stirrer used for now)
/* Drain valves on pins 8,9,10
/*Pumps on pins 11,12,13

 */
#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 
int pos = 0;    // variable to store the motor position 
int lpct = 4;  /*variable to keep loop count */
 //********************************
 
int pausetime = 1000; /*  Standard delay */
int notepause = 150;  /* delay between notes */
int stirtime = 2000;  /* set for 20 min later */ 
int filltime = 2000; /* calibrate from pump */ 
int draintime =2000; /* measure drain time */
int pump1 = 11;  /*setup pump 1 */
int pump2 = 12;  /*setup pump 2 */
int pump3 = 13;  /*setup pump 3 */
int valve1 = 8; /* setup valve 1 */
int valve2 = 9;  /* setup valve 2 */
int valve3 = 10;  /* setup valve 3 */
int stirrer1 = 3; /*setup stirrer 1 */
int stirrer2 = 4; /*setup stirrer 2 */

void setup() {
  
  myservo.attach(2);  // attaches the servo on pin 9 to the servo object 

  
   pinMode(pump1, OUTPUT); /* configure pin as output */
   pinMode(pump2, OUTPUT); /* configure pin as output */
   pinMode(pump3, OUTPUT); /* configure pin as output */
   pinMode(valve1, OUTPUT); /*configure pin as output */
   pinMode(valve2, OUTPUT); /*configure pin as output */
   pinMode(valve3, OUTPUT); /*configure pin as output */
   pinMode(stirrer1, OUTPUT); /* configure pin as output */
  
 /* Initialization  */ 
   tone (7, 4978,100); /* Init tones */
   delay (notepause);
   tone (7, 4699,100);
   delay (pausetime);
}

void loop() {
  
  
  /* Start process  */ 
  
  /* CYCLE 1  */
  /* play a single note on pin 7 for 100 ms: signifying cycle 1 */
  tone(7, 4000, 100);
  delay(notepause);
  
  /*  FILL  */
  digitalWrite(pump1, HIGH);   /*  turn on pump1 */
  delay(filltime);             /* fill tank      */
  digitalWrite(pump1, LOW);    /* turn off pump1 */
  
  /* STIR  */
  
 
  for (lpct = 0; lpct <  4; lpct +=1)
  {
     for(pos = 60; pos < 180; pos += 1)  // goes from 0 speed to 180 speed 
     {                                  // in steps of 1 
        myservo.write(pos);              // tell motor to go to speed in variable 'pos' 
        delay(15);                       // waits 15ms  
     } 
        for(pos = 180; pos>=60; pos-=1)     // goes from 180 speed to 0 speedspeed 
     {                                
        myservo.write(pos);              // tell motor to go to position in variable 'pos' 
       delay(15);                       // waits 15ms for the motor to reach the position 
     } 
  }
 
 
 /*  Drain  */
  digitalWrite(valve1, HIGH);   /*  turn on valve1 */
  delay(draintime);             /* drain tank      */
  digitalWrite(valve1, LOW);    /* turn off valve1 */
  
 
 /* CYCLE 2 */   
  /* play a double note on pin 7 for 100 ms: signifying cycle 2 */
  delay(pausetime);
  tone(7, 4000, 100);
  delay(notepause);
  tone(7, 4000, 100); 
  delay(notepause);
  
  digitalWrite(pump2, HIGH);   /*  turn on pump2 */
  delay(filltime);             /* fill tank      */
  digitalWrite(pump2, LOW);    /* turn off pump2 */
  
  
  /* STIR */
 
  
  for (lpct = 0; lpct <  4; lpct +=1)
       {
       for(pos = 60; pos < 180; pos += 1)  // goes from 0 speed to 180 speed 
       {                                  // in steps of 1  
          myservo.write(pos);              // tell motor to go to position in variable 'pos' 
         delay(15);                       // waits 15ms for the motor to reach the position 
       } 
 for(pos = 180; pos>=60; pos-=1)     // goes from 180 speed to 0 speed 
       {                                
       myservo.write(pos);              // tell motor to go to position in variable 'pos' 
       delay(15);                       // waits 15ms for the motor to reach the position 
       } 
  }



  /*  Drain  */
  digitalWrite(valve2, HIGH);   /*  turn on valve2 */
  delay(draintime);             /* drain tank      */
  digitalWrite(valve2, LOW);    /* turn off valve2 */
  
  
  
  /* CYCLE 3  */
  /* play a triple note on pin 7 for 100 ms: signifying cycle 3 */
  delay(pausetime);
  tone(7, 4000, 100);
  delay(notepause);
  tone(7, 4000, 100); 
  delay(notepause);
  tone(7, 4000, 100); 
  delay(notepause);
  
  
 digitalWrite(pump3, HIGH);   /*  turn on pump3  */
  delay(filltime);             /* fill tank      */
  digitalWrite(pump3, LOW);    /* turn off pump3 */
 
 
  /*  STIR  */

  for (lpct = 0; lpct <  4; lpct +=1)
      {
       for(pos = 60; pos < 180; pos += 1)  // goes from 0 speed to 180 speed 
       {                                  // in steps of 1  
         myservo.write(pos);              // tell motor to go to position in variable 'pos' 
         delay(15);                       // waits 15ms for the motor to reach the position 
       } 
       for(pos = 180; pos>=60; pos-=1)     // goes from 180 speed to 0 speed 
       {                                
        myservo.write(pos);              // tell motor to go to position in variable 'pos' 
        delay(15);                       // waits 15ms for the motor to reach the position 
  } 
  }
 
  /*  Drain  */
  digitalWrite(valve3, HIGH);   /*  turn on valve3 */
  delay(draintime);             /* drain tank      */
  digitalWrite(valve3, LOW);    /* turn off valve3 */
  
  
  
  
   
  
  /* end of cycle  */
  
   /* play a 4 note sequence on pin 7  signifying end of cycle */
  delay(pausetime);
  tone(7, 3729, 100);
  delay(notepause);
  tone(7,2489 , 400); 
  delay(notepause);
  tone(7, 4978, notepause); 
  delay(notepause);
  tone(7, 4435, 400); 
  delay(notepause);
  
  
}

The biggest problem is the delay statements but i still need to be able to exit anywhere in the program.
Scratching my head???

Take a look at blink without delay, then rewrite your program.

Mark

The biggest problem is the delay statements but i still need to be able to exit anywhere in the program.

urthlight:
The biggest problem is the delay statements but i still need to be able to exit anywhere in the program.

If you use the approach demonstrated in the 'blink without delay' example then your sketch will work without blocking anywhere - this makes it possible to check for as many independent events as you choose, so you can handle button presses, timeouts, serial input etc as they occur. If you take this approach, all you need to do is test for the 'emergency stop' button being pressed and abort the washing sequence.

Search the forum for 'state machine'. There have been any number of examples posted (some by me) that illustrate the technique - it's ideal for your application.

Ok I have played with blink without delay and that works pretty good for the most part except that all of my outputs are running all of the time. So....now it looks like I need that fsm. Can you point me to the particular example that you are talking about . There is a metric ton of threads on state machines in the forum and my eyes are about to bleed from reading.

Here's one: http://arduino.cc/forum/index.php/topic,106335.0.html

That is indeed ideal for my needs? That is a nice piece of code. I think I see what you did there. Thank you for your response.

OK, I have an FSM that looks pretty good however I am having trouble resetting the elapsed time variable.
It works the first time thru the loop but the second iteration does not stop because its value is greater than 10. What am i missing. Do I need a separate variable for each timer?

// system states 
#define WAITING   0
#define FILLING   1
#define STIRRING  2
#define DRAINING  3
#define ABORT     4



const int Pump1 =  10;
const int Valve1 = 11;
const int Stirrer1 = 12;
const int alternatorPin = 2;
int state = WAITING;        // master variable for the state machine
int fill_seconds = 10;
int startTime;
int new_elapsed_seconds;
int elapsed_seconds;
void setup() 
{
  startTime = millis();
  pinMode(Pump1, OUTPUT);
  pinMode(Valve1, OUTPUT);
  pinMode(Stirrer1, OUTPUT);
  pinMode(alternatorPin,INPUT);
  Stop(); // Make sure everything is set correctly
  Serial.begin(9600);
}

void loop() 
{ 
  switch(state)
  {
  case WAITING:
    HandleWAITINGState();
    break;
  case FILLING:
    new_elapsed_seconds = (millis() - startTime) / 1000;
    if (new_elapsed_seconds != elapsed_seconds)
    {
      elapsed_seconds = new_elapsed_seconds;
      Serial.println( elapsed_seconds); 

      if (elapsed_seconds == fill_seconds)
      {
        //startTime = 0;
        //new_elapsed_seconds = 0; 
        //elapsed_seconds = 0;  
        Serial.println("Done Filling");
        Serial.println( elapsed_seconds);
        Serial.println( new_elapsed_seconds);
        state=STIRRING;  
      }
    }
    HandleFILLINGState();
    break;
  case STIRRING: 
    HandleSTIRRINGState();
    break;  
  case DRAINING:
    HandleDRAININGState();
    break;  
  default:
    Serial.print("Unknown State: ");
    Serial.println(state);
    Stop(); // Should never get here
    break;  
  }
}
void HandleWAITINGState()
{
  if (Serial.available() > 0) 
  {
    Serial.read(); // I wonder if this should be flush
    Serial.println("");  
    Serial.println("Waiting"); 
    state=FILLING;
  }   
}
void HandleFILLINGState()
{
  digitalWrite(Pump1,HIGH);
  digitalWrite(Valve1,LOW);
  digitalWrite(Stirrer1,LOW);
}  
void HandleSTIRRINGState()
{
  Serial.println("STIRRING"); 
  state=DRAINING;
}
void HandleDRAININGState()
{
  Serial.println("DRAINING"); 
  state=WAITING;  
}
void abort()
{
  Serial.println("ABORT");  
  state=WAITING;
}
      if (elapsed_seconds == fill_seconds)

elapsed_seconds is just simply millis() / 1000, so it will only ever be equal to 10 once every 49ish days (when millis() rolls over).

Am I correct in assuming that you want to be in the FILLING state for 10 seconds? If so, you should be recording the time that you enter the state, and while in that state, checking if it's been 10 seconds since you entered the state. If so, move to the next state.