@@ -259,12 +259,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
259259#define MA_FOR_ESP 100 // how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
260260 // you can set it to 0 if the ESP is powered by USB and the LEDs by external
261261
262- void WS2812FX::show (void ) {
263-
264- // avoid race condition, caputre _callback value
265- show_callback callback = _callback;
266- if (callback) callback ();
267-
262+ void WS2812FX::estimateCurrentAndLimitBri () {
268263 // power limit calculation
269264 // each LED can draw up 195075 "power units" (approx. 53mA)
270265 // one PU is the power it takes to have 1 channel 1 step brighter per brightness step
@@ -277,65 +272,72 @@ void WS2812FX::show(void) {
277272 actualMilliampsPerLed = 12 ; // from testing an actual strip
278273 }
279274
280- if (ablMilliampsMax > 149 && actualMilliampsPerLed > 0 ) // 0 mA per LED and too low numbers turn off calculation
281- {
282- uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
283- uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; // 100mA for ESP power
284- if (powerBudget > puPerMilliamp * _length) // each LED uses about 1mA in standby, exclude that from power budget
285- {
286- powerBudget -= puPerMilliamp * _length;
287- } else
288- {
289- powerBudget = 0 ;
290- }
275+ if (ablMilliampsMax < 150 || actualMilliampsPerLed == 0 ) { // 0 mA per LED and too low numbers turn off calculation
276+ currentMilliamps = 0 ;
277+ busses.setBrightness (_brightness);
278+ return ;
279+ }
280+
281+ uint16_t pLen = getLengthPhysical ();
282+ uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
283+ uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; // 100mA for ESP power
284+ if (powerBudget > puPerMilliamp * pLen) { // each LED uses about 1mA in standby, exclude that from power budget
285+ powerBudget -= puPerMilliamp * pLen;
286+ } else {
287+ powerBudget = 0 ;
288+ }
291289
292- uint32_t powerSum = 0 ;
290+ uint32_t powerSum = 0 ;
293291
294- for (uint16_t i = 0 ; i < _length; i++) // sum up the usage of each LED
295- {
296- uint32_t c = busses.getPixelColor (i);
292+ for (uint8_t b = 0 ; b < busses.getNumBusses (); b++) {
293+ Bus *bus = busses.getBus (b);
294+ if (bus->getType () >= TYPE_NET_DDP_RGB) continue ; // exclude non-physical network busses
295+ uint16_t len = bus->getLength ();
296+ uint32_t busPowerSum = 0 ;
297+ for (uint16_t i = 0 ; i < len; i++) { // sum up the usage of each LED
298+ uint32_t c = bus->getPixelColor (i);
297299 byte r = c >> 16 , g = c >> 8 , b = c, w = c >> 24 ;
298300
299- if (useWackyWS2815PowerModel)
300- {
301- // ignore white component on WS2815 power calculation
302- powerSum += (MAX (MAX (r,g),b)) * 3 ;
303- }
304- else
305- {
306- powerSum += (r + g + b + w);
301+ if (useWackyWS2815PowerModel) { // ignore white component on WS2815 power calculation
302+ busPowerSum += (MAX (MAX (r,g),b)) * 3 ;
303+ } else {
304+ busPowerSum += (r + g + b + w);
307305 }
308306 }
309307
310-
311- if (isRgbw) // RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
312- {
313- powerSum *= 3 ;
314- powerSum = powerSum >> 2 ; // same as /= 4
308+ if (bus->isRgbw ()) { // RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
309+ busPowerSum *= 3 ;
310+ busPowerSum = busPowerSum >> 2 ; // same as /= 4
315311 }
312+ powerSum += busPowerSum;
313+ }
316314
317- uint32_t powerSum0 = powerSum;
318- powerSum *= _brightness;
319-
320- if (powerSum > powerBudget) // scale brightness down to stay in current limit
321- {
322- float scale = (float )powerBudget / (float )powerSum;
323- uint16_t scaleI = scale * 255 ;
324- uint8_t scaleB = (scaleI > 255 ) ? 255 : scaleI;
325- uint8_t newBri = scale8 (_brightness, scaleB);
326- busses.setBrightness (newBri);
327- currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
328- } else
329- {
330- currentMilliamps = powerSum / puPerMilliamp;
331- busses.setBrightness (_brightness);
332- }
333- currentMilliamps += MA_FOR_ESP; // add power of ESP back to estimate
334- currentMilliamps += _length; // add standby power back to estimate
315+ uint32_t powerSum0 = powerSum;
316+ powerSum *= _brightness;
317+
318+ if (powerSum > powerBudget) // scale brightness down to stay in current limit
319+ {
320+ float scale = (float )powerBudget / (float )powerSum;
321+ uint16_t scaleI = scale * 255 ;
322+ uint8_t scaleB = (scaleI > 255 ) ? 255 : scaleI;
323+ uint8_t newBri = scale8 (_brightness, scaleB);
324+ busses.setBrightness (newBri); // to keep brightness uniform, sets virtual busses too
325+ currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
335326 } else {
336- currentMilliamps = 0 ;
327+ currentMilliamps = powerSum / puPerMilliamp ;
337328 busses.setBrightness (_brightness);
338329 }
330+ currentMilliamps += MA_FOR_ESP; // add power of ESP back to estimate
331+ currentMilliamps += pLen; // add standby power back to estimate
332+ }
333+
334+ void WS2812FX::show (void ) {
335+
336+ // avoid race condition, caputre _callback value
337+ show_callback callback = _callback;
338+ if (callback) callback ();
339+
340+ estimateCurrentAndLimitBri ();
339341
340342 // some buses send asynchronously and this method will return before
341343 // all of the data has been sent.
@@ -553,6 +555,20 @@ uint32_t WS2812FX::getLastShow(void) {
553555 return _lastShow;
554556}
555557
558+ uint16_t WS2812FX::getLengthTotal (void ) {
559+ return _length;
560+ }
561+
562+ uint16_t WS2812FX::getLengthPhysical (void ) {
563+ uint16_t len = 0 ;
564+ for (uint8_t b = 0 ; b < busses.getNumBusses (); b++) {
565+ Bus *bus = busses.getBus (b);
566+ if (bus->getType () >= TYPE_NET_DDP_RGB) continue ; // exclude non-physical network busses
567+ len += bus->getLength ();
568+ }
569+ return len;
570+ }
571+
556572void WS2812FX::setSegment (uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
557573 if (n >= MAX_NUM_SEGMENTS) return ;
558574 Segment& seg = _segments[n];
0 commit comments