Simple User Input, Delay and Loop Delay


after you switch on the fan wait for the transmitter switch to go low, e.g.

  // When you key the transmitter, this happens
  else {
    digitalWrite(5, HIGH);  // BOARD OUTPUT PIN 5
    while(switchState == HIGH);  // wait for low
    // wait before turning off again
    delay(5000); // seconds fan ON
    digitalWrite(5, LOW); // BOARD OUTPUT PIN 5 - Turn FAN off again and start new cycle

while(switchState == HIGH); Errm…

while(switchState == HIGH); Errm...

your right ! I guess it should be

while(digitalRead(6) == HIGH);  // wait for low

the while is blocking the whole microcontroller. The microcontroller is busy and can do nothing else until
the condition becomes false

below I post a code-version that uses non-blocking timing.
This enables that the microcontroller can execute any other commands and still does a timed switching.
I added also some basic coding-techniques that make it easier to read the code and make it easier to maintain
and less error-prone.

Whenever possible use self-explaining names. In case of constants defining constants means:
there is only one place to change the number if needed less work, less error-prone.
You just read the names instead of (not) remembering IO-pin 5 was … and no additional comment needed

I don’t have an Arduino and switches handy right now. So I haven’t tested the code.
It compiles.

// Create a global variable to hold the state of the switch. This variable is
// persistent throughout the program. Whenever you refer to switchState, you're
// talking about the number it holds

const byte FAN_IO_Pin = 5; // only place to change number => easier to maintain
const byte PTT_IO_Pin = 6; // only place to change number => easier to maintain

int switchState = 0;

unsigned long KeepFanON_Timer;
unsigned long CoolingTimeMs;
boolean CoolingPeriodStarted;
boolean CoolingPeriodOver;

boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod )
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  else return false;            // not expired

void setup() {
  // declare the pins as outputs
  pinMode(FAN_IO_Pin, OUTPUT); // with self-explaining name no comment needed
  digitalWrite(FAN_IO_Pin, LOW);
  // declare the pins as inputs
  pinMode(PTT_IO_Pin, INPUT);
  CoolingPeriodStarted = false;
  CoolingPeriodOver    = true;
  CoolingTimeMs        = 15000;

void loop() {
  // Create a global variable to hold the state of the switch. This variable is
  // persistent throughout the program. Whenever you refer to switchState, you're
  // talking about the number it holds

  // FAN Delay Control - Triggered by the transmitter PTT output
  // digitalRead() checks to see if there is signal on the pin or not
  switchState = digitalRead(PTT_IO_Pin);

  // if-condition #1
  // only if there is no transmission AND additonal cooling-time is over
  if (  (switchState == LOW)  && CoolingPeriodOver) {
    digitalWrite(FAN_IO_Pin, LOW);  // switch Fan OFF

  // if a new transmission has started (CoolingPeriodStarted is false and !false delivers true
  if (  (switchState == HIGH)  && !CoolingPeriodStarted) {
    CoolingPeriodStarted = true;   // immediately set CoolingPeriodStarted to avoid condition above to be true again
    CoolingPeriodOver    = false;  // Cooling-fan shall run
    digitalWrite(FAN_IO_Pin, HIGH);  
    KeepFanON_Timer = millis(); // initialise Timer when cooling starts

  if (CoolingPeriodStarted) {
    if (TimePeriodIsOver(KeepFanON_Timer,CoolingTimeMs) ) {
      CoolingPeriodStarted = false;
      CoolingPeriodOver    = true;  // this flag set true will switch OFF the fan in if-condition #1

So if you would like to use this codeversion please test with care if the cooling fan switches really on

best regards Stefan

if none blocking is required the following may work

void loop() {
   static long int delayTime=0;
   if(digitalRead(SWITCH)){               // switch pressed ?
          digitalWrite(FAN, HIGH);        // fan ON
          delayTime=millis();             // start timer
    else if((millis()-delayTime) > 5000)  // delay elapsed?
          digitalWrite(FAN, LOW);         // fan OFF
    // do othet things?

or you could use a state machine

Hi horace,

this is very elegant solution for this functionality using much less lines of code to create the same thing.
Though I have a question:
is variable type long int exactly the same as unsigned long?

The rollover of function millis() needs an unsigend long to make the calculation work correctly in case of a rollover from 2^32 - 1 to 0.

best regards Stefan

you are correct! it should be unsigned long int, e.g.

void loop() {
   static unsigned long int delayTime=0;
   if(digitalRead(SWITCH)){               // switch pressed ?
          digitalWrite(FAN, HIGH);        // fan ON
          delayTime=millis();             // start timer
    else if((millis()-delayTime) > 5000UL)  // delay elapsed?
          digitalWrite(FAN, LOW);         // fan OFF
    // do othet things?