Run the relay once in loop after buttonpress [solved]

Hello,

Is there another way, for example, to trigger a relay once after you press the button. (The code below doesn't work btw)

What I want it to do is after you press the button, the relay turns on for 5 seconds. After the 5 seconds it turns off and doesn't activate even if the relay is still activated UNTIL you release the button and press it again.

bool fHasLooped = false;  

void zaag(){
int switchstate = digitalRead(safety_switch);
  if (switchstate = LOW) {
    if (fHasLooped == false)
    {
      for (int x = 0; x < 1; x++)
      {
        delay(2000);
        digitalWrite(relay, HIGH);
        delay(5000);
        digitalWrite(relay, LOW);
      }

      fHasLooped = false;
    }
  }
  else {
    digitalWrite(relay, LOW);
  }
}

You need to check if the switch has changed state from HIGH to LOW - something like this

static byte switchState = LOW; // assumes LOW when pressed
                // static ensures the value is remembered between iterations of loop()
byte previousSwitchState;
previousSwitchState = switchState; 
switchState = digitalRead(switchPin);
if (switchState == LOW and previousSwitchState == HIGH) {

Note that your use of delay()s will make you program unresponsive. The functions delay() and delayMicroseconds() block the Arduino until they complete. Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

for (int x = 0; x < 1; x++)

Why use a for loop with only 1 step ?

That is because I want to use it multiple times, but only when the button is pressed.

for (int x = 0; x < 1; x++)

I used this because i thought it was possible to force it to run once after activating. (Just wanted to try it out)

Here is a way to do it using library calls.

#include <mechButton.h>

#define  TRIGGER_PIN 2        // What pin the trigger will be on.
#define  OUT_PIN     13       // What pin we'll toggle high when the trigger goes low.
#define  HOLD_MS     500      // How long we'll hold the output high after being triggered.


mechButton  trigger(TRIGGER_PIN);   // Button debouncer.
timeObj     timer;                  // Our output hold timer.


// Your standard Arduino setup() function.
void setup() {
   
   pinMode(OUT_PIN,OUTPUT);               // Setup output pin.
   digitalWrite(OUT_PIN,LOW);             // Lets make sure its off.
   trigger.setCallback(triggerAction);    // Set up the function to call when the trigger is clicked.
   timer.setTime(HOLD_MS,false);          // Set the timer, but don't start it yet.
}


// When you click the button, this function will be called.
void triggerAction(void) {

   if (!trigger.trueFalse()) {      // If the trigger returns false, button has been clicked.
      digitalWrite(OUT_PIN,HIGH);   // So we fire the output pin.
      timer.start();                // And start the timer.
   }
}


// Your standard Arduino loop() function.
void loop() {
   
   idle();                       // Give the stuff running behind the scenes time to run.
   if (timer.ding()) {           // If the timer has expired..
      digitalWrite(OUT_PIN,LOW); // Shut down the output.
      timer.reset();             // Reset the timer for next time.
   }
}

If you would like to try it this way you will need LC_baseTools from your Arduino IDE library manager.

Good luck.

-jim lee

A state machine would seem to fit the bill

enum STATES
{
  WAITING,
  TIMING
};
STATES currentState = WAITING;
const byte buttonPin = 27;
const byte relayPin = 26;
byte currentButtonState;
byte previousButtonState;
unsigned long waitStartTime;
unsigned long currentTime;
unsigned long waitPeriod = 5000;

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);
}


void loop()
{
  currentTime = millis();
  switch (currentState)
  {
    case WAITING:
      previousButtonState = currentButtonState;
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState)  //button state has changed
      {
        if (currentButtonState == LOW)  //button has become pressed
        {
          digitalWrite(relayPin, LOW);
          waitStartTime = currentTime;
          currentState = TIMING;
        }
      }
      break;
    case  TIMING:
      if (currentTime - waitStartTime >= waitPeriod)
      {
        Serial.println("time's up");
        digitalWrite(relayPin, HIGH);
        currentState = WAITING;
      }
      break;
    case RELEASED_AND_TIMING:
      break;
  }
}

Thanks!

I noticed (line 52)

case RELEASED_AND_TIMING:

wasn't in the enum STATES so i added it in.

It works now!

That state was left over from my original idea but is, in fact, not needed. Simply removing it from the sketch completely works

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