This works but I would like to have a timed failsafe...
If the FLOAT_PIN
goes LOW
for more than 3 seconds, it will turn SOLENOID_PIN
to LOW
.
I can't figure out how to incorporate it into my loop. I tried delay()
and started playing with millis()
but all I keep finding is LED blinking samples...
I'm not very good with C++ - still learning.
const int FLOAT_PIN = 8; // Pin connected to FLOAT switch
const int SOLENOID_PIN = A0; // SOLENOID pin - active-high
void setup() {
Serial.begin(9600);
// Since the other end of the FLOAT switch is connected to ground, we need
// to pull-up the FLOAT switch pin internally.
pinMode(FLOAT_PIN, INPUT_PULLUP);
pinMode(SOLENOID_PIN, OUTPUT);
}
void loop() {
int floatswitch = digitalRead(FLOAT_PIN); // Read the state of the float switch
if (floatswitch == HIGH) {
// If the pin reads high, water is OFF.
Serial.println("Switch closed");
digitalWrite(SOLENOID_PIN, HIGH); // Turn the SOLENOID on
} else {
digitalWrite(SOLENOID_PIN, LOW); // Turn the SOLENOID off
}
}
1 Answer 1
This is one of those cases when thinking in terms of a finite state machine makes the programming quite straightforward. Here I would use three states:
- In the
OFF
state, the switch isLOW
and the solenoid is off - in the
ON
state, the switch isHIGH
and the solenoid is on - in the
DELAYING
state, the switch isLOW
, but the program is keeping the switchHIGH
for three seconds.
The possible transitions are:
OFF
→ON
when the switch goesHIGH
ON
→DELAYING
when the switch goesLOW
DELAYING
→OFF
after three second in this stateDELAYING
→ON
when the switch goesHIGH
.
The last transition is meant to ensure that LOW
states of the switch
that last less than three seconds do not turn the solenoid off.
And here is a tentative implementation. Keep your constants and your
setup()
, and replace your loop()
with this:
const uint32_t DELAY_TIME = 3000; // time to deay the -> off transition
void loop() {
static enum {OFF, ON, DELAYING} state;
static uint32_t start_delay;
int floatswitch = digitalRead(FLOAT_PIN);
switch (state) {
case OFF:
if (floatswitch == HIGH) {
Serial.println("Switch closed");
digitalWrite(SOLENOID_PIN, HIGH); // Turn the SOLENOID on
state = ON;
}
break;
case ON:
if (floatswitch == LOW) {
start_delay = millis();
state = DELAYING;
}
break;
case DELAYING:
if (floatswitch == HIGH) {
state = ON;
}
else if (millis() - start_delay >= DELAY_TIME) {
digitalWrite(SOLENOID_PIN, LOW); // Turn the SOLENOID off
state = OFF;
}
break;
}
}
-
think its backwards. Worked but backwards, it's preventing it from turning off for 3 seconds, rather then turning off if its on for more then 3 seconds.Mike S– Mike S2018年01月01日 21:35:31 +00:00Commented Jan 1, 2018 at 21:35
-
no matter what I do it works one way but not the other... not sure what i did wrong.Mike S– Mike S2018年01月01日 21:45:50 +00:00Commented Jan 1, 2018 at 21:45
-
@MikeS: I can't understand your comment "it's preventing it from turning off for 3 seconds, rather then turning off if its on for more then 3 seconds". I wrote this answer to match your question as written. If this is not the behavior you expect, please, edit your question with a more explicit description of your expectations.Edgar Bonet– Edgar Bonet2018年01月01日 23:14:41 +00:00Commented Jan 1, 2018 at 23:14
-
your example works, but not as intended. Float goes low, turn on solenoid, Float goes high, turns off solenoid but delays 3 seconds once Float is high. The logic about is right, not sure if your states are written correctly. Can it be written outside the loop that Solenoid can only be high for X seconds (no matter the output of the FLOAT?)Mike S– Mike S2018年01月02日 02:02:40 +00:00Commented Jan 2, 2018 at 2:02
-
@MikeS: This works exactly as intended – as I intended it to work based on my understanding of your question. I assume you didn't read my last comment, so let me repeat: please, update your question and add an explicit and clear description of the behaviour you expect.Edgar Bonet– Edgar Bonet2018年01月02日 13:37:08 +00:00Commented Jan 2, 2018 at 13:37
floatFlag
....if floatSwitch == high and floatFlag == false
(floatFlag = true;
tim = currentTime;)
......if floatSwitch == low
(floatFlag == false)
.......if floatFlag == true and currentTime == tim +3 seconds
(turn on valve)