"Blink without Delay" is a good start. The only add on you need is to differentiate the on time from the off time. 20 seconds vs. 60*60-20 seconds.
imho the easiest way is to introduce new constants for intervalOn and intervalOff and modify the used interval everytime you change the state of the pin.
/*
Blink Without Delay - with different intervals
https://forum.arduino.cc/t/turn-on-solenoid-for-certain-duration-every-hour/1228168/4
by noiasca
*/
const uint8_t ledPin = LED_BUILTIN; // the number of the LED pin
const uint32_t intervalOn = 500UL; // interval at which to blink (milliseconds)
const uint32_t intervalOff = 3000UL;
uint32_t interval = intervalOn; // will be changed during runtime
uint32_t previousMillis = 0; // will store last time LED was updated
void timerBlink() {
uint32_t currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // save the last time you blinked the LED
// if the LED is off turn it on and vice-versa:
if (digitalRead(ledPin) == LOW) {
digitalWrite(ledPin, HIGH);
interval = intervalOn; // the interval for the next iteration
} else {
digitalWrite(ledPin, LOW);
interval = intervalOff; // the interval for the next iteration
}
}
}
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
timerBlink();
// do other things non-blocking here
}
additionally I like to put a closed functionality in a separate function. Hence the timerBlink().
When you describe the problem you had with the different times, one might be able to help you.
Imho you could implement a Finite State Machine with 3 States:
IDLE
FLUSH_ACTIVE
FLUSH_WAIT
check in each state the conditions and jump to the next state in your flow.
Something like:
Graphviz Source
digraph G {
graph [
label="Finite State Machine"
labelloc="t"
fontname="sans-serif"
]
node [
style=filled
fillcolor=gray95
fontname="sans-serif"
]
IDLE -> FLUSH_ACTIVE [label="highEye=HIGH" fontsize=10];
FLUSH_ACTIVE -> FLUSH_WAIT [label="after 20s" fontsize=10];
FLUSH_ACTIVE -> IDLE [label="lowEye=HIGH" fontsize=10];
FLUSH_WAIT -> FLUSH_ACTIVE [label="after 60m" fontsize=10];
FLUSH_WAIT -> IDLE [label="lowEye=HIGH" fontsize=10];
}
if you need more help on implementing such a finite state machine, let us know.
