@downriver_bob (downriver_bob) posted a new topic, subject "Delay-off Timer". It read:

   Hi All,
    
    I'm trying to have a relay activated when an input goes low, then stay activated for a time after the input goes high again. I have tried all kinds of combinations but can't get this functionality. Code below.
    
    Thanks for any help.
    [code] 
        /*
        
        */
        
        int in1Pin = 8;
        int in2Pin = 9;
        int in3Pin = 10;
        int in4Pin = 11;
        
        int out1Pin = 4;
        int out2Pin = 5;
        int out3Pin = 6;
        int out4Pin = 7;
        
        int in1Status;
        byte in2Status;
        byte in3Status;
        byte in4Status;
        
        byte out1Status;
        byte out2Status;
        byte out3Status;
        byte out4Status;
        
        int lastIn1Status;
        
        unsigned long out1Delay;
        
        unsigned long currentMillis = 0;
        
        
        
        
        void setup() {
        
          pinMode(in1Pin, INPUT_PULLUP);
          pinMode(in2Pin, INPUT_PULLUP);
          pinMode(in3Pin, INPUT_PULLUP);
          pinMode(in4Pin, INPUT_PULLUP);
        
          pinMode(out1Pin, OUTPUT);
          pinMode(out2Pin, OUTPUT);
          pinMode(out3Pin, OUTPUT);
          pinMode(out4Pin, OUTPUT);
        
          digitalWrite(out1Pin, 1);
          digitalWrite(out2Pin, 1);
          digitalWrite(out3Pin, 1);
          digitalWrite(out4Pin, 1);
        }
        
        void loop() {
        
          in1Status = digitalRead(in1Pin);
          currentMillis = millis();
          
          if (in1Status == 0)
          {
            digitalWrite (out1Pin, 0);
          }
        
          if (in1Status == 1)
          {
            out1Delay = currentMillis;
            //digitalWrite (out1Pin, 0);
            
          }
        if (currentMillis - out1Delay >= 1000)
            {
              digitalWrite (out1Pin, 1);
            }
          lastIn1Status = in1Status;
        }
        
    [/code]

To which @Idahowalker (Idahowalker) replied

    downriver_bob:
    
    > `currentMillis = millis();`
    
    How many millis pass per loop? Not many. Your code does not give millis() time to advance a 1000ms.

@gcjr (greg) replied

    while the input is low, repeatedly set a target time to release the relay (msecTarg = currentMillis + 1000) as well as setting the relay.
    
    you can use digitRead () to determine if the relay is set. if it is, check if the target time is reached (if (currentMillis > msecTarg). if it is, release the relay which will also prevent further checking

To which @johnwasser (johnwasser) replied

    Really close. The problem is that you are resetting out1Delay whenever the input is HIGH, even if the timer was already running. You also check for the end of the timer even if the timer has not been started.
    [code] 
          in1Status = digitalRead(in1Pin);
        
          if (in1Status == LOW)
          {
            digitalWrite (out1Pin, LOW);
            out1Delay = 0;
          }
        
          if (out1Delay == 0 && in1Status == HIGH)
          {
            out1Delay = currentMillis;
            //digitalWrite (out1Pin, LOW);
          }
        
          if (out1Delay != 0 && currentMillis - out1Delay >= 1000)
          {
            digitalWrite (out1Pin, HIGH);
            out1Delay = 0;
          }
        
    [/code]
    
    Note: If you are going to do the same thing for four sets of inputs and outputs you should use arrays or an array of structures to avoid writing the same code four times.
    [code] 
        /*
        
        */
        
        int inPins[] = {8, 9, 10, 11};
        int outPins[] = {4, 5, 6, 7};
        unsigned long outDelays[4];
        
        void setup()
        {
          for (int i = 0; i < 4; i++)
          {
            pinMode(inPins[i], INPUT_PULLUP);
            pinMode(outPins[i], OUTPUT);
            digitalWrite(outPins[i], HIGH);
            outDelays[i] = 0; // Not really needed.  Globals default to 0
          }
        }
        
        void loop()
        {
          unsigned long currentMillis = millis();
        
          for (int i = 0; i < 4; i++)
          {
            int inStatus = digitalRead(inPins[i]);
        
            if (inStatus == 0)
            {
              digitalWrite (outPins[i], LOW);
              outDelays[i] = 0;
            }
        
            if (outDelays[i] == 0 && inStatus == 1)
            {
              outDelays[i] = currentMillis;
              //digitalWrite (outPins[i], LOW);
            }
        
            if (outDelays[i] != 0 && currentMillis - outDelays[i] >= 1000)
            {
              digitalWrite (outPins[i], HIGH);
              outDelays[i] = 0;
            }
          }
        }
    [/code]

@downriver_bob (downriver_bob) replied

    Hi John,
    
    Thanks for posting this, I've uploaded it, the relay activates, but doesn't deactivate again. Any ideas on this?

After which, @downriver_bob (downriver_bob) added

    Actually, my mistake. Copying the first section you posted into my existing sketch didn't work, but copying everything in the second section into a new sketch worked perfectly.
    
    Thanks!

@system (system) replied

    This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.


{'source': 'discourse', 'url': 'https://forum.arduino.cc/t/delay-off-timer/911214', 'title': 'Delay-off Timer', 'views': 370, 'has_accepted_answer': False, 'word_count': 529, 'like_count': 0, 'reply_count': 2, 'participant_count': 4, 'posts': 7, 'tags': '', 'author': '@downriver_bob (downriver_bob)', 'participants': '@downriver_bob (downriver_bob), @Idahowalker (Idahowalker), @gcjr (greg), @johnwasser (johnwasser), @system (system)', 'image_url': [None], 'created_at': '2021-10-03T00:30:47.609Z', 'last_posted_at': '2022-04-01T01:31:36.168Z'}