-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWater_Dispenser.h
197 lines (172 loc) · 7.37 KB
/
Water_Dispenser.h
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
// reflects the open/closed state of the solenoid
enum SolenoidState {
OPEN,
CLOSED
};
/* Water 1 config:
A "Water" consists of a solenoid that controls the flow of water from the resevour to the port. The port contains a beam-break sensor (SENSOR) that when broken dispenses a drop of water.
*/
// Arduino is Arduino UNO:
#define SENSOR3PIN 3 // SENSOR1PIN: This pin is connected by a green wire to the beam-break sensor's "SIG" pin.
#define SOLENOID1PIN 8
int sensor3State = HIGH; // variable for reading the beam-break sensor3 status
int moveOperationCounter3 = 0; // This variable keeps track of the total number of "move" operations performed.
SolenoidState solenoid1State = CLOSED; // reflects the open/closed state of the solenoid
/* Water 2 config:
*/
#define SENSOR4PIN 6 // SENSOR1PIN: This pin is connected by a green wire to the beam-break sensor's "SIG" pin.
#define SOLENOID2PIN 11
int sensor4State = HIGH; // variable for reading the beam-break sensor4 status
int moveOperationCounter4 = 0; // This variable keeps track of the total number of "move" operations performed.
SolenoidState solenoid2State = CLOSED; // reflects the open/closed state of the solenoid
/*
After a beam-break, the solenoid opens for SolenoidOpenDuration to allow water to be dispensed.
Following SolenoidOpenDuration, the solenoid is closed (stopping the flow of water) for at least SolenoidPostDoseClosedDuration before re-opening.
*/
unsigned long lastSolenoidOpenTimer1 = 0; // This variable keeps track of the last time the Solenoid1 "open" operation was performed
unsigned long lastSolenoidCloseTimer1 = 0; // This variable keeps track of the last time the Solenoid1 "close" operation was performed
unsigned long lastSolenoidOpenTimer2 = 0; // This variable keeps track of the last time the Solenoid2 "open" operation was performed
unsigned long lastSolenoidCloseTimer2 = 0; // This variable keeps track of the last time the Solenoid2 "close" operation was performed
// Function Prototypes:
void setupWaterDispensers();
void loopWaterDispensers(unsigned long currentLoopMillis);
void closeSolenoid(int waterPortNumber);
void openSolenoid(int waterPortNumber);
// Called from setup()
void setupWaterDispensers() {
// initialize the sensor pins as an input:
pinMode(SENSOR3PIN, INPUT);
digitalWrite(SENSOR3PIN, HIGH); // turn on the pullup
pinMode(SENSOR4PIN, INPUT);
digitalWrite(SENSOR4PIN, HIGH); // turn on the pullup
// Setup Solenoids
pinMode(SOLENOID1PIN, OUTPUT);
//digitalWrite(SOLENOID1PIN, LOW);
pinMode(SOLENOID2PIN, OUTPUT);
//digitalWrite(SOLENOID2PIN, LOW);
}
//allows independent solenoid operation (simultaneous)
void loopWaterDispensers(unsigned long currentLoopMillis) {
// For any open solenoid, check to see if it's time to close it.
// If it's not, do nothing.
// For any closed solenoid, check to see if the beam-break sensor is blocked
// If it is, open it.
// Check Water Port 1:
if (solenoid1State == OPEN) {
if (currentLoopMillis - lastSolenoidOpenTimer1 >= SolenoidDoseOpenDuration) {
// Close the solenoid
closeSolenoid(1);
}
}
else { // else the solenoid is CLOSED
// Check if at least SolenoidPostDoseClosedDuration msec have passed since the last solenoid close event (to prevent immediate re-opening).
if (currentLoopMillis - lastSolenoidCloseTimer1 >= SolenoidPostDoseClosedDuration) {
/* Check sensor beam state:
LOW: Sensor Beam is broken
HIGH: Sensor Beam has continuity
*/
// The sensor must have changed state after the end of the last water dispense and timeout period
#if REQUIRE_STATE_CHANGE_BEFORE_SECOND_WATER_DISPENSE
if (lastSensorChangeEvent3 > (lastSolenoidCloseTimer1 + SolenoidPostDoseClosedDuration)) {
#endif
if ((sensor3State == LOW) || (IS_DIAGNOSTIC_MODE && DIAGNOSTIC_SHOULD_CONTINUOUSLY_DISPENSE_WATER)) {
#if ENABLE_LOGGING_SIGNAL_ON_CHANGE
sendLoggingSignal(Water1, ActionDispense);
#endif
openSolenoid(1);
}
#if REQUIRE_STATE_CHANGE_BEFORE_SECOND_WATER_DISPENSE
}
#endif
}
}
// Check Water Port 2:
if (solenoid2State == OPEN) {
if (currentLoopMillis - lastSolenoidOpenTimer2 >= SolenoidDoseOpenDuration) {
// Close the solenoid
closeSolenoid(2);
}
}
else { // else the solenoid is CLOSED
// Check if at least SolenoidPostDoseClosedDuration msec have passed since the last solenoid close event (to prevent immediate re-opening).
if (currentLoopMillis - lastSolenoidCloseTimer2 >= SolenoidPostDoseClosedDuration) {
/* Check sensor beam state:
LOW: Sensor Beam is broken
HIGH: Sensor Beam has continuity
*/
// The sensor must have changed state after the end of the last water dispense and timeout period
#if REQUIRE_STATE_CHANGE_BEFORE_SECOND_WATER_DISPENSE
if (lastSensorChangeEvent4 > (lastSolenoidCloseTimer2 + SolenoidPostDoseClosedDuration)) {
#endif
if ((sensor4State == LOW)) {
#if ENABLE_LOGGING_SIGNAL_ON_CHANGE
sendLoggingSignal(Water2, ActionDispense);
#endif
openSolenoid(2);
}
#if REQUIRE_STATE_CHANGE_BEFORE_SECOND_WATER_DISPENSE
}
#endif
}
}
}
void closeSolenoid(int waterPortNumber) {
int activeSolenoidPin = 0;
if (waterPortNumber == 1) {
activeSolenoidPin = SOLENOID1PIN;
}
else if (waterPortNumber == 2) {
activeSolenoidPin = SOLENOID2PIN;
}
else {
// Should never happen. Would be nice to assert.
Serial.println("----- waterPortNumber Error A! -----");
}
// Actually close the solenoid and save the time it was closed
digitalWrite(activeSolenoidPin, LOW);
if (waterPortNumber == 1) {
lastSolenoidCloseTimer1 = millis();
if (solenoid1State == OPEN) {
solenoid1State = CLOSED; // update the state to closed
moveOperationCounter3++; // when the solenoid is transitioned from opened to closed, count that as a move operation
}
}
else if (waterPortNumber == 2) {
lastSolenoidCloseTimer2 = millis();
if (solenoid2State == OPEN) {
solenoid2State = CLOSED; // update the state to closed
moveOperationCounter4++; // when the solenoid is transitioned from opened to closed, count that as a move operation
}
}
else {
// Should never happen. Would be nice to assert.
Serial.println("----- waterPortNumber Error B! -----");
}
}
void openSolenoid(int waterPortNumber) {
int activeSolenoidPin = 0;
if (waterPortNumber == 1) {
activeSolenoidPin = SOLENOID1PIN;
solenoid1State = OPEN; // update the state to closed before actually closing it (just to avoid another if/elseif/else block)
}
else if (waterPortNumber == 2) {
activeSolenoidPin = SOLENOID2PIN;
solenoid2State = OPEN; // update the state to closed before actually closing it (just to avoid another if/elseif/else block)
}
else {
// Should never happen. Would be nice to assert.
Serial.println("----- waterPortNumber Error A! -----");
}
// Actually close the solenoid and save the time it was closed
digitalWrite(activeSolenoidPin, HIGH);
if (waterPortNumber == 1) {
lastSolenoidOpenTimer1 = millis();
}
else if (waterPortNumber == 2) {
lastSolenoidOpenTimer2 = millis();
}
else {
// Should never happen. Would be nice to assert.
Serial.println("----- waterPortNumber Error B! -----");
}
}