Are there any examples of how to properly change the SPI data rate?

Are there any examples of how to properly change the SPI data rate? Some of the templates have SPI_DATA_RATE but I’m not sure what are valid inputs… is it a divider or the actual speed?

Also, all the templates want a compile time constant in the <> part… I’m trying to setup some code that will setup all the driver type, data rate, pins from data in an EEPROM config… is there any way to set that up without a giant switch statement? I tried passing a LPD8806Controller into addLeds(CLEDController *pLed, const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset) but my compiler keeps complaining it’s invalid…

There are macros for setting the SPI clock as MHz or kHz (the macros turn that into the clock divider necessary).

Right now there’s no Api to change the clock speed at runtime, hasn’t been needed yet, and it’s a template parameter for bitbanging (to remove a variable load/conditional).

Also, the fast is, in part, because of the template parameters - the library really isn’t geared to the kind of generic “select leds you want at runtime” controller, since that’s a pretty edge use case, and supporting that would impact performance/overhead elsewhere.

Ok… makes sense regarding the templating. I think I’ve found a way around it… it’s very verbose, but should work :slight_smile:
And I found the DATA_RATE_MHZ macro, assuming that’s what you mean. Should be what I need… my LPD strips apparently can’t handle the default full speed.

Thanks!

Although, regarding the templating… shouldn’t something like this still work?
static LPD8806Controller<SPI_DATA, SPI_CLOCK> c;
FastLED.addLeds(&c, RGB, numLEDs);

That’s basically what you seem to be doing internally.
That would at least get me around the chipset part of the templating…

Sure - but in that case you would have instances of code generated for every chipset/combination that you have there.

Hehehe… OK. I’ll stick to calling FastLED.addLeds() the normal way. It’s gonna be one BIG switch statement.
Thanks!

Wait… thought about that some more…
So, if I did this:
if(useLPD)
FastLED.addLeds<LPD8806, BRG>(_fastLEDs, numLEDs);
elif(use2801)
FastLED.addLeds<WS2801, BRG>(_fastLEDs, numLEDs);
elif etc…

would it create a new instance of FastLED in memory for every single call to addLeds even if they never actually get called in code? I’ve already done something similar to this so I know addLeds isn’t actually getting called more than once… but I guess that static CLEDController object in each of the addLeds instances would become active?

Primarily I ask because it’s possible that I could have dozens of these setup calls. The right one would get called depending on what’s in the EEPROM config. Clearly I don’t want dozens of instances of the controller created.

Cna you elaborate when you say your “LPD strips can’t handle the default speed”? I work with LPD8806 strips (both factory made as well as custom made) and I push them at full speed with no problems. Kinda have to for POV displays.

I’ve gotten some in the past that seem to crap out above 8MHz or so. Also, I was oversimplifying… There are some other cases where I need to decrease the speed to adjust for any signal noise. In many installations I’ve done there was a certain amount of unavoidable noise, usually from nearby power. Even with attempts of electrical filtering, one easy solution has always been to decrease the SPI speed, usually to 2 or 4 MHz. In most of my scenarios, this is more than fast enough.

To clarify more the example from before:
static LPD8806Controller<SPI_DATA, SPI_CLOCK> c;
FastLED.addLeds(&c, RGB, numLEDs);

Would’ve only been with an if statement or something around it… so, like in the code in FastLED.h it should only create those static instances if that controller type is actually called. Correct?

Also, the real issue with the code above was that trying to call addLEDs that way gave me this error: error: no matching function for call to ‘CFastLED::addLeds(CLEDController*, EOrder, int)’
FastLED.h:addLeds(CLEDController*, const CRGB*, int, int)

I’ve worked around this now and found another way to more simply do what I wanted. Question though… SPI_DATA_RATE is only for bitbanged SPI only, correct? If I wanted to change the hardware SPI rate couldn’t I just set it externally with SPI.setClockDivider()?

I don’t generally have a set divider method that will work post setup across all platforms. I need to write one - but there hasn’t really been a need to, yet, for the most part - and the list of things on my need to list is still pretty long :slight_smile:

Ok… no problem. I used setClockDivider and that seemed to work fine. Apparently one of my setups is quite prone to noise (I think the strips are sub-standard chinese junk)… but it’s great for testing SPI speeds :stuck_out_tongue:

SPI.setClockDivider might work - but I’ve moved some of the hardware SPI classes over to resetting SPI parameters (including clock divider) before writing out each frame (sort of a prelude to making it possible to share SPI w/multiple devices) - so be aware that may not be reliable on all the hardware platforms. (As part of that, though i’ll also make an exposed setDivider method that can be used, and just use the template parameter as a default value)

Cool. Good to know. I will search around for anything SPI divider related and make sure it doesn’t conflict with my particular platform. Maybe disable it if it does for now, until I use a newer version with setDivider. If it matters, I’m just currently using the 2.0 release.

I checked… setSPIRate() is commented out in all AVR writeBytes() methods.So at least I’m good for now :slight_smile: