Pages: [1]   Go Down
Author Topic: Exit from cycle needed  (Read 579 times)
0 Members and 1 Guest are viewing this topic.
Space Coast Florida
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

 
Code:

/* 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???
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 52
Posts: 2396
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Mark
Logged

Space Coast Florida
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

New Jersey
Offline Offline
Faraday Member
**
Karma: 72
Posts: 3764
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Space Coast Florida
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 72
Posts: 3764
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Space Coast Florida
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Space Coast Florida
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Code:
// 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;
}

Logged

California
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3447
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
      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.
Logged

Pages: [1]   Go Up
Jump to: