Switch a fan on for 5 seconds and then turn off

Hi everyone,
I'm working on project which involves pressing a button and a fan turns on for 5 seconds before turning. While I was able to turn the fan on by pressing the button, I was unable to turn it off after 5 seconds.

Any help is appreciated.

Here's the code:

int buttonPin = 2;
int relayPin = 3;
int relayState = HIGH;
int buttonState; //record the current button state
int lastButtonState = LOW; // record the last button state
long lastDebounceTime = 0; 
long debounceDelay = 50; // eliminate debounce time


void setup() {
  pinMode(buttonPin,INPUT);
  pinMode(relayPin, OUTPUT);

  digitalWrite(relayPin, relayState); // configure the initial state of relay

}

void loop() {
  int reading = digitalRead(buttonPin); //read the value of button

  //once detects change of state, record time
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  // wait for 50ms to evaluate if it is the same state as last state
  // if different, change the button state
  // if the state of button is high(pressed), change the state of relay
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        relayState = !relayState;
        
      }
    }
  }
  digitalWrite(relayPin, relayState);

  //change the last state of button
  lastButtonState = reading;
  
}



Instead of toggling the relayState when a button is pressed, set it to HIGH (assuming the relay is activated with a HIGH signal) and 'start a timer'.

The below code is based on your code; it gives the fleibility to use active HIGH or active LOW relay.

// defines if relay is active when a the pin is set HIGH; change HIGH to LOW if the relay activates with a LOW signal
#define ACTIVE HIGH

int buttonPin = 2;
int relayPin = 3;
int relayState = HIGH;
int buttonState; //record the current button state
int lastButtonState = LOW; // record the last button state

// changed long to unsigned long; millis() based timings should use unsigned variables
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // eliminate debounce time

// duration that relay must be on
const unsigned long duration = 5000;

void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(relayPin, OUTPUT);

  digitalWrite(relayPin, relayState); // configure the initial state of relay

}

void loop()
{
  
  static unsigned long startTime;

  if (relayState != ACTIVE)
  {
    int reading = digitalRead(buttonPin); //read the value of button

    //once detects change of state, record time
    if (reading != lastButtonState)
    {
      lastDebounceTime = millis();
    }

    // wait for 50ms to evaluate if it is the same state as last state
    // if different, change the button state
    // if the state of button is high(pressed), change the state of relay
    if ((millis() - lastDebounceTime) > debounceDelay)
    {
      if (reading != buttonState)
      {
        buttonState = reading;

        if (buttonState == HIGH)
        {
          // 'start' a timer
          startTime = millis();
          // set the relay state to active
          relayState = ACTIVE;
        }
      }
    }
    //change the last state of button
    lastButtonState = reading;
  }
  else
  {
    // check if time is over
    if (millis() - startTime > duration)
    {
      // set the relay state back to inactive
      relayState = !ACTIVE;
    }
  }

  digitalWrite(relayPin, relayState);
}

I have also fixed a minor issue in your original code regarding long / unsigned long.

Compiles, not tested.

Note:
relayState is also used as a flag to check if the relay is active; if the relay is active, the button is not checked.

Thank you so much for helping me!

There was a slight problem the code as the fan turning off for 5 seconds before turning on but I was able to fixed it by defining active and relayState as low.

consider

#undef MyHW
#ifdef MyHW
int buttonPin = A1;
int relayPin  = 10;
#else
int buttonPin = 2;
int relayPin  = 3;
#endif

enum { Off = LOW, On = HIGH };  // relay on when HIGH

byte buttonState; //record the current button state

#define RelayPeriod     5000    // change to 5 * 60 * 1000
unsigned long  msecRelay;
int  relayState = Off;

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

    // check for button press
    byte but = digitalRead (buttonPin);
    if (buttonState != but) {
        buttonState = but;
        delay (50);                         // debounce

        if (LOW == but)  {
            if (On == digitalRead (relayPin))  {
                digitalWrite (relayPin, Off);
                relayState = 0;
            }

            else  {
                digitalWrite (relayPin, On);
                relayState = 1;
                msecRelay = msec;
            }
        }
    }

    if (relayState && (msec - msecRelay) >= RelayPeriod)  {
        // turn off
        digitalWrite (relayPin, Off);
        relayState = 0;
    }
}

void setup () {
    pinMode (buttonPin, INPUT_PULLUP);
    buttonState = digitalRead (buttonPin);

    digitalWrite (relayPin, Off);
    pinMode (relayPin, OUTPUT);
}