Millis() Instead of Delay Library Questions

Hello!
I have created a libary called Easy. It has 4 classes: schedule events using millis() (Routine), manipulate common cathode RGB LED (RGBled), manipulate LED (EasyLED), and play music on piezo (Song). I am having difficulties with the Routine class. In another thread, I posted the prototype code for the Routine class: http://arduino.cc/forum/index.php/topic,105742.msg793353.html. That code would not work as expected if the extra parameter is removed, because it uses 2 calls to the same function, and the static prev variable is being reset, so only the fading happens.

I then decide to use the new code here: http://arduino.cc/forum/index.php/topic,105742.msg793424.html#msg793424 using the Routine class of the Easy library. It should have blink the LED on pin 13 while fading the LED on pin 9 at the same time.

But, this is what happened: When I use that code LED on pin 13 blinks once, then never blinks again. LED on pin 9 continues to fade as expected, though. This can’t be a static variable resetting, because I used 2 instances of the class.

Easy.h (only showing the Routine class):

#ifndef Easy_h
#define Easy_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class Routine{
  public:
  Routine();
  void begin(unsigned long interval, void (*g)());
  void begin(unsigned long interval, void (*g)(), word times);
  void end();
  void restart();
  void begin_us(unsigned long interval, void (*g)());
  void begin_us(unsigned long interval, void (*g)(), unsigned long times);
  private:
  boolean go;
};

#endif

Easy.cpp (only showing the Routine class):

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "Easy.h"

Routine::Routine(){
  go = true;
}
void Routine::begin(unsigned long interval, void (*g)()){
  static unsigned long prev = 0;
  if (millis() - prev >= interval && go){
    g();
    prev = millis();
  }
}
void Routine::begin(unsigned long interval, void (*g)(), word times){
  static unsigned long prev = 0;
  static word counter = 0;
  if (millis() - prev >= interval && go && counter < times){
    g();
    prev = millis();
    counter++;
  }
}
void Routine::end(){
  go = false;
}
void Routine::begin_us(unsigned long interval, void (*g)()){
  static unsigned long prev = 0;
  if (micros() - prev >= interval && go){
    g();
    prev = micros();
  }
}
void Routine::begin_us(unsigned long interval, void (*g)(), unsigned long times){
  static unsigned long prev = 0;
  static unsigned long counter = 0;
  if (micros() - prev >= interval && go && counter < times){
    g();
    prev = micros();
    counter++;
  }
}
void Routine::restart(){
  go = true;
}

What might be the problem, and how can I improve the code, and fix it so that I can multitask? I am also looking for a way to make it easier to schedule events in the same manner as delay(), but without halting the code.

This can't be a static variable resetting, because I used 2 instances of the class.

What about the statics named "prev"?

Look at the first link in my first post. Reply #1 and Reply #7 talks about it. To calls to the same timer function will use the same prev variable. The second one will cause prev to reset, and the first function will never time out, and will not execute; only the second one will execute. I just talked about the prototype code. In the new code, I use two instances of the same class. Then, calls to begin() in different classes is supposed to cause them to use their own static prev variable, that isn't affected by another function. What am I doing wrong in the library and the new code?

What does "static" mean to you, in respect of a class?

I would like that variable to keep it's value when the function reruns, instead of becoming 0 again (prevent it from being recreated). I could have made it a global variable, but that isn't favorable in my case.

dkl65: I would like that variable to keep it's value when the function reruns, instead of becoming 0 again (prevent it from being recreated). I could have made it a global variable, but that isn't favorable in my case.

In case you hadn't noticed, that is what is known as a 'loaded question' and should prompt you to go research what the static keyword means in the context of a class.

that is what is known as a 'loaded question'

I prefer to think of it as a "thought-provoking question", but yes, that's the sentiment.

I include an illustration

class Fubar {
  public:
    void report (void) {static int x;
                        Serial.print ("this "); 
                        Serial.print ((int)this, HEX);
                        
                        Serial.print (" my x @ 0x"); 
                        Serial.print ((int)&x, HEX);
                        
                        Serial.print (" object x @ 0x"); 
                        Serial.print ((int)&(Fubar::x), HEX);
                        
                        Serial.print (" y @ 0x"); 
                        Serial.print ((int)&y, HEX);
                        
                        Serial.print (" z @ 0x"); 
                        Serial.print ((int)&z, HEX);
                      };
  private:
    int x;
    int y;
    int z;
};

Fubar foo;
Fubar bar;

void setup ()
{
  Serial.begin (9600);
  Serial.print ("foo ");
  foo.report ();
  Serial.println ();
  Serial.print ("bar ");
  bar.report ();
  Serial.println ();
}

void loop (){}

dkl65: I would like that variable to keep it's value when the function reruns, instead of becoming 0 again (prevent it from being recreated). I could have made it a global variable, but that isn't favorable in my case.

Make it a class variable then.

I changed my code to the following:
Easy.cpp:

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "Easy.h"
Routine::Routine(){
  go = true;
  prev = 0;
  prev2 = 0;
  prev_us = 0;
  prev_us2 = 0;
}
void Routine::begin(unsigned long interval, void (*g)()){
  //static unsigned long prev = 0;
  if (millis() - prev >= interval && go){
    g();
    prev = millis();
  }
}
void Routine::begin(unsigned long interval, void (*g)(), word times){
  //static unsigned long prev = 0;
  static word counter = 0;
  if (millis() - prev2 >= interval && go && counter < times){
    g();
    prev2 = millis();
    counter++;
  }
}
void Routine::end(){
  go = false;
}
void Routine::begin_us(unsigned long interval, void (*g)()){
  //static unsigned long prev = 0;
  if (micros() - prev_us >= interval && go){
    g();
    prev_us = micros();
  }
}
void Routine::begin_us(unsigned long interval, void (*g)(), unsigned long times){
  //static unsigned long prev = 0;
  static unsigned long counter = 0;
  if (micros() - prev_us2 >= interval && go && counter < times){
    g();
    prev_us2 = micros();
    counter++;
  }
}
void Routine::restart(){
  go = true;
}

Easy.h:

#ifndef Easy_h
#define Easy_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class Routine{
  public:
  Routine();
  void begin(unsigned long interval, void (*g)());
  void begin(unsigned long interval, void (*g)(), word times);
  void end();
  void restart();
  void begin_us(unsigned long interval, void (*g)());
  void begin_us(unsigned long interval, void (*g)(), unsigned long times);
  private:
  boolean go;
  unsigned long prev;
  unsigned long prev2;
  unsigned long prev_us;
  unsigned long prev_us2;
};

I used 4 private variables for the begin functions. Now it will multitask!