10

I am working with some libraries that provide APIs for interacting with specific hardware chips (that makes these drivers?). However, different custom boards or shields will have the chip mapped to different pins meaning the library needs to be modified for each case. Needing to modify the library does not work well with the Arduino IDE Library Manager.

Are there preferred/recommended patterns for exposing this configuration so that the library itself does not need to be modified every time?

Here is an example where it is documented which part needs to be changed to match the pin layout of your board.

chicks
  • 213
  • 4
  • 10
vossad01
  • 203
  • 1
  • 6
  • Many of the normal Arduino libraries already do this - start by familiarizing yourself with that method, even from a user perspective. – Chris Stratton Aug 20 '17 at 16:48

4 Answers4

6

The method I use is to provide the pins as parameters to the constructor. Those pin numbers are stored in variables to use later in the .begin() function and elsewhere.

Most of the time I use initialization lists to keep things simple. For example:

class Something {
    uint8_t _cs;
    uint8_t _dc;

    Something(uint8_t cs, uint8_t dc) : _cs(cs), _dc(dc) {}
    void begin();
};

void Something::begin() {
    pinMode(_cs, OUTPUT);
    pinMode(_dc, OUTPUT);
}

Something mySomething(10, 8);
Majenko
  • 103,876
  • 5
  • 75
  • 133
6

I would use either of the following two possibilities:

Use (class) variables and set them within the constructor.

Advantages:

  • Always initialized
  • Easy to use (constructor and pin setup at once)

Use a separate (e.g. Init) method.

Advantages:

  • Can be dynamically changed

Remarks

For pin settings, mostly static circuits are used so the first approach is probably better.

For settings, mostly the second method is better.

If many pins are involved (not likely), use a structure or separate pin settings class.

Macros

What I wouldn't advice is macros. When users need to change source code themselves, and new versions are installed, they either have to merge or redo the changes again. The advantages is a bit less (machine)code, a little bit faster probably and a bit less memory usage, but all three aspects are minimal.

Michel Keijzers
  • 12,759
  • 7
  • 37
  • 56
3

In case you'd avoid the C++ constructor stuff that's quite commonly an overkill on Arduino, you could use #define's (object-like macros).

Like so:

#define PIN_ONE 1
#define PIN_TWO 2

The preprocessor will seamlessly replace PIN_ONE with the number 1 and PIN_TWO with 2 assuming those definitions are in the library header .h file. This will most likely takes the least amount of resources compared to the other possible solutions.

Alternative 1

If you have the opportunity to use modern-ish C++, you can use constexpr to define variables. Compared to macros you'll get type checking and it should be just as efficient.

Avamander
  • 624
  • 2
  • 11
  • 35
2

depending on your approach.

1) if you just provide the binary + header files, you will have to make the pins variables.

2) if you provide the source code and expect the user to recompile the source code, use macros.

dannyf
  • 2,730
  • 9
  • 13