WS2812Serial declare numleds in runtime?

snowsh

Well-known member
I want to be able to set the number of leds in my UX. I am adding neopixels to a MIDI controller keyboard. I have a 25 key mini keyboard, but I want to support up to 88 keys.

At present, I set memory as suggested in the examples:

C++:
const int numled PROGMEM = 425;//375;                                           // grid = 256 keyboard buttons = 64, keyboard buttons = 16, encoder = 5, shift = 1, extra = 1, pots = 32, pianoKeys = 50

byte drawingMemory[numled * 3];                                           //  3 bytes per LED

DMAMEM byte displayMemory[numled * 12];                                   // 12 bytes per LED

I now have a new keyboard, with more keys. I have put this off but now it's time to do this dynamically. How best to do this in setup? I will add to my UX to allow the user to define the number of keys, start and end keys, etc..

So, how best can this memory be declared in runtime?

#EDIT
I am happy to use EXTMEM if this can stay fast......
 
Last edited:
Doesn't hurt to always have the maximum number defined. Also in the case when there are not so many leds connected.
 
Doesn't hurt to always have the maximum number defined. Also in the case when there are not so many leds connected.
Yes, that is currently going to be my approach, but I am interested to see if there are other ways.
 
but I am interested to see if there are other ways.

I'm having a hard time imagining anything useful to be gained by dynamic allocation. You still need to have enough memory available for the maximum possible number. Attempting dynamic allocation comes with some disadvantages. The main one is the possibility of memory fragmentation making even less efficient use of memory than simple static allocation of the maximum amount. You'll (probably) also need to abandon constexpr inside WS2812Serial, which often causes the compiler to generate less efficient code.

If you really want to do this despite the likely drawbacks and unlikely path to any useful gain, of course you'll need to edit WS2812Serial to move all the initialization it does from the constructor to a begin() function. Then you can use malloc() to allocation the 2 buffers.
 
I'm having a hard time imagining anything useful to be gained by dynamic allocation. You still need to have enough memory available for the maximum possible number. Attempting dynamic allocation comes with some disadvantages. The main one is the possibility of memory fragmentation making even less efficient use of memory than simple static allocation of the maximum amount. You'll (probably) also need to abandon constexpr inside WS2812Serial, which often causes the compiler to generate less efficient code.

If you really want to do this despite the likely drawbacks and unlikely path to any useful gain, of course you'll need to edit WS2812Serial to move all the initialization it does from the constructor to a begin() function. Then you can use malloc() to allocation the 2 buffers.
Paul, thanks for your input. I have been further mulling this and can see that declaring the memory for the maximum is the way forward. This leads me to another question though:

I'm potentially adding a further 196 pixels to 375 - new total of 571 pixels.

the extra pixels do not need to be updated as frequently as the first 375, I don't want to add undue delay by updating the extension pixels if there is no change. If I understand WS2812 correctly, the data is sent to the first pixel, the first pixel data read and removed and the rest is passed on until all the pixel data has been set. Would it be worthwhile to modify WS2812Serial to allow me to send either the full 571 pixels, or the first 375? I appreciate that sending the last 196 requires passing through the first 375, I could use a flag to determine if the WS2812 leds.show() sends the full set or the first and my current call to leds.show() will take care of the update?

I hope your greater knowledge here can point me in the right direction before i wade into the library.
 
It's about 30µs needed per LED, i.e. ~6ms added update time for 200 pixels, i.e. you are going from ~12ms to ~18ms in total. This limits the update rate of the leds. For LEDs on a MIDI controller 50Hz (20ms) should be more than sufficiently quick in practice. Even half of that would be absolutely fine. So I wouldn't worry about it.

(There are types of LED installations where higher update rates can make sense, look smoother or give more options for very quick "movements".)
 
Back
Top