-
Notifications
You must be signed in to change notification settings - Fork 53
Description
Worst case power draw from Pixels
_(A pixel is the hardware unit, which contains three leds ... one red, one green, one blue. Avoids ambiguity between per-pixel vs. per-LED values)_
Note that these calculations are all estimates. For original WS2812 5050 pixels, a rule of thumb was 60mA
current per pixel. The BusPirate 5, for example, uses SK6812 ... where the last two digits indicate 12mA
per led, with ~1mA
overhead (idle power draw) per pixel, giving maximum power draw per pixel of ~38mA
. I'll show values for both below.
The buspirate system configuration settings only support three LED brightness scales:
1/3
brightness1/5
brightness1/10
brightness
Thus, for worst case / highest power draw calculations, we'll consider 1/3
brightness. The brightness reduction in the buspirate code is a linear reduction ... which is to say, no gamma is applied anywhere in the current buspirate code. Therefore, the maximum value for R, G, and B is 255 / 3 == 81
.
Pixel Type | Per-Pixel mA | Pixel Count | Max Brightness | approx max mA | Notes |
---|---|---|---|---|---|
WS2812 5050 | 60 |
18 |
255 |
1080 |
No reduction |
WS2812 5050 | 60 |
18 |
81 |
~344 |
1/3 brightness |
WS2812 5050 | 60 |
18 |
51 |
~216 |
1/5 brightness |
WS2812 5050 | 60 |
18 |
25 |
~106 |
1/10 brightness |
SK6812 | 38 |
18 |
255 |
684 |
No reduction |
SK6812 | 38 |
18 |
81 |
~218 |
1/3 brightness BP5 Target |
SK6812 | 38 |
18 |
51 |
~137 |
1/5 brightness |
SK6812 | 38 |
18 |
25 |
~67 |
1/10 brightness |
Even at the maximum 1/3 brightness configuration, all pixels at 100% white would still leave > 150mA
(> 280mA
) for the rest of the system.
I encourage setting to 1/5 or 1/10 brightness in the settings ... reduces the power fluctuations, even if your eyes don't hurt from the brightness at the default 1/3 power. ;-)
Based on the above calculations, I think it'd be safe to allow updates to more than one onboard pixel, so long as the total current is below a pre-selected threshold.
Pseudo-code
bool estimated_to_exceed_power_limit(CPIXEL_COLOR* buffer, const size_t buffer_count) {
bool result = true; // exceeds result unless calculations will show otherwise
static const uint8_t LEDS_PER_PIXEL = 3u; // implied by CPIXEL_COLOR structure
static const uint8_t MAX_DRAW_PER_LED_mA = 12u; // SK6812 may be adjusted to 12mA after confirmation
static const uint8_t MAX_DRAW_PER_PIXEL_mA = LEDS_PER_PIXEL * MAX_DRAW_PER_LED_mA;
static const uint8_t IDLE_DRAW_PER_PIXEL_mA = 2u; // SK6812 datasheet lists 1mA, real-world suggests 2mA
static const uint8_t OVERALL_MARGIN_mA = 20u; // safety margin, slop, manufacturing tolerances, etc.
static const uint32_t SYSTEM_POWER_BUDGET_mA = 500u - 150u; // USB 500mA; 150mA by non-plank items?
uint16_t PLANK_OUTPUT_LIMIT_mA = 0; // NOTE: should be updated via events from `W` and `w`
// TODO: avoid overflow in subtractions (if (X - Y > X) then underflow occurred...)
uint32_t pixel_power_budget_mA = SYSTEM_POWER_BUDGET_mA - PLANK_OUTPUT_LIMIT_mA;
pixel_power_budget -= OVERALL_MARGIN_mA;
pixel_power_budget -= (IDLE_DRAW_PER_PIXEL_mA * COUNT_OF_PIXELS);
uint32_t color_data_sum = 0; // simple sum works for SK6812
for (uint_fast8_t i = 0; i < buffer_count; ++i) {
color_data_sum += buffer[i].r;
color_data_sum += buffer[i].g;
color_data_sum += buffer[i].b;
}
if ((UINT32_MAX / MAX_DRAW_PER_LED) >= color_data_sum) {
// no overflow when multiplying ... can continue
uint32_t estimated_power_draw = (color_data_sum * MAX_DRAW_PER_LED) / 255;
if (estimated_power_draw < pixel_power_budget_mA) {
result = false; // Estimated to be within power budget
}
}
// todo: logging when result is true (exceeding budget)
return result;
}
// todo: automatic brightness limiter ... automatically reduce values to fit the current limit