Help with passing variable to a function and updating variable value

Hi guys,

so the story goes that I notice that I been using millis() function extensively in my coding for a while now. As recommended by blink without delay, I use this line a lot in my code

if ( timeNow - timePrev >= interval )

Usually I would declare those variable as a local variable in void loop as so

void loop()
{
  const unsigned long interval = 500;
  static unsigned long timePrev = 0 ;
  unsigned long timeNow = millis();
  if ( timeNow - timePrev >= interval )
  {
    timePrev = timeNow;
  }
}

so i was thinking to refactor this line into a function

  if ( timeNow - timePrev >= interval )
  {
    timePrev = timeNow;
  }
}

into something like this

boolean timeElapse( unsigned long timeNow, unsigned long timePrevious, unsigned long timeDelay)
{
  if ( timeNow - timePrevious >= timeDelay )
  {
    timePrev = timeNow;
    return 1;
  }
  return 0;
}

so now when i tested the code, timePrev will not change unless I put timePrev as a global variable, and I do think its not as robust as i would like to use it as one possible reuse of the function. to demonstrate what i mean lets say i have 2 timer

void loop()
{
  const unsigned long timeInterval_A = 300;
  const unsigned long timeInterval_B = 500;
  static unsigned long timePrev_A = 0 ;
  static unsigned long timePrev_B = 0 ;
  unsigned long timeNow = millis();
  
  timeElapse( timeNow, timePrev_A, timeInterval_A);
  timeElapse( timeNow, timePrev_B, timeInterval_B);
}

is I could say both timePrev_A, and timePrev_B is not updated to the value of timeNow when this function is called.

So my question is that how do I able to call this function to return a boolean and also update the TimePrevious ( in my example ) ?

any help and suggestion are most welcome. many thank you in advance

See if you can follow these examples:

//**********************************************************************
unsigned long counter = 0;
unsigned long Millis13 = millis();
unsigned long currentMillis = millis();

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

  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);

} //  >>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  if(CheckTime(Millis13,1000UL,true))
  {
  digitalWrite(13, !digitalRead(13));
  }  
  
  if(digitalRead(2) == 0)
  {
    Serial.println(++counter);
  }
  

} //  >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<


//======================================================================
//                      F U N C T I O N S
//======================================================================


//**********************************************************************
//Delay time expired function
//lastMillis = time we started, wait = delay in mS, restart = do we start again  
boolean CheckTime(unsigned long &lastMillis, unsigned long wait,boolean restart) 
{
  //is the time up for this task?
  if (currentMillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //get ready for the next iteration
      lastMillis = millis();  //get ready for the next iteration
    }
    return true;
  }
  return false;

} // END of CheckTime()


//**********************************************************************

//======================================================================
//                      E N D  O F  C O D E
//======================================================================

//Blink without Delay skeleton example using a structure.
//LarryD

//LED wiring options
//=============================================

//#define PlusEqualsON //uncomment to invert

#ifdef PlusEqualsON
//wired so +5V turns LED ON
#define ledON  HIGH
#define ledOFF LOW
//=========================
#else
//wired so +5V turns LED OFF
#define ledON  LOW
#define ledOFF HIGH

#endif

//======================================================================
struct timer
{
  //lastMillis = the time this "timer" was (re)started
  //waitMillis = delay time (mS) we are looking for
  //restart    = do we start "this timer" again and again  
  //enableFlag = is "this timer" enabled/allowed to be accessed
  //**********************
  //For each timer object you need: 
  //Example:
  //   timer myTimer = //give the timer a name "myTimer"
  //   {
  //     0, 200UL, true, true  //lastMillis, waitMillis, restart, enableFlag 
  //   };
  // You have access to: 
  // myTimer.lastMillis, myTimer.waitMillis, myTimer.restart, myTimer.enableFlag, myTimer.CheckTime() 
  //**********************

  unsigned long lastMillis; 
  unsigned long waitMillis; 
  bool          restart; 
  bool          enableFlag;
  bool CheckTime() //Delay time expired function "CheckTime()"
  {
    //is the time up for this task?
    if (enableFlag && millis() - lastMillis >= waitMillis) 
    //Note: if delays of < 2 millis are needed use micros() and adjust waitMillis as needed
    {
      //should this start again? 
      if(restart)
      {
        //get ready for the next iteration
        lastMillis = millis();   
      }
      //time was reached
      return true;
    }
    //time was not reached
    return false;
    
  } //END of CheckTime()

}; //END of structure timer
//======================================================================


//**********************************************************************
//Let's create 6 timer objects and initialize them in this sketch
//**********************************************************************
timer pin13 = //create timer pin13
{
  0, 200UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin12 = //create timer pin12
{
  0, 3000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin11 = //create timer pin11
{
  0, 10000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin10 = //create timer pin10
{
  0, 6000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer Toggle10 = //create timer Toggle10
{
  0, 50UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer checkSwitches = //create timer checkSwitches
{
  0, 50UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************

byte lastMySwitchState = 1; //for mySwitch on Pin 2
byte counter           = 0; 

const byte Pin13 = 13;
const byte Pin12 = 12;
const byte Pin11 = 11;
const byte Pin10 = 10;
const byte Pin9  =  9;

const byte mySwitch = 2;

//**********************************************************************

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

  pinMode(Pin13,OUTPUT);
  pinMode(Pin12,OUTPUT);
  pinMode(Pin11,OUTPUT);
  pinMode(Pin10,OUTPUT);
  pinMode(Pin9, OUTPUT);

  digitalWrite(Pin13,LOW);
  digitalWrite(Pin12,LOW);
  digitalWrite(Pin11,LOW);
  digitalWrite(Pin10,LOW);
  digitalWrite(Pin9, LOW);

  pinMode(mySwitch,INPUT_PULLUP);


} //  >>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  //Below are examples demonstrating different timing situations 

  //***************************
  //example 1    Toggle Pin13 every 200ms
  if (pin13.CheckTime())
  {
    //Toggle Pin13
    digitalWrite(Pin13,!digitalRead(Pin13));

    //if you only want this section of code to happen once
    //uncomment the next line 
    //pin13.enableFlag = false;
  }

  //***************************
  //example 2    After 3 seconds, Pin12 goes and stays HIGH 
  if (pin12.CheckTime())
  {
    //Pin12 HIGH now
    digitalWrite(Pin12,HIGH);
    //disable timing section of code 
    pin12.enableFlag = false;
  }

  //***************************
  //example 3    Pin11 is HIGH for 10 seconds, then goes and stays LOW
  //if (pin11.enableFlag && !pin11.CheckTime())
  if (!pin11.CheckTime())
  {
    digitalWrite(Pin11,HIGH);
  }
  //10 seconds is now up now, leave the Pin11 LOW
  else
  {
    digitalWrite(Pin11,LOW);
    //disable timing section of code 
    pin11.enableFlag = false;
  }

  //***************************
  //example 4    For 6 seconds, toggle Pin10
  //if (pin10.enableFlag && !pin10.CheckTime())
  if (!pin10.CheckTime())
  {
    //example 5  Toggling Pin10 every 50mS
    if(Toggle10.CheckTime())
    {  
      //toggle Pin10
      digitalWrite(Pin10,!digitalRead(Pin10));    
    }
  }
  //6 seconds is now up, stop toggling, toggle at 100ms
  else
  {
    digitalWrite(Pin10,LOW);
    //disable timing section of code 
    pin10.enableFlag = false;
  }

  //***************************
  //example 6    Is it time to check the switches?
  if (checkSwitches.CheckTime())
  {
    //time to read the switches
    Switches();      
  } 

  //**********************************
  //Put other non-blocking stuff here
  //**********************************

} //  >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<


//======================================================================
//                      F U N C T I O N S
//======================================================================


//**********************************************************************
//switches are checked every checkSwitches.waitMillis milli seconds 
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void Switches()  
{
  boolean thisState; //re-usable for all the switches      

  //****************************************** mySwitch Pin 2 code  
  //check if this switch has changed state
  thisState = digitalRead(mySwitch); 
  if (thisState != lastMySwitchState)
  {  
    //update the switch state
    lastMySwitchState = thisState;  

    //This switch position has changed, let's do some stuff

    //"HIGH condition code"
    //switch goes from LOW to HIGH
    if(thisState == HIGH)        
    {
      //example: LED on Pin9 is Push ON, Push OFF
      digitalWrite(Pin9,!digitalRead(Pin9)); 
    }

    //"LOW condition code"
    //switch goes from HIGH to LOW
    else                          
    {
      //example: display the current switch push count 
      Serial.println(++counter);      
    }
  } //END of mySwitch Pin 2 code

  //******************************************  
  //similar code for other switches goes here 
  //******************************************  

} //END of Switches()


//======================================================================
//                        E N D  O F  C O D E
//======================================================================

[/code]

In old-style C you would use a pointer to pass-by-reference instead of pass-by-value:

void loop() {
  const unsigned long interval = 500;
  static unsigned long timePrev = 0 ;
  unsigned long timeNow = millis();
  if (timeElapse(timeNow, &timePrev, interval){
   // Do Stuff
  }
}

boolean timeElapse( unsigned long timeNow, unsigned long *timePrevious, unsigned long timeDelay) {
  if ( timeNow - *timePrevious >= timeDelay ) {
    *timePrevious = timeNow;
    return 1;
  }
  return 0;
}

In modern C and C++ you can use a 'reference':

void loop() {
  const unsigned long interval = 500;
  static unsigned long timePrev = 0 ;
  unsigned long timeNow = millis();
  if (timeElapse(timeNow, timePrev, interval) {
   // Do Stuff
  }
}

boolean timeElapse( unsigned long timeNow, unsigned long &timePrevious, unsigned long timeDelay) {
  if ( timeNow - timePrevious >= timeDelay ) {
    timePrevious = timeNow;
    return 1;
  }
  return 0;
}

@LarryD :

Hey thanks for both example, I will study them both and if I have any problem understanding them, I will get back to you

I love that the first example you gave, It shows the simplicity of the code while at the same time allow for a much complex behaviour. For the second example I still in the process of understanding it.

As a thank you token, you deserves a Karma

@johnwasser:

Wow, just by putting a "*" or "&" the function work as I wanted. I know pointer, reference are the strength of C++, after all this years I still find it hard to wrap my head around pointer and also polymorphism too.

Johnwasser you too receive Karma as a thank you token.

Maybe I should change the Topic as SOLVE?