Go Down

Topic: Dishwasher control advice needed (Read 1 time) previous topic - next topic

steve8428

Well that's good to know and it does not need to be clock accurate so this should be ok

steve8428

I am having some trouble with using the millis delay. I have a small sketch for testing. It calls two functions and I have put a count on then to see what is happening. I need the fill function to be longer than it currently is. At the current interval of 9800 I get a count of 4594, but if i increase this interval the count goes on for ever.

Also if i change the drain interval it changes the fill time, the count will be shorter or longer.

Therefore i cannot fill the washer and when changing intervals all the settings for the other functions will change.

Is this because i am sending the interval by the function. One option may be to use a counter to control how long things run for. A millis function could run the counter so i do not have a delay

Any help would be great

Code: [Select]
 
int fillValve = 13;
int drainPump = 14;
int flag = 0;
unsigned long fill_Time = 0;
int fillStatus;

unsigned long drain_Time = 0;
int drainTime;

unsigned long count;

void setup() {
  Serial.begin(9600);
  pinMode(fillValve, OUTPUT);
  Serial.println("Setup Completed");
}

void loop() {
  switch(flag){
      case 0:
        drainFun (6000); //flag 0
      break;
      case 1:
        fillFun (98000); //flag 1
      break;
  } 
}

void drainFun(int Draininterval){
  count++;
  Serial.println(count);
  digitalWrite(drainPump, LOW);   
  if ((millis() - drain_Time) >= Draininterval){
      drain_Time = millis();
        flag++;  //stop this process
        digitalWrite(drainPump, HIGH);
        Serial.println("Drainning finnished");
        count = 0;
      }
   }

void fillFun(int interval){
  count++;
  Serial.println(count);
  digitalWrite(fillValve, HIGH);;
  if ((millis() - fill_Time) >= interval){
    fill_Time = millis();
      flag++;
      digitalWrite(fillValve, LOW);
      Serial.println("Filling Completed");
  }
 }

Robin2

#17
Jul 10, 2017, 09:18 pm Last Edit: Jul 10, 2017, 09:23 pm by Robin2
Using the drainFun() function as an example I suspect you need to set drainTime = millis() when the function is first called but not during the repeat calls

I think the way to do that is to have a variable called drainRunning and normally it is false. Then the code in the drainFun() would be like this
Code: [Select]
void drainFun(int Draininterval){
  if (drainRunning == false) {
     drainStartTime = millis();
     drainRunning = true;
  }
  count++;
  Serial.println(count);
  digitalWrite(drainPump, LOW);  
  if ((millis() - drainStartTime) >= Draininterval){
            // line removed
        flag++;  //stop this process
        drainRunning = false;
        digitalWrite(drainPump, HIGH);
        Serial.println("Drainning finnished");
        count = 0;
      }
   }


There is no point setting drainStartTime = millis() when the draining is finished because you have no idea when it will start again.

You should be conscious that the changes I have suggested are what I would call "logic" changes - in other words, while they are implemented in code they really have little to do with code and all to do with the washing process. Even if you were instructing your kitchen maid to do the washing this sort of logic would be needed. I have seen several Threads on the Forum where people seemed not to see that distinction - not saying you don't, however.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

steve8428

I have changed the interval from integer to long and this has solved the problem with the length of the run. I can now get it so far to a count of 6511. Still need to do some more testing to see if i can run this to a full fill of the washer.

Robin thanks again for the reply. You have lost me with this one at the moment. Is this change to do with the intervals interfering with each other. The following seems to work but have not tested what happens when i change the variables being sent to the function.

Code: [Select]

void loop() {
  switch(flag){
      case 0:
        drainFun (500);
      break;
      case 1:
        fillFun (40000);
      break;
  } 
}

void drainFun(long Draininterval){
  count++;
  Serial.println(count);
  digitalWrite(drainPump, LOW);   
  if ((millis() - drain_Time) >= Draininterval){
      drain_Time = millis();
        flag++;  //stop this process
        digitalWrite(drainPump, HIGH);
        Serial.println("Drainning finnished");
        count = 0;
      }
   }

void fillFun(long interval){
  count++;
  Serial.println(count);
  digitalWrite(fillValve, HIGH);;
  if ((millis() - fill_Time) >= interval){
    fill_Time = millis();
      flag++;
      digitalWrite(fillValve, LOW);
      Serial.println("Filling Completed");
      Serial.println(interval);
  }

steve8428

just run the fill on the dishwasher with an interval of 170000 and got a count of 23709 with the water level near the bottom door seal. So at this part is looking good. Still a lot to do.

Robin2

In this line (from Reply #18) where was the value of drain_Time set?
Code: [Select]
if ((millis() - drain_Time) >= Draininterval){

And I don't think you mean "drain_Time" - surely that is what the Draininterval is? I think you mean drainStartTime

Using appropriate meaningful names for variables can be a great help in seeing the logic of the system.

Indeed drainDuration might be more meaningful than Draininterval

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

steve8428

Yes my use of terminology is not always great. drain_Time was a changeable variable set at the beginning, substitute for previousMillis from the delay example 

You advice is greatly welcome  and I will be update what you have said and post further my progress

thank you

steve8428

just completed the drain and fill functions and they seem to be working well. Robin thanks for your input the code you sent worked well. Took me a while to work out why but i understand now that after a while millis has increased and with out my functions being called it meant the timings had all drifted off.

Now i need to work on the wash function

Code: [Select]

void loop() {

  onOffFun();  // keep checking on/off button. if pushed start program if operated during program stopp all
  if (prog_State == 1){   
    switch(flag){
      case 0:
        drainFun (5000); //flag 0 12000
      break;
      case 1:
        fillFun (6000); //flag 1 17000
      break;
      case 2:
       // washFun(3); //flag 2
       flag = 0;
      break;
      case 3:
        drainFun (9000);
      break;
      case 4:
        Serial.println("Ended");
        prog_State = 0;
      break;
    }
  }

 }

void onOffFun (){
    // read the button status
    int reading = digitalRead(O_Button);
   
    if(reading != O_lastButtonState){  //meaning button has been pushed
      lastDebounceTime = millis();
     }
     if((millis() -  lastDebounceTime) >= debounceDelay){ // button held down long enought to count
      if(reading != O_buttonState){
        O_buttonState = reading;
        if (O_buttonState == LOW){
          prog_State = ! prog_State;  //change prog_State from 1 to 0 or vice versa
      }
     }
  }
  O_lastButtonState = reading;
}

// All outputs are inverted due to relay card. HIGH will be OFF and LOW will be ON

void drainFun(int Draininterval){
  if(drainRunning == false){
    drainStartTime = millis();
    drainRunning = true;
  }
  digitalWrite(drainPump, LOW);   
  if ((millis() - drainStartTime) >= Draininterval){
        flag++;  //stop this process
        drainRunning = false;
        digitalWrite(drainPump, HIGH);
      }
   }
       
void fillFun(int fillinterval){
  if(fillRunning == false){
    fillStartTime = millis();
    fillRunning = true;
  }
  digitalWrite(fillValve, LOW);
  if ((millis() - fillStartTime) >= fillinterval){
      flag++;
      fillRunning = false;
      digitalWrite(fillValve, HIGH);
    }
  }

steve8428

The wash/rinse cycle has a motor connected to a disc which diverts the wash to different jets as it rotates. It also has a micro switch which makes when the disc has got to one of the jet ports.

So i will need to rotate the disc till one port is in line with the pump, then stop the motor rotating and turn the wash pump on for a set duration. Then the wash pump needs to turn off, turn the disc motor on and rotate around till the next jet is in line (micro switch closed again).

So the process will be { selectorMotor - ON / JetSelectorSwitch - Closed / selectorMotor - OFF / Wash pump ON / Interval / Wash pump off / SelectorMotor on till switch open again / start again}

This needs to happen for the required times sent by the call function.

I have made an attempt which at the moment seems to be working on the TinkerCab simulator. I will hopefully test this on the washer tonight.

Any thoughts would be appreciated.

Code: [Select]

int washPump = 6;
int jetSelectorSwitch = 2;
int selectorMotor = 5;
int motorRunning;
unsigned long stopTime;
int washDuration = 2000;
int flag = 0;
int currentWash = 0;

void setup(){
  Serial.begin(9600);
  pinMode(washPump, OUTPUT);
  digitalWrite(washPump, HIGH);
  pinMode(jetSelectorSwitch, INPUT);
  digitalWrite(jetSelectorSwitch, HIGH);
  pinMode(selectorMotor, OUTPUT);
  digitalWrite(selectorMotor, HIGH);
  motorRunning = true;
}

void loop (){
  switch(flag){
    case 0:
   washFun(6);
     currentWash++;
   break;
   case 1:
   Serial.println("Wash finnished");
         Serial.print("Current Wash number = ");
        Serial.println(currentWash);
   break;
  }
}

void washFun(int washCycle){

  if(washCycle > currentWash){
      int reading = digitalRead(jetSelectorSwitch);

      if(reading == 0 && motorRunning == false){  // switch closed so stop motor and start wash
        
        digitalWrite(selectorMotor, HIGH); // OFF
        stopTime = millis();
        motorRunning = true;
        digitalWrite(washPump, LOW); //ON
        Serial.println("Wash ON / Motor OFF");
      }
    if(reading == 1 && motorRunning == true ){  // switch open so motor should be running

        motorRunning = false;
        digitalWrite(selectorMotor, LOW); //ON
        digitalWrite(washPump, HIGH); //OFF
        Serial.println("Wash OFF / Motor ON");
      }
      if (millis() - stopTime >= washDuration && motorRunning == true){

        digitalWrite(selectorMotor, LOW); //ON
        Serial.println("Motor ON");
      }
   if (currentWash == 6){
     flag++;
     currentWash = 0;
   }
  }

Robin2

I suspect you have the same problem that I pointed out for timing - no code to set currentWash to zero when the wash cycle is started.

I'm not sure I see clearly how the disc and jets are to be dealt with. I think I would create a function called moveToNextJet()

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

steve8428

Hi robin

i have edited the code slightly by taking the currentWash++ and placing it inside the
Code: [Select]
if(reading == 1 && motorRunning == true )
 statement as it would not increment.

Hopefully the following make sense.

If reading = 0 then the switch has made so the motor needs to be turned off as the wash jet is aligned. It can now turn the wash pump on. stopTime records the time this happened and motorRunning made TRUE so this is not run again. Wash pump is left ON at this point

Code: [Select]
     if(reading == 0 && motorRunning == false){  // switch closed so stop motor and start wash
        
        digitalWrite(selectorMotor, HIGH); // OFF
        stopTime = millis();
        motorRunning = true;
        digitalWrite(washPump, LOW); //ON
        Serial.println("Wash ON / Motor OFF");
      }


After a set time the jet selector motor is turned on so the cam can get away from the micro switch and open the switch.

Code: [Select]

      if (millis() - stopTime >= washDuration && motorRunning == true){
        digitalWrite(selectorMotor, LOW); //ON
      }


Now motor is running and motorRunning = TRUE i am waiting for the the switch to open, the jet will have moved half way from the pump so I need to turn off the wash pump change motorRunning to false but keep the selector motor running so it can move around to the next position to make the switch again.

Code: [Select]
   if(reading == 1 && motorRunning == true ){  // switch open so motor should be running
        motorRunning = false;
        digitalWrite(selectorMotor, LOW); //ON
        digitalWrite(washPump, HIGH); //OFF
        currentWash++;
      }


This will then happen all over again.

The last piece should reset currentWash to 0 for the next time i call this function.

Code: [Select]
  if (currentWash == 3){
     flag++;
          Serial.println(currentWash);
     currentWash = 0;
     Serial.println(currentWash);
   }


This is working in simulator but i do need to test it in real tonight. It has been a pain to write due to the fact the selector motor need to run for a few second to open the cam switch.


Robin2

#26
Jul 12, 2017, 08:14 pm Last Edit: Jul 12, 2017, 08:15 pm by Robin2
This is working in simulator but i do need to test it in real tonight. It has been a pain to write due to the fact the selector motor need to run for a few second to open the cam switch.
I suspect that is because of the way your program is written rather than any fault of the switch :)

You need a state which is perhaps washPumpRunning and that get set to true when the cam triggers the switch. And when the pump cycle has been on long enough you set washPumpRunning to false. That makes the way clear for the motor to move regardless of the state of the cam switch.

It's for this sort of reason that I would have separate functions for moving to the next position and for operating the pump

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

steve8428

I believe i have got the wash function working OK, i have taken on board your comments Robin and made the wash and jet control in two separate functions. I have done a test and all seems to be working great. I now need to start putting this all together and add a dispenser operation during a wash cycle.

i still have the door control and pause function to write

Code: [Select]
//--wash pump variables----
int pump = 27;
int jetSwitch = 2;
int jetMotor = 29;
int jetSWreading;
unsigned long washDuration = 8000;
unsigned long stopTime = 0;
int washPumpRunning;
int currentWash = 0;

void setup() {
  pinMode(pump, OUTPUT);
  digitalWrite(pump, HIGH);
  pinMode(jetSwitch, INPUT);
  digitalWrite(jetSwitch, HIGH);
  pinMode(jetMotor, OUTPUT);
  digitalWrite(jetMotor, HIGH);
  washPumpRunning = false;
}

void loop() {
    pumpFun();
    jetFun(4);
 }
// switches are high in setup to use Arduino internal resistor. So input is inverted.
// 1 = Open switch, 0 = Closed switch
// OUTPUTS are also inverted due to relay board. High out will turn off, LOW will turn ON

void jetFun(long washCycle){
   if(washCycle > currentWash){
     jetSWreading = digitalRead(jetSwitch);
     if(jetSWreading == 1){ //SW open
        digitalWrite(jetMotor, LOW); // Motor on
        stopTime = millis();
        washPumpRunning = true;
     }
     if(jetSWreading == 0 && washPumpRunning == true){ // SW close
        digitalWrite(jetMotor, HIGH); // Motor off
        washPumpRunning = false;
        currentWash++;
     }
     if (millis() - stopTime >= washDuration && washPumpRunning == false){
       digitalWrite(jetMotor, LOW); // Motor on
     }
   }
   if (currentWash == washCycle){
     flag++;
     currentWash = 0;
     digitalWrite(jetMotor, HIGH); //OFF
     digitalWrite(pump, HIGH); //OFF
   }
}
void pumpFun(){

  switch (jetSWreading){
    case 0:  //switch closed
      digitalWrite(pump, LOW); //ON
    break;
    case 1: //switch open
      digitalWrite(pump, HIGH);  //OFF
    break;
  }
}

nixie

Steve, I'm very impressed by this project.  Which Arduino are you using, and what sort of interfacing issues have you encountered? Is it all 5v logic, or did you have to add driving electronics?

I'd be scared of overlooking something, and ending up with a flood.

Good luck!

steve8428

I am using the Mega arduino connected to a relay bank. No other electronics needed. The arduino controls the relays which control all the dishwasher devices which are all 240V. All switches are going straight to the arduino digital pins which are held HIGH by the program so no need for pull up resistors.

As for flooding The fill function of the codes should stop the inlet valve when the water is at a level I am happy with. If there was an overfill then I have a flood sensor on the bottom try (still to be programmed in) which will shut down the inlet valve.

Go Up