Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic pins / color order in a method #282

Closed
SciLor opened this issue Apr 2, 2016 · 23 comments
Closed

Dynamic pins / color order in a method #282

SciLor opened this issue Apr 2, 2016 · 23 comments

Comments

@SciLor
Copy link

SciLor commented Apr 2, 2016

Currently I am using a static config in compile time in my project.
(usage of Config::)

I would like to configurate my connected LEDs dynamicly at runtime.
But when I am using the parameters of my method, I get following error:

no matching function for call to 'CFastLED::addLeds(CRGB*&, int&)'

Is there something I can do to workaround that?

class Config {
    static const ESPIChipsets chipset = WS2801;

    static const EOrder colorOrder = RGB;

    static const uint8_t dataPin  = D1;    // Data
    static const uint8_t clockPin = D2;    // optional for clockless LED Pixels, just set it to 0;
    static const uint8_t ledCount = 50;
}
void WrapperFastLed::begin(const uint8_t chipset, uint8_t dataPin, const uint8_t clockPin, const uint16_t ledCount, const uint8_t colorOrder) {
  _ledCount = ledCount;
  leds = new CRGB[_ledCount];
   /*
  Chipset eChipset = static_cast<Chipset>(chipset);
  const EOrder eColorOrder = static_cast<EOrder>(colorOrder); 
  switch(eChipset) {
    case SPI_LPD8806:
      FastLED.addLeds<LPD8806, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_WS2801:
      FastLED.addLeds<WS2801, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_WS2803:
      FastLED.addLeds<WS2803, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_SM16716:
      FastLED.addLeds<SM16716, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_P9813:
      FastLED.addLeds<P9813, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_APA102:
      FastLED.addLeds<APA102, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
    case SPI_DOTSTAR:
        FastLED.addLeds<DOTSTAR, dataPin, clockPin, colorOrder>(leds, _ledCount);
      break;
  }*/
    FastLED.addLeds<WS2801, dataPin, clockPin, colorOrder>(leds, _ledCount);
    //FastLED.addLeds<Config::chipset, Config::dataPin, Config::clockPin, Config::colorOrder>(leds, _ledCount);
}
@SciLor SciLor changed the title Dynamic pins / color order in a methid Dynamic pins / color order in a method Apr 2, 2016
@focalintent
Copy link
Contributor

No, the pins are compile time constants and can't be set dynamically at the moment. The compiler has to be able to determine their value at compile time.

@cansik
Copy link

cansik commented Nov 7, 2017

@focalintent Is it still like that? I am writing my own wrapper class in CPP for a FastLed driven circle of LEDs. Now I would like to set the LED PIN for each ring separate. Is that possible?

void LEDRing::setup()
{
  FastLED.addLeds<LED_TYPE, pin, COLOR_ORDER>(leds, count).setCorrection(TypicalLEDStrip);
}

gives following error:

LEDRing.cpp:13: error: wrong number of template arguments (3, should be 1)
   FastLED.addLeds<LED_TYPE, pin, COLOR_ORDER>(leds, count).setCorrection(TypicalLEDStrip);

Why are you not letting people set the pin number on runtime?! Could be a configuration of the output or something else.

@focalintent
Copy link
Contributor

This is not something that has changed - on a number of platforms there are optimizations to output/timing that can only be done with having the pin number determined at compile time - this is pretty central to much of the low level design of the library and unlikely to be changed any time soon.

@tonton81
Copy link

tonton81 commented Nov 7, 2017

its a template, pin must be constant
this is for performance reasons
however what i did for a project of mine dynamically is i made a list if if and if else statements for dynamic pin, when when i enter the pin it chooses the correct template
crude, but works.

@kcouck
Copy link
Contributor

kcouck commented Nov 7, 2017

Depending on your platform, you could try parallel output?

@cansik
Copy link

cansik commented Nov 7, 2017

Ok, fixed it with an own template method. It's not usable if I load the PIN from the EEPROM but at least for my own LEDRing class. Just declare following template method in your header:

template<uint8_t DATA_PIN> void setup() {
    this->pin = DATA_PIN;
    FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, count);
}

@tonton81
Copy link

tonton81 commented Nov 7, 2017

you should of added the led type as well (for different mixed type strips) :P

@cansik
Copy link

cansik commented Nov 7, 2017

@tonton81 Yeah and the clock, it was just an example, because as a C++ noob it's not that easy to know where to put the template method.

@DougLeary
Copy link

DougLeary commented Jan 25, 2018

This thread answered my question about using a variable to specify DATA_PIN, so thanks for posting it!

I've written a wrapper class using FastLED to light the buildings in a model town, medieval village, etc. My class defines various behaviors - always On, always Off, Switched on and off at random to simulate human activity, Flickering firelight, and Custom. I can pass the class a simple character string, using one char to specify how each led should behave. The length of this string is used to allocate the CRGB array dynamically. I know dynamic allocation is frowned upon because of the potential for memory fragmentation, but this step is only executed once in setup.

The whole thing works great and the only remaining problem is to assign the data pin as a parameter, which I can now see is not possible using FastLED. The reason I wrote the wrapper class was to control several strings with one Arduino or ESP8266 using different control pins. I guess the lesson here is to do better research before jumping into coding. I really like FastLED, so for now I'll be using a separate controller for each led string. At least a wrapper makes the top level code nice and clean!

@tonton81
Copy link

i dynamically can change pins. if you wanna know the trick, copy the addLeds constructor as many times as pins you have, like a list
edit each line to go 0,1,2,3,4,5,6
you may dynamically write to “FastLED.*” now

ive ran random stuff for over a week on my old project with that non stop

@tonton81
Copy link

sorry forgot to add, put them in a switch case and make the function call the proper case when a pin is set

@TobiNorris
Copy link

@cansik Could you share your completed code ? tks!

@tonton81
Copy link

ok when i get home i can

@hippyau
Copy link

hippyau commented Feb 22, 2020

i hope you made it home @tonton81 , it's been a few years now :) :) :)

I just want to dynamically change the LED type at runtime or boot, not the pins... how'd I do this?

@DeeJayMX
Copy link

Me too !
please can you post an example ?

@marmilicious
Copy link
Contributor

@sblantipodi
Copy link

I still have this problem.
Adding
FastLED.addLeds<WS2811, DATA_PIN>(leds, MAX_COUNT);
to a switch case or even inside an if consumes memory.

Every addLeds() call inside the if statement consumes memory.

is there a real workaround to the problem?

@kriegsman
Copy link
Member

Especially on 8-bit (AVR) microcontrollers, FastLED needs to optimize the assembly code differently depending on which which pin is being used; different pins have different ways of accessing them and FastLED tries to choose the fastest -- at compile time, so that there's no IF/THEN required at runtime.

On faster microcontrollers, like ARM, and ESP, we could probably add the ability to dynamically set a pin number, because the cost of the IF/THEN logic at runtime is so much lower on these faster chips.

@samguyer and I just started a conversation about how we might be able to do this in the future, and we're interested in taking a look at doing that once we get the current 'release' out the door. So, short version of the answer is: the pin number is fixed at compile time for performance reasons. We might be able to make it dynamic in the future, but we don't have a timeline for that.

@larryl79
Copy link

larryl79 commented Dec 16, 2022

I need make a lib/class for ESP, which initializing Fastled, but I always run into same issue. Is it any update about a dynamically configured data pin?

@vortigont
Copy link

vortigont commented Aug 25, 2023

Just in case somebody is interested in an easy way to use run-time configured gpio for ESP32, this could be done with a derived class template for ClocklessController. I've implemented it for popular w2812 clockless strips, but same could be made for other led types I presume.
No need to patch FastLED lib at all, just drop this header file in your project's folder and use it i.e. like this:

#include w2812-rmt.hpp

ESP32RMT_WS2812B<GRB> *wsstrip;

setup(){
   uint8_t mygpio = load_from_cfg();     // read it from some eeprom or file config, etc...
   wsstrip = new ESP32RMT_WS2812B<GRB>(mygpio);
   FastLED.addLeds(wsstrip, CRGB_buffer, CRGB_buffersize);  // define or create your buffer somewehere
}

loop(){
  // do your stuff
}

@ethanhjennings
Copy link

ethanhjennings commented Dec 13, 2023

+1 for this request.
Here is an easy but hacky workaround for custom data pins and color orders. You need one case for every possible pin value, so it's pretty ugly and wastes storage for the program, but it's doable since there's a finite number of pins you can use.

switch (pin_num) {
  case 1: FastLED.addLeds<WS2811,1>(leds, NUM_LEDS); break;
  case 2: FastLED.addLeds<WS2811,2>(leds, NUM_LEDS); break;
  case 3: FastLED.addLeds<WS2811,3>(leds, NUM_LEDS); break;
  ...
  default: break;
}

And same for color modes:

switch (color_mode) {
  case RGB: FastLED.addLeds<WS2811,PIN,RGB>(leds, NUM_LEDS); break;
  case BGR: FastLED.addLeds<WS2811,PIN,BGR>(leds, NUM_LEDS); break;
  ...
  default: break;
}

Doing both together is also possible but you need n2 cases.

@vortigont, your link seems to be broken.

@vortigont
Copy link

@ethanhjennings sorry, updated with permalink

@kevinl7778
Copy link

kevinl7778 commented Jan 6, 2024

Hello all,

I am having trouble with this as well,

I had a workaround for multi-color order using the A0 pin and a resistor to 3.3V, if hi color_order_2 if low color_order_1 but now I need a thrid color order.

one strip in color order 1,2, or3 and two more each with two configs in order 1,2 or 3 but I get an Iram error and cant fit the new third option.

how can I make a list of color orders and assign that array location in fastled.addleds(ws2811, color_order[ ], NUM_LEDS(x,x,x):

I have tried every option I can think of all with some form of error.

// if (currentPatternIndex2 == 0 ) {COLOR_ORDER_1 == GRB; return COLOR_ORDER_1; Serial.println(currentPatternIndex2);}
// if (currentPatternIndex2 == 1 ) {COLOR_ORDER_1 == BRG; return COLOR_ORDER_1; Serial.println(currentPatternIndex2);}
// if (currentPatternIndex2 == 2 ) {COLOR_ORDER_1 == RGB; return COLOR_ORDER_1; Serial.println(currentPatternIndex2);}

If I simply put all three below I get the I ram error and can only run two configs with two color orders, three orders is an Iram crash.

void LedSet() {
if (currentPatternIndex <= 2 ){if (blinking == 1) {SingleStrip = 0;}else {SingleStrip = 1;}}else {SingleStrip = 0;}
if (SingleStrip == 1) {
if (currentPatternIndex2 == 0 ) {FastLED.addLeds<LED_TYPE, LED_L, COLOR_ORDER_1>(leds, led_cnt);FastLED.addLeds<LED_TYPE, LED_R, COLOR_ORDER_1>(leds, led_cnt);}
}
else {
if (currentPatternIndex2 == 0 ) {FastLED.addLeds<LED_TYPE, LED_L, COLOR_ORDER_1>(ledsL, led_cnt);FastLED.addLeds<LED_TYPE, LED_R, COLOR_ORDER_1>(ledsR, led_cnt);}
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests