Dishwasher control advice needed

In this line (from Reply #18) where was the value of drain_Time set?

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

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

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

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);
    }
  }

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.

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;
   }
  }

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

Hi robin

i have edited the code slightly by taking the currentWash++ and placing it inside the

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

     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.

      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.

   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.

  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.

steve8428:
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 :slight_smile:

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

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

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

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!

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.

steve8428:
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.

If at all possible, have an anti-flood system that shuts off the water (perhaps shuts off all the power) without needing any signal from the Arduino

...R

I'd use the watchdog timer too, to recover from a crash. To help with that, write status info to EEPROM as the cycle progresses.

I have not thought about the flood sensor at the moment as i still need to get it all running. Probably a good idea shut all power down by a relay in the event of a flood. At the moment there is a polystyrene disc on the bottom try which will float up in a flood and makes a micro switch. i could easily connect this is a relay to turn all the supply off when made.

WildBill thanks for the tip. i don't know how to do what you are suggesting. But later i will google this to see what i can find out

I have now completed the door pause function. When the door is opened the flag status and the time door is opened if recorded. All pumps and valves are stopped. The program comes out of the current flag process to prevent any variables changing and gets put into a holding flag = 10.

When the door is closed the flag is reset so the program goes back to where it left off. The time the door was opened for is calculated and added to the interval of the current flag process. When that process is finished the pause time is rest to 0 so the next process does not have any delays.

This is the test code below which works well on bread board but still needs testing on the washer

int door = 30;
byte doorState;
byte pause = 1;
unsigned long TimeStopped = 0;
unsigned long pauseTime = 0;
unsigned long lastChecked = 0;
int duration = 300;
int flagStatus;

int flag = 0;

//-----Drain variables------
int drainPump = 25;
unsigned long drainStartTime = 0;
int drainRunning;

void setup() {
  Serial.begin(9600);
  pinMode(door, INPUT);
  digitalWrite(door, HIGH);
  pinMode(drainPump, OUTPUT);
  digitalWrite(drainPump, HIGH);
}

void loop() {
    doorFun(); // this will be in side prog_status loop so only called when wash in progress
    switch(flag){
      case 0:
           drainFun(10000); 
      break;
      case 1:
        //Fill function
      break;
      case 10;
        Serial.println("Program Paused");
      break;
    }
}

void drainFun(long Draininterval){
  long interval = Draininterval + pauseTime;  // now have pause delay. If program was paused the delay will be added to the interval so the total 
                                              // run time will always be the same if no pause the it will be equal to 0
  if(drainRunning == false){
    drainStartTime = millis();
    drainRunning = true;
  }
  digitalWrite(drainPump, HIGH);   
  if ((millis() - drainStartTime) >= interval){
        flag++;  //stop this process
        drainRunning = false;
        digitalWrite(drainPump, LOW);
        pauseTime = 0;   // reset pause time to zero so next flag is not running a pause add on.
      } 
   }
// door function check door switch every 300ms. Time delay to stop any double reading when switch changing states
void doorFun (){
  if (millis() - lastChecked >= duration){
    lastChecked = millis();
    doorState = digitalRead(door);
  if (doorState == 0 && pause == true){ //door open
    pauseFun();     // call the pause function
  }
  if (doorState == 1 && pause == false){ //door closed
    restartFun();  // call the restart function
  }
  }

}

void pauseFun(){
  digitalWrite(drainPump, HIGH);
  if (pause == true){ //pause = true statment is so this is only called once to record the stop time. Then pause will be = false
    pause = false;
    timeStopped = millis();  // record the stop time
    flagStatus = flag;  //record what flag state the program was at
    flag = 10;  // set flag to 10 so program stops counting current flag state
  }
}
void restartFun(){
  flag = flagStatus;  // restart so set flag to number it was stopped at
  pauseTime = millis() - stopTime;  // record the time the door was opened for so we can add it to the interval
  pause = true;  // reset pause to true so door function can be recalled
}

With this i can add a pause button which will call the same pause function.

I still need to work out how the salt flush for the water softener works. I have a solenoid on the side of the salt box which I think when energized allows water into the salt box. But i cannot find any information on how this part works on the internet. If anyone can explain this part it would be a great help.

I also have a Whirlpool Turbidity Sensor which I hope i can use. The cables are all yellow so i don't know yet what ones do what. i will remove this next week and have a play.

I also still need to add some safety features.

  • As already stated a shut off if water overflows, Thinking of using external relay to cut off supply for this
  • Inlet water flow needs to be counted so the heater element will not turn on without water in the machine
  • An external watch dog to monitor that the arduino has not crashed and left the machine running with no control. I might use a micro arduino to monitor a pulse from the main arduino. If pulse stops possible crash use overflow relay to turn machine off.

Still lots to do.

Just completed a full rinse today and have noticed two problems. When the wash pump starts up there is a kick from the Wash pump on start. This at first caused the jet selector switch to chatter which caused the wash count to increase by about 4 each time. I sorted this by putting a millis() time delay of 300ms before reading the switch the same as I did with the door function.

if (millis() - jetlastChecked >= duration){ //duration = 300
      jetlastChecked = millis();
   if(washCycle > currentWash){
     jetSWreading = digitalRead(jetSwitch);

This sorted the switch bounce but I am not sure the wash motor needs to be switch off during the movement of the jet selector. This jet selector moves within a second or two and is not a tight fit, water will pass around the side of the selector disc so the pump would not be under load.

The reason I am thinking this. Every time the pump is turned OFF and ON again the washer kicks a little and you hear a start up thud from the pump. This is something I never noticed from the original manufacturers wash. This has also caused the relays to chatter on two occasions, when the relay chatters the pump keeps kicking and will not start.

If i leave the pump on and just move the selector every interval it all works OK and sound more like what it did before breaking. When the selector is not on the jet position it makes a whooshing noise which sounds normal from what I remember.

This will also help with the heating of the water as the heater can be on all the time the water temperature is low.

If anyone has worked on dishwashers and know more about this please let me know. There is not much information on the web.

I will at the moment proceed with the pump always on during a wash process

I have been following this project for the last few days. I think it's great! Could you please post your current version of the code so lazy people like us don't have to piece together the various updates? :slight_smile:

Thanks!

I have had a little play with the turbidity sensor but not having much luck. The sensor has 6 terminals and I cannot guarantee the wiring diagrams I have found on the web are correct.

So far I have connected the supply up to the VDD 5v and GND ground and then pins 1 to AO and 6 to A1 of the arduino.

running the following sketch I get a reading of 0 which does not change when I cover the sensor. Not tried in in water yet

int temp = A0;
int x = A1;

void setup() {
  Serial.begin(9600);
  pinMode(temp, INPUT);
    pinMode(x, INPUT);
  Serial.println("SETUP COMPLETED");
}

void loop() {
  int reading2 = analogRead(x);
  int reading = analogRead(temp);
  Serial.println(reading);
    Serial.println(reading2);
  delay(1000);
}

So if I cannot get this working then I might pull the circuit out of the housing so I can use the housing and make my own sensor.

For the temperature i would like to use the DS18D20 1-wire device as I have used these before and they are very reliable and accurate.

For the turbidity I wonder if I could make my own with an LED and LDR setup or use a IR LED and IR receiver.

I will let you know how I get on but I am away at the end of the week so might not be much posts for a while

I have a strange thing happening which I cannot work out why. In the following sketch at the bottom of this post I have an IF statement at the beginning which records the fill start time if the fillRunning variable is == to 0, which it will be at the start for this function. As it is, it works, but originally I had this IF statement just above this part if((millis() - fillStartTime) >= fillInterval){ which worked on the first time around but the second time the fillStartTime would not be updated, even though the fillRunning was == to 0.

Don't know if this makes sense. It would be nice to know why this is happening so I can rectify it if i get a similar problem

long fillInterval = (100000 + pauseTime);  // pauseTime is calculated when door on opened

if(fillRunning == 0){         //fillRunning initially zero at setup
    fillStartTime = millis();
    fillRunning = 1;
    long start_time = ( millis() - fillStartTime);
}

int reading = digitalRead(flowSW);

if(reading != lastflowReading){
   if(reading == HIGH){
     flowCount++;
   }
}

lastflowReading = reading;

if(flowCount < 800){
   digitalWrite(fillValve, LOW); // fill valve ON
}
else{
   digitalWrite(fillValve, HIGH); // fill valve OFF
   flowCount = 0;  //reset flow count for next time
   flag++;            // increase flag to move to next function
   fillRunning = 0; // reset fillRunning to 0 for next time
} 

if((millis() - fillStartTime) >= fillInterval){
   fillRunning = 0;
   if(flowCount < 50){
      faultCode = 2;  // This will stop wash and lock it in fault mode
      flowCount = 0;
      pauseFun();     // call pauseFun to shut the wash down
    }
  } 
}

steve8428:
Don't know if this makes sense. It would be nice to know why this is happening so I can rectify it if i get a similar problem

It will be easier to help if you post the two versions of the program. It would be too easy to imagine the wrong location for that line of code.

...R