0

I am using the FastLED library in my program and the basic usage is that the following lines go at the top of the main sketch:

#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 6

You can see the documentation at https://github.com/FastLED/FastLED/wiki/Basic-usage

However, I am using the FastLED library in several different objects in my program and I would like to be able to reference NUM_LEDS in different header files for each object so that the number of LEDS can be controlled just by changing the value in the main sketch.

I am also intending that my own objects can be made into libraries for others to use, so they will then define the settings in their main sketch, that my libraries will then use.

  • Sure.. Create a header file containing those three lines (call it, for instance, FastLedInclude.h) and then, in each file you need the FastLed library, write #include "FastLedInclude.h" instead of #include <FastLed.h> – frarugi87 Mar 18 '16 at 12:32
  • This won't work as someone using my library in their own fastLED sketch won't then be able to define their own size of project from the main sketch. I'll alter my question to make sure that is understood. – Rob Hilken Mar 18 '16 at 12:34
  • You will need to have NUM_LEDS defined in every file you compile; that's why you need it in a header file to be included by every cpp or ino file. Now, if you want to make a library, that file should either be in 1) the library folder, or 2) the sketch folder. The second approach is, IMHO, very bad, since it requires the user to create the file in its sketch folder and requires the library to know where the sketch is, which is against the definition of "library", i.e. a piece of code that can work by itself. My personal advice is to ask the user to modify the library file or, if you don't want – frarugi87 Mar 18 '16 at 12:45
  • to force/allow him to modify your files, edit the code using dynamic allocation instead of compile-time static allocation. I mean, instead of defining DATA_PIN you can store a uint8_t variable in your class containing the data pin. You can do the same with NUM_LEDS, and then allocate the matrix dynamically (with mallocs or news) in the code. It can have lower performances, but it will work better – frarugi87 Mar 18 '16 at 12:47
  • That's very helpful. I wonder if I could I ask the user to add const byte numberOfLeds = NUM_LEDS to their sketch and then use numberOfLeds in my library rather than NUM_LEDS ? – Rob Hilken Mar 18 '16 at 12:56
1

As the OP suggested, I'm posting a summing up of the comments under his question since the answer was found.

In order to make a common define for those parameters in different source files, the easiest solution is to make a shared header. To do this, just create a new file called FastLedInclude.h and, inside of that, write

#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 6

Then in every source file you will just have to #include "FastLedInclude.h" to be able to use that library.

The FastLED library also requires the programmer to create a struct. Now, placing the definition of the struct (i.e. struct CRGB leds[NUM_LEDS];) into the header file leads to compilation errors, since the compiler writes the code to allocate it once for every object file.

The correct way to share this among different object files is to declare it extern in the header, then define it just once in one of the cpp or ino files:

// into FastLedInclude.h
extern struct CRGB leds[];

// into any cpp or ino file (but just once)
struct CRGB leds[NUM_LEDS];

This can also be done in the main ino sketch file, but personally I prefer to define it into another one (it depends, however, on how you choose to divide the program).

If you want to create a library, some other problems arise. The easiest solution is to ask the user to manually modify the header file which will be in the library folder. This solution is a bit uncomfortable, but it is the safest one.

Another solution is to force the user to create a header file into the sketch folder. Then the library should know the sketch folder path to back-include it. But.. This is a very discouraged option, since it will require the library to know the sketch location, thus violating the consistency principle at the base of a library-based approach.

The third solution is to modify the approach, from a compile-time static definition to a dynamic one. In order to do this, instead of defining NUM_LEDS and DATA_PIN at compile time you save them as variables in the library class.

For instance, in your library class definition you have

class yourclass
{
    public:
        yourclass(uint8_t data_pin, uint8_t num_leds);
        ~yourclass();
    private:
        uint8_t _data_pin;
        uint8_t _num_leds;
        struct CRGB *leds = NULL;
};

And the implementation can be

yourclass::yourclass(uint8_t data_pin, uint8_t num_leds)
{
    _data_pin = data_pin;
    _num_leds = num_leds;

    // Dynamic allocation of the array
    leds = (struct CRGB *) malloc(num_leds * sizeof(struct CRGB));
}

yourclass::~yourclass()
{
    // you should free the leds array when done
    free(leds);
}

Then the user can write

yourclass *obj = new yourclass(6, 60);

// or, if he wants to define,
#define NUM_LEDS 60
#define DATA_PIN 6
...
yourclass *obj = new yourclass(DATA_PIN, NUM_LEDS);

or, in the case of a statically allocated object,

yourclass obj(6, 60);

// or, if he wants to define,
#define NUM_LEDS 60
#define DATA_PIN 6
...
yourclass obj(DATA_PIN, NUM_LEDS);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.