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.

Rob Hilken
  • 142
  • 1
  • 2
  • 11

1 Answers1

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);
frarugi87
  • 2,731
  • 12
  • 19