With the 16×16 123RGB panel base on WS2812b, I have 256leds able to consume up to 50mA each. I want to use this with a limited current under 3A and want to ensure using software, this limit will not be reached. This article detailed my code for doing this.
Each led value is stored in a int array where each value is containing rvb values.
To start, I have to store panel led values :
// Maximum supported LED (this can be changed) #define MAX_lEDS 256 // --------------------------------------------------- // Raw data representing pixels each value format is // --------bbbbbbbbrrrrrrrrgggggggg // --------012345670123456701234567 // led matrix is 16x16, direction change each line uint32_t rgb123_256_pixels[MAX_lEDS]; int max_x=0; // number of Leds on a line int max_y=0; // number of Leds
Then, to set and get a pixel in this table we have two functions:
// --------------------------------------------------- // set a pixel in the coordinate [0-15][0-15] void rgb123_256_setPixel(uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b) { if ( x >= max_x || y >= max_y ) return; int v = 0; for ( int i = 0 ; i < 8 ; i++ ) v = ( v | (( b >> i ) & 1) ) << 1; for ( int i = 0 ; i < 8 ; i++ ) v = ( v | (( r >> i ) & 1) ) << 1; for ( int i = 0 ; i < 8 ; i++ ) v = ( v | (( g >> i ) & 1) ) << 1; v = v >> 1; uint32_t _x = (y & 1 != 0)?(max_x-1)-x:x; rgb123_256_pixels[max_x*y+_x] = v; } // -------------------------------------------------- // get r,g,b values from the matrix // @TODO - check it works void rgb123_256_getPixel(uint32_t x, uint32_t y, uint32_t * r, uint32_t * g, uint32_t * b) { if ( x >= max_x || y >= max_y ) return; uint32_t _x = (y & 1 != 0)?(max_x-1)-x:x; int v = rgb123_256_pixels[max_x*y+_x]; *g=0; *r=0; *b=0; for ( int i = 0 ; i < 8 ; i++ ) *g = ( *g | (( v >> i ) & 1 )) << 1; *g = *g >> 1; for ( int i = 8 ; i < 16 ; i++ ) *r = ( *r | (( v >> i ) & 1 )) << 1; *r = *r >> 1; for ( int i = 16 ; i < 24 ; i++ ) *b = ( *b | (( v >> i ) & 1 )) << 1; *b = *b >> 1; }
Now, we can calculate current according to this article :
// -------------------------------------------------- // evaluate current consumption of the 16x16 matrix // per pixel : ma = 1 + R/16 + G/16 + B/16 // @TODO - finish it ! int rgb123_256_estimateCurrent() { int ma = 0; uint32_t r,g,b; for ( int y = 0 ; y < max_y ; y++ ) { for ( int x = 0 ; x < max_x ; x++ ) { rgb123_256_getPixel(x,y,&r,&g,&b); ma += 1 + (r >> 4) + ( g >> 4) + ( b >> 4 ); } } return ma; }
And manage the limitation like this:
int max_i=-1; // -------------------------------------------------- // setIntensityLimit - 5% error void rgb123_256_setIntensityLimit(int _m) { max_i=(_m - _m/20 ); rgb123_256_limitIntensity(); } // -------------------------------------------------- // setIntensityLimit void rgb123_256_limitIntensity() { int _initialI = rgb123_256_estimateCurrent(); if ( _max_i > 0 && _initialI > max_i ) { // ratio computation, the fixed part can't be reduce and is substracted from max_i int ratio = ( (max_i - max_x*max_y) << 10 ) / (_initialI - max_x*max_y); uint32_t r,g,b; for ( int y = 0 ; y < max_y ; y++ ) { for ( int x = 0 ; x < max_x ; x++ ) { rgb123_256_getPixel(x,y,&r,&g,&b); r = (( r * ratio ) >> 10); g = (( g * ratio ) >> 10); b = (( b * ratio ) >> 10); rgb123_256_setPixel(x,y,r,g,b); } } } }
This is giving pretty good result and as much as I have tested at this time the produced light with a 2500mA constraint is good enough for my project ! good news !
The complete sketch is here ; it works with RFDuino (16 Mhz arm cortex M0 only)
test_rfduino_rgb_pw_control.ino
Hey Paul, Could you advice which controller you use with above code,we want to control a DIY WS2812B led matrix. Their circuit are designed with vertical direction. whether we need revise somewhere.
WS2812B led matrix manual here: http://www.greeled.net/uploadfile/03/60/6003/21141/11/13/ws2812b-led-matrix-unit-greeled.pdf
You can take a look to this post : http://www.disk91.com/2014/technology/hardware/rgb123-256-leds-and-rfduino-first-hacks/ where you have all the details and the source code to control them. You must have a fast micro-controler as the timing for these leds is really critical.
Thanks Paul, i will research it.
i adopt Array shook hands with WS2812B led strip www pt ledlightmake pt com / rgb-addressable-led-strip-c-80_87 / led-ws2812b-addressable-digital-stripsmd5050-strips-60-pcsm-p-216.html. always get the Pointer Overflow.
the Array is static const.Be similar as you define.
static const uint8_t ledTable[256] = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3,
3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16,
16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26,
26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39,
40, 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 75,
76, 77, 78, 80, 81, 82, 83, 85, 86, 87, 89, 90, 91, 93, 94, 95, 97, 98,
99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 119,
121, 122, 124, 125, 127, 129, 130, 132, 134, 135, 137, 139, 141, 142,
144, 146, 148, 150, 151, 153, 155, 157, 159, 161, 163, 165, 166, 168,
170, 172, 174, 176, 178, 180, 182, 184, 186, 189, 191, 193, 195, 197,
199, 201, 204, 206, 208, 210, 212, 215, 217, 219, 221, 224, 226, 228,
231, 233, 235, 238, 240, 243, 245, 248, 250, 253, 255 };
Do you know why that is?get a clues to me thanks!