Help with "until" loop

"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.

2 Likes