Timing event only when switch is on, and within specific parameters

Hi,

I am a novice with Arduino.

In this project I am using an Arduino nano. I’d like to use a push button switch to control a valve. The valve is to close only after a specified time or time intervals has occurred. It will start with an open valve. The valve has only 2 wires which opens and closes via reverse polarity using a 2-channel relay.

If the button is pressed and held down, print to serial monitor “Switch Press Start Timer”. If the switch is let go, print to the serial monitor “Switch Not Pressed. Timer Reset”. But if the button is pressed and held down for longer than 2 minutes, close the valve and turn on a red LED and stop the loop until reset button is pressed.

If a switch is pressed and held down for 10 seconds or more but less than 30 seconds (only within this time interval. We will call this condition “switch short press”. Have the serial monitor to print “switch short press”.

If the “switch short press” condition occurs 3 times within 15 minutes, close the valve and turn on a yellow LED and stop the loop until reset button is pressed.

With the current code, if the switch is pressed and held down it will start the “Switch Short Press Count” and continue to count up (past 3). Then at the 2-minute mark the valve closes and lights up the Red LED.

I would like it to only count the “Switch Short Press Count” if only the parameters above are seen (switch is pressed and held down for 10 seconds or more but less than 30 seconds).

I would really appreciate any help and advice.

Thank you in advance.


```cpp
const int switchPin = 3;        // Pin to check for 5V
const int ledPinYellow = 5;     // LED pin to indicate 3 switch short press counts
const int ledPinRed = 6;        // LED pin to indicate switch pressed longer than 2 minutes
int switchShortPressCount = 0;  // Counter for switch short presses
unsigned long startTime = 0;    // Timer start time
const int valveOpen = 11;       // Valve open pin
const int valveClose = 12;      // Valve close pin

// previous time for tasks depending upon time.
unsigned long prevTime_T1 = millis();
unsigned long prevTime_T2 = millis();
unsigned long prevTime_T3 = millis();

// time intervals for the tasks
long interval = 120000;     // Interval for valve closure
long interval_T1 = 10000;   // switch pressed for 10 seconds or more
long interval_T2 = 30000;   // switch pressed for 30 seconds or less
long interval_T3 = 900000;  // Interval for 3 switch short presses

void setup() {
  Serial.begin(9600);
  pinMode(switchPin, INPUT);
  pinMode(ledPinYellow, OUTPUT);
  pinMode(ledPinRed, OUTPUT);
  digitalWrite(ledPinYellow, LOW);  // Turn off the LED initially
  digitalWrite(ledPinRed, LOW);     //Turn off the LED initally
  pinMode(valveOpen, OUTPUT);
  pinMode(valveClose, OUTPUT);
  digitalWrite(valveOpen, HIGH);
  digitalWrite(valveClose, HIGH);
}

void loop() {
  digitalWrite(valveOpen, LOW);
  delay(4500);
  digitalWrite(valveOpen, HIGH);
  Serial.println("Valve Open");
  unsigned long currentMillis = millis();
  unsigned long currentTime = millis();
  int voltage = digitalRead(switchPin);  // Read voltage on pin D3

  if (voltage == HIGH && startTime == 0) {
    startTime = currentMillis;  // Set the timer start time when switch is pressed
    Serial.print(startTime);
    Serial.println(" Switch Press Start Timer");
  }

  if (startTime > 0 && voltage == LOW) {
    startTime = 0;  // Reset the timer when switch is not pressed
    Serial.println("Switch Not Pressed. Timer Reset");
  }

  if (startTime > 0 && (currentMillis - startTime) > interval) {
    digitalWrite(valveClose, LOW);
    delay(4500);
    digitalWrite(valveClose, HIGH);
    Serial.println("Valve Closed Until Reset");
    digitalWrite(ledPinRed, HIGH);  // Turn on the LED to indicate valve closed
    for (;;) {
      // Code inside this loop will run indefinitely
    }
  }

  if (voltage == HIGH && currentTime - prevTime_T1 >= interval_T1 && currentTime - prevTime_T2 <= interval_T2) {
    prevTime_T1 = currentTime;
    prevTime_T2 = currentTime;
    switchShortPressCount++;
    Serial.print("Switch Short Press Count:  ");
    Serial.println(switchShortPressCount);

  } else if (currentTime - prevTime_T2 >= interval) {
    prevTime_T2 = currentTime;
  }

  if (switchShortPressCount >= 3 && currentTime - prevTime_T3 >= interval_T3) {
    digitalWrite(valveClose, LOW);
    delay(4500);
    digitalWrite(valveClose, HIGH);
    Serial.println("Valve Closed Until Reset");
    digitalWrite(ledPinYellow, HIGH);

    for (;;) {
      // Code inside this loop will run indefinitely
    }
  }
}

Welcome to the forum

What does the sketch that you have posted do ?

int voltage = digitalRead(switchPin);  // Read voltage on pin D3

How is the switch wired ? I would guess that the switch pin goes HIGH when the button is pressed but what keeps it LOW when it is not pressed ? Have you got a pulldown resistor in place keeping it LOW ?

Hello apogee8

Welcome to the world's best Arduino forum ever.

You can use the delay() function when running a single task on the Arduino.
Mixing the delay() function with a millis() based timer leads to unstable system behaviour.

If you have serval tasks with a dedicated timing behaiviour it is usefull to have time slices based on millis() function.

Take the BlinkWithOutDelay example of the IDE, as mother of all Arduino timers, and use this example to design your timer() function.

This timer() function might provide the following methodes:

start();
stop(),
event();
isRunning();

Have a nice day and enjoy coding in C++.


This is not true, there is nothing unstable happening if you mix them. The results might not be what you wanted, but they will be predictable, if you think hard enough about it.

Please clarify what you mean here. If the button is held down for 2 mins and 10 seconds and then released, will the valve close at 2m0s, while the button is still held down, or will it close at 2m10s when the button is released?

you may be interested in the following for recognizing the times for a button press ... or perhaps it should be release since you won't know how long they've been pressed until released

const byte PinBut = A2;
      byte butState;

const unsigned long TenSecs     =  2000;   // 10 * 1000L;
const unsigned long ThirtySecs  =  5000;   // 30 * 1000L;
const unsigned long TwoMins     = 10000;   // 2 * 60 * 1000L;
      unsigned long msecPeriod;
      unsigned long msecLst;
      unsigned long msec15mins;
      unsigned long msecSecLst;

unsigned secs;
int swCnt;

// -----------------------------------------------------------------------------
void
loop (void)
{
    unsigned long msec = millis ();

    if (msec - msecSecLst >= 1000) {
        msecSecLst = msec;
        Serial.println (secs++);
    }

    if (msecPeriod && msec - msecLst >= TwoMins) {
        msecPeriod = 0;
        Serial.println (" timeout");
    }

    byte but = digitalRead (PinBut); 
    if (butState != but)  {
        butState = but;
        delay (20);         // debounce

        if (LOW == but)  {
            msecLst    = msec;
            msecPeriod = TwoMins;

            Serial.println ("Switch Press Start Timer");
        }
        else if (msecPeriod)  {
            msecPeriod = 0;

            unsigned long dMsec =  msec - msecLst;
            if (TenSecs > dMsec)
                Serial.println ("Switch Not Pressed");
            else if (ThirtySecs > dMsec)  {
                Serial.println ("Switch short press");

                if (0 == swCnt++)
                    msec15mins = msec;
                else if (3 == swCnt)
                    Serial.println (" 3 presses in 15 mins");
            }
        }
    }
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);

    pinMode (PinBut, INPUT_PULLUP);
    butState = digitalRead (PinBut); 
}

recognizing 3 button presses within 15 mins seems more difficult. do you need to keep track of the start time of each button press and evaluate the possibly prior two whenever a button press occurs since the 1st button press may have been > 15 mins ago and the start point is not the time of the 2nd button press.

@apogee8 I tossed your word salad with some magic garlic pseudocode dressing and ask if this is fair:

if OFF
     press say “Switch Press Start Timer”.
     release say “Switch Not Pressed. Timer Reset”.

     pressed for longer than 2 minutes
          close the valve
          turn on a red LED
          -> ON (after button is released?)

if ON
// pressed and held down for 10 - 30 seconds is a “switch short press”
     if “switch short press” 3 times within 15 minutes
          close the valve
          turn on a yellow LED

     if reset
          valve?
          -> OFF

I ask if the valve should be remained closed when the yellow light has been invoked. It is what you said. I'm just trying to make any sense of what you are doing and why your user interface is so obtuse complicate.

Why, for example, does the button pressing during the timed period need to be between ten and thirty seconds?

Do you have plans for "long button press" events other than your very long press to close the valve?

Or plans for "very short press" less than ten seconds?

It would be better if you got all the functions into the specifications before you, or someone, goes to any trouble at all to code this beast.

a7

Not going to happen.  loop() runs continuously and your sketch lives inside loop().  Think about it, if loop() stopped how would you sense any further switch action?

@dougp :

But if the condition above which the OP described is a one-off ‘terminating’ event, then is it not reasonable to effectively ‘stop’ processing with a

while (1).

?

No. Read @apogee8's word salad, or my pseudocode.

turn on a red LED and stop the loop until reset button is pressed.

(then go on and)

If a switch is pressed and held down for 10

After she has the red LED turn on, then the timed period begins where we need to be alive to watch for three presses in fifteen minutes…

Besides, stopping it that way and relying on a total system reset or power cycke is lame.

a7

Hi @apogee8

welcome to the arduino-forum.

Your description is not yet sufficient and shomehow unclear

You should describe each single case that is of interest.
I try to write it in my words

case A
button is pressed down and continiously hold down for more than 2 minutes
actions:

  • close valve
  • switch on red led

case B

  1. button is pressed down and continiously hold down for 11 up to 29 seconds
    store actual time the button is pressed down the first time called FIRST_PRESS_DOWN
    button is released
  2. button is pressed down and continiously hold down for 11 up to 29 seconds
    button is released
  3. button is pressed down and continiously hold down for 11 up to 29 seconds
    button is released store actual time of third button-release called THIRD_RELEASE

calculate difference in time THIRD_RELEASE - FIRST_PRESS_DOWN
if this difference is less than 15 minutes
actions:

  • close valve
  • switch on yellow led
  • wait for reset-button to be pressed

case C
button is pressed down and continiously hold down for less than 2 minutes
what shall happen??

case D
starts in the same manner as case B but button is released within less than 10 seconds
what shall happen?

case E
starts in the same manner as case B but button is released after more than 29 seconds but less than 2 minutes
what shall happen?

case F-1
starts in the same manner as case B

  1. button is pressed down and continiously hold down for 11 up to 29 seconds
    store actual time the button is pressed down the first time called FIRST_PRESS_DOWN
    button is released
    after first button-release the second button-press occurs
    but button is released after more than 29 seconds but less than 2 minutes
    what shall happen?

variant F-2
after first button-release the second button-press occurs
but button is released after less than 10 seconds
what shall happen?

Are these really such long button-presses?
or
is this some kind of signal sometimes longer some times shorter?

You should describe the real application. What this is all about.
This will help a lot to find a suitable solution

best regards Stefan

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