This repository has been archived by the owner on Sep 26, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patharduino-dishwasher.ino
260 lines (228 loc) · 6.39 KB
/
arduino-dishwasher.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
* Runs a dishwasher built according to instructions at
* http://www.instructables.com/id/Building-a-Dishwasher-From-Scratch
*
* By default, this sketch assumes an LCD is connected on pins 8-13,
* three buttons are connected on pins 5-7, and a pump and two
* solenoids are connected on pins 2-4. Pin numbers can be easily
* changed by modifying the definitions near the top of the file.
*
* Copyright (C) 2016 Nathaniel Paulus
* Licensed with the MIT License
*/
#include <RBD_Timer.h>
#include <RBD_Button.h>
#include <elapsedMillis.h>
#include <LiquidCrystal.h>
// specify the pins the LCD is connected to
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);
//configure our button pins
RBD::Button left(7);
RBD::Button primary(6);
RBD::Button right(5);
//configure pins for solenoids and pump
const int solenoidAPin = 4, solenoidBPin = 3, pumpPin = 2;
boolean coldOn = false, hotOn = false;
boolean running = false; //stopped/waiting
boolean paused = false;
//washing cycles
String defaultInstructions = "Red btn to run";
String message = "Waiting", option1 = defaultInstructions, option2 = "";
const int totalSeconds = 60*90; //seconds in a cycle
int secondsLeft = 0; //seconds left in current cycle
elapsedMillis mil; //automatically counts milliseconds
//pump and water sensor
const int minPumpTimeOn = 3000;
elapsedMillis pumpTimeOn;
boolean pumpOn = false;
const int waterSensorPin = A0, waterSensorThreshold = 750;
//thermistors
const int solenoidAThermistorPin = A1, solenoidBThermistorPin = A2;
//on a scale 0-100, which solenoid appears to be which?
//if number is less than 50, assume solenoidA is cold, B is hot
//otherwise assume the opposite
//this keeps a wildly-off reading from switching the solenoids
byte tempScale = 49;
//piezo beeper
const int piezoPin = A3, piezoHz = 500, piezoBeeps = 10, piezoBeepLength = 500, piezoPauseLength = 250;
boolean piezoBeeping = false, piezoPaused = false;
int piezoBeepsSoFar = 0;
elapsedMillis piezoTimer;
void setup() {
//set the LCD's dimensions
lcd.begin(16, 2);
updateLCD();
//set up solenoid, piezo, and pump pins as outputs
pinMode(solenoidAPin, OUTPUT);
pinMode(solenoidBPin, OUTPUT);
pinMode(pumpPin, OUTPUT);
pinMode(piezoPin, OUTPUT);
//set up input pins
pinMode(waterSensorPin, INPUT_PULLUP);
pinMode(solenoidAThermistorPin, INPUT_PULLUP);
pinMode(solenoidBThermistorPin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
if(left.onPressed()) {
//if paused, the left button means stop
if(paused) {
resetState();
}
updateLCD();
}
if(primary.onPressed()){
//if stopped/waiting, start cycle
if(!running && !paused){
secondsLeft = totalSeconds;
message = "Running";
option1 = "";
option2 = "Pause";
running = true;
coldOn = true;
hotOn = true;
mil = 0;
}
updateLCD();
}
if(right.onPressed()){
//when running, the right button pauses
if(running && !paused){
message = "Paused";
paused = true;
option1 = "Stop";
option2 = "Resume";
}
//when paused, the right button resumes
else if(paused){
paused = false;
option1 = "";
option2 = "Pause";
message = "Running";
mil = 0;
}
updateLCD();
}
if(running && !paused){
//handle countdown
if(mil >= 1000){
mil -= 1000;
secondsLeft--;
updateLCD();
}
//handle termination of cycle (i.e., when it finishes naturally)
if(secondsLeft == 0){
resetState();
option1 = "Finished";
updateLCD();
piezoBeeping = true;
piezoTimer = 0;
}
}
//handle thermistors
int a = analogRead(solenoidAThermistorPin), b = analogRead(solenoidBThermistorPin);
//readings go lower when temperature increases
//if a is cold and b is hot
if(a > b) tempScale--;
else tempScale++;
tempScale = constrain(tempScale, 0, 100);
//handle solenoids
boolean aOn, bOn;
if(tempScale < 50){
aOn = coldOn, bOn = hotOn;
}
else {
aOn = hotOn, bOn = coldOn;
}
if(!running || paused) {
aOn = false, bOn = false;
}
solenoidA(aOn);
solenoidB(bOn);
//handle water sensor and pump
//if the water sensor pin has been pulled low by current in the water
if(analogRead(waterSensorPin) < waterSensorThreshold){
if(!pumpOn){
pumpOn = true;
pumpTimeOn = 0;
pump(HIGH);
}
}
else if(pumpOn && pumpTimeOn >= minPumpTimeOn){
pumpOn = false;
pump(LOW);
}
//handle the piezo
if(piezoBeeping){
//start by checking if we're at the end or beginning of a beep
if(!piezoPaused && piezoTimer >= piezoBeepLength || piezoPaused && piezoTimer >= piezoPauseLength) {
if(!piezoPaused) piezoBeepsSoFar++;
piezoPaused = !piezoPaused;
piezoTimer = 0;
}
if(piezoBeepsSoFar >= piezoBeeps) {
piezoBeeping = false;
piezoBeepsSoFar = 0;
noTone(piezoPin);
}
else if(piezoPaused){
noTone(piezoPin);
}
//in a beep
else {
tone(piezoPin, piezoHz);
}
}
delay(1);
}
//reset state to default (as when a cycle finishes, or is stopped by the user)
void resetState(){
secondsLeft = 0;
running = false;
paused = false;
message = "Waiting";
option1 = defaultInstructions;
option2 = "";
}
//the message (to be displayed on the top row)
//the number of seconds left in the cycle (0 if stopped)
//option1 is an option to be shown in the bottom left, option2 to be
//shown on the bottom right (only if applicable)
void updateLCD(){
lcd.clear();
lcd.print(message);
//go to line 2
lcd.setCursor(0, 1);
//show the time left if applicable
if(running && !paused){
lcd.setCursor(0, 1);
//minutes
lcd.print(secondsLeft / 60);
lcd.print(":");
//print the number of seconds
//the % sign is used to divide and find the remainder
byte seconds = secondsLeft % 60;
if(seconds < 10) lcd.print("0"); // add a padding zero
lcd.print(secondsLeft % 60);
}
//if no count down to show
else {
lcd.print(option1);
}
//move the cursor so option2 can be right-aligned
lcd.setCursor(16-option2.length(), 1);
lcd.print(option2);
}
// functions below turn the solenoids, piezo, and pump on and off
void solenoidA(uint8_t state){
digitalWrite(solenoidAPin, state);
}
void solenoidB(uint8_t state){
digitalWrite(solenoidBPin, state);
}
void pump(uint8_t state){
digitalWrite(pumpPin, state);
}
void piezo(uint8_t state) {
digitalWrite(piezoPin, state);
}