how to use a function several times independently???

Hi,
I search a lot but I’m still lost…

this is the section of my code that I try to make independent:

int lapse(int ON, int OFF){

    static int State;
    static int PreviousTime;

    int Time = State ? OFF : ON;
    int CurrentTime = millis();
 
      if (CurrentTime - PreviousTime >= Time) {
        PreviousTime = CurrentTime;
        State = ! State;
      }

    return State;
    
  }

My goal is to use my lapse(ON,OFF) function multiple time without begin submerge by a other lapse(ON,OFF).

in other word:

void loop() {
  int a = lapse(1000,1000);

  lcd.setCursor(0,0);

  if ( a==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
  

  int b = lapse(2000,2000);

  lcd.setCursor(0,1);

  if ( b==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
}

but that way, my " int b = lapse(2000,2000) " is submerge by my “int a = lapse(1000,1000)”, what I try yo make is (b) switch every 2 second while (a) switch every 1 second and NOT (a) and (b) switch both at 1 second…

can someone help me? PLS?

this is my full code :

#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7);

void setup() {
  lcd.begin(16,2);
  lcd.clear();
}


int lapse(int ON, int OFF){
    static int State;
    int Time = State ? OFF : ON;
    int CurrentTime = millis();
    static int PreviousTime;
      if (CurrentTime - PreviousTime >= Time) {
        PreviousTime = CurrentTime;
        State = ! State;
      }
    return State;
    
  }



void loop() {

 int a = lapse(1000, 1000);
  lcd.setCursor(0,0);
  if (a==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
   int b = lapse(2000, 2000);
  lcd.setCursor(0,1);
  if (b==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }

  
}

You will need to have a separate PreviousTime variable for each of the periods that you are timing and also a separate period for each of them. The neatest way to do this is to use arrays and to pass the values to the function if that is what you want to do.

Personally I would do it all inline without a separate function and use a for loop to iterate through the values

You need to make it a class.

UKHeliBob: You will need to have a separate PreviousTime variable for each of the periods that you are timing and also a separate period for each of them. The neatest way to do this is to use arrays and to pass the values to the function if that is what you want to do.

Personally I would do it all inline without a separate function and use a for loop to iterate through the values

You could also create a struct.

KeithRB: You could also create a struct.

In C++, there is literally no difference at all between structs and classes except the default member scope (class is default private, struct is default public).

Try to define a method in a struct.

KeithRB: Try to define a method in a struct.

What's wrong with that?

You write,

I search a lot but I’m still lost…

This means you’ve searched a lot. Let me explain what your code does RIGHT NOW:

The function you’re calling has variables that it saves. Imagine if a function had a STATIC variable “HowManyTimesHasAnyoneCalledMe”. If you call this function from two different places, they will both increase it.

This is what is happening. This is why the behavior matches. Both places that are calling it end up using the same time stuff.

so here is a simple example. Imagine you were counting button presses, and when you were trying to increase the count for button A you called the function that saved “HowManyTimesHasAnyoneCalledMe” and when you were trying to increase the count for button B you also called the same function.

So whether you pressed A or B they would both increase the counts for both. This is why your timings are matching.

Instead, you need to store those variables separately - you need two versions (or ‘instances’) of the function. Luckily, classes are a good abstraction for that. However, they are not in the official Arduino reference: https://www.arduino.cc/en/Reference/HomePage

Which is why you didn’t find it.

So, I have two options for you:

  1. Learn about classes from C++ references. (The Arduino language is almost C++, it’s like 15 seconds from being C++.) Then you can use it easily. You will make a class, that includes both a function and some variables. Then it can have different copies.

Imagine if integer were a class.

you could do:

integer a;
a.increase();
integer b;
b.increase(); // <— this wouldn’t increase A, because it’s another copy with its own variables.

whereas the current version is more like:

int increase()
{
static integer MyOneCopy;
MyOneCopy = MyOneCopy + 1;
return MyOneCopy;
}

so when you say
int a = 0;
int b = 0;
a = increase(); // a is now 1
b = increase(); // b is now 2, because the function is increasing its own MyOneCopy;
a = increase(); // a is now 3, because the function increase() is increase its own MyOneCopy;

So you see, it’s no good to have increase() have its own one copy. You need a and b to have their own versions.

So, if you had two copies of your object, they wouldn’t share the same state. That’s why you should learn to use objects.


OPTION 2:

  1. If you don’t want to learn how to make a class, you can just copy your function twice. This doesn’t scale very nicely. So a working solution is:
#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7);

void setup() {
  lcd.begin(16,2);
  lcd.clear();
}


int lapseVersionA(int ON, int OFF){
    static int State;
    int Time = State ? OFF : ON;
    int CurrentTime = millis();
    static int PreviousTime;
      if (CurrentTime - PreviousTime >= Time) {
        PreviousTime = CurrentTime;
        State = ! State;
      }
    return State;
    
  }

int lapseVersionB(int ON, int OFF){
    static int State;
    int Time = State ? OFF : ON;
    int CurrentTime = millis();
    static int PreviousTime;
      if (CurrentTime - PreviousTime >= Time) {
        PreviousTime = CurrentTime;
        State = ! State;
      }
    return State;
    
  }


void loop() {

 int a = lapseVersionA(1000, 1000);
  lcd.setCursor(0,0);
  if (a==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
   int b = lapseVersionB(2000, 2000);
  lcd.setCursor(0,1);
  if (b==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }

  
}

This should be a fully working version. It’s not very nice, is it? What if you needed to track ten things - would you have ten versions of the function? lapseVersionA, lapseVersionB, lapseVersionC etc.

But, it’ll work.

So, you could simply start by copying it into different versions, then when you were tired of doing that you could learn how to make a class.

it’s like how you might start by doing

integer1;
integer2;
integer3;

and when you were tired of doing that, learn how to do an array so you can do integer[ i ] and not have to copy so much code.

Unfortunately, the official Arduino language reference doesn’t teach you about Classes. But, you can learn them from any C++ language reference and use them.

I hope you understood all this. The code I gave you in 2 should be working (I didn’t run it) unless I missed something. The second version I gave you should be working perfectly, you can just use it.. I hope I’ve explained why your code isn’t working.

AWOL:
What’s wrong with that?

What’s wrong is I assume too much about C++.

I try with class and it work fine… Thanks for the tips but I have a delay of 3 second (in my case) every time I start the program, like if it’s make a first run without doing anything (1000us + 2000us) after it start fine. But I coundn’t fine and explanation of why it’s doing that?
can someone help me please?

here is my code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);

void setup() {
  lcd.begin(16,2);
  lcd.clear();
}

//Timer classes
class Timer {
  /* private : */ //by default//
    int ON, OFF;
    int State;
    int PreviousTime;
    
  public :
    lapse (int,int);
    int statement();
};

Timer::statement() {
  
  int Time = State ? OFF : ON;
  
  int CurrentTime = millis();
  
    if (CurrentTime - PreviousTime >= Time) {
      PreviousTime = CurrentTime;
      State = ! State;
    }
    
  return State;
}

Timer::lapse(int x, int y) {
    ON = x;
    OFF = y;
    }


void loop() {
  Timer A;
  A.lapse(2000,2000);
  lcd.setCursor(0,0);
  if(A.statement()==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }

  Timer B;
  B.lapse(1000,1000);
  lcd.setCursor(0,1);
  if(B.statement()==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
}

Hey guys I found it thank a lot :wink:

here my code :

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);

void setup() {
  lcd.begin(16,2);
  lcd.clear();
}

//Timer classes
class Timer {
  /* private : */ //by default//
    uint16_t ON, OFF;
    unsigned int State;
    uint16_t PreviousTime;
    uint16_t Time;
    uint16_t CurrentTime;
    
  public :
    lapse (int,int);
    int statement();
};

Timer::statement() {
  
  Time = State ? OFF : ON;
  
  CurrentTime = millis();
  
    if (CurrentTime - PreviousTime >= Time) {
      PreviousTime = CurrentTime;
      State = ! State;
    }
    
  return State;
}

Timer::lapse(int x, int y) {
    ON = x;
    OFF = y;
    }


void loop() {
  Timer A;
  A.lapse(2000,2000);
  lcd.setCursor(0,0);
  if(A.statement()==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }

  Timer B;
  B.lapse(1000,1000);
  lcd.setCursor(0,1);
  if(B.statement()==true) {
    lcd.print("true ");
  } else {
    lcd.print("false");
  }
}