Delay in library, noob question

so this is a really noobish question but not something ive come across.

if a library included in a sketch

#include librarywithdelay.h

would the delay function within the library still halt the main sketch?

essentially i'd like to convert this into a library for use in another sketch

// LED Fire Effect

int ledPin1 = 1;
int ledPin2 = 0;


void setup()
{
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);

}

void loop() {
analogWrite(ledPin1, random(120)+135);
analogWrite(ledPin2, random(120)+135);
delay(random(100));
}

Code is executed step by step, or should I say: statement by statement.
If a delay() is executed then everything waits. It does not matter if that delay() is in the library or in the sketch.
So yes, if a function from a library is called and that function has a delay, then everything waits.

With C++, a library is often a class. That is a convenient way to put code and variables together and easy re-use it.

You really don't want delay() statements anywhere in your code.

As @Koepel has said, a Class is a fairly easy way to achieve what you want. You just need to keep track of the timing for each object.

Consider the following example (note that the pins you use need to be PWM capable).

class flame
{
  public:
    flame();                              // Constructor method     
    void begin(int pinPassed);            // Initialisation.    
    void flicker();                       // Method to flicker the flame.
    
  private:
    int           pin;                    // GPIO pin of this flame.
    unsigned long timer;                  // Last time this flame brightness was changed.
};

flame::flame()                            // Constructor (does nothing special).
{}

void flame::begin(int pinPassed)          // Initiailise the flame.
{
  pin = pinPassed;                        // Set the pin for this flame.
  pinMode(pin, OUTPUT);                   // Set pin mode to OUTPUT.
  timer = millis();                       // Start the timer for this flame.

}

void flame::flicker()                     // Flicker the flame if required                   
{
  unsigned long now = millis();           // Get current time.
  if (now - timer > 100)                  // Has enough time passed since last flickered?
  {
    timer = now;                          // Reset the timer.
    analogWrite(pin, random(200) + 55);   // Change the brightness of the LED.
  }
}





flame flame1;
flame flame2;

void setup() 
{
  flame1.begin(5);
  flame2.begin(6);
}

void loop() 
{
  flame1.flicker();
  flame2.flicker();
}

@red_car I'm curious to know why you didn't just use pinPassed in pinMode(), but went via an extra variable, pin. Is there a technical reason for that or is it a convention?

I'm also curious. There is no need for it; only thing one should not do is call pinMode in the constructor.

No real reason... probably just habit.

I could have used pinPassed in this instance to set the pinMode. If pin is required by some other method in the future it is now available as a class variable.

That would also be the case if you passed the pin in the constructor. Or am i missing it?

No, you're correct... that would have been more economical. I guess the intent of my post was to show the OP that they should/could avoid using delay in their library/Class, rather than the best way to instantiate a class object.

One other thing I noticed @red_car is that the constructor, begin and flicker are coded below the closing }; of the class. In my limited experience I've only ever seen them above that }; .... does it matter?

    unsigned long timer;                  // Last time this flame brightness was changed.
};
// flame, begin and flicker are below this }; ...
flame::flame()                            // Constructor (does nothing special).
{}

Doesn't that put them "outside" the class?

edit... although I just looked at other examples where they are above the closing }; and they don't have the "classname::" in front. So would I be right to say that if they are inside the class braces {}; they don't need the "classname::" thing, and if they are outside (below the }; ) they do?

Yep pretty much.

:: is the scope resolution operator - typically used between a class name and a class method.

Thanks @red_car I meantime did some experimenting with some old code, and found that the other thing is that if the methods are outside the class {};, then they need to be declared in the class first, as you did in public:. I guess that's so that it knows to expect them (so to speak) below the closing };

It's a matter of taste which way one does it? Seems a little neater to me, to do it the way you did it, rather than have a mile of code inside the class {};

That's clarified some class-related confusions I had. Sorry to OP @secretreeve for hijacking.... but perhaps it's helped you as well :wink:

There's a lot of things when coding that are a matter of taste for sure :slight_smile:

The other consideration... is that in OO Programming there is school of thought that says "One does not need to know how it is implemented, he/she should only know the interface"... so the declaration and implementation are often separated into separate files.

The true test... in my humble opinion.. is when someone has to maintain that code in a year's time... that's when you realise what good and bad code is. That someone else is often you.. so pays to make it understandable when you write it... there is no other time when you will understand it better.

Largely as an exercise for myself, but perhaps of help to OP @secretreeve I took @red_car's code from post #4 and put the class in a library, attached hereto fwiw.

flame.zip (1.7 KB)

edit: I used the explanation in the playground:

Great way to learn... do.

It made it clear that your way of declaring the methods inside the class {}; and then putting the code below with the :: thingies makes for an easier way of making the .h and .cpp files than if everything was in the {}; to start. The {}; stuff goes into the .h, the rest into the .cpp and add a few #defines. Simples.

Interesting exercise; thanks @red_car for the initial code.