Control WS2812b panel current consumption

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

 

This entry was posted in Hardware and tagged , , . Bookmark the permalink.

4 Responses to Control WS2812b panel current consumption

  1. Athony says:

    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

  2. Athony says:

    Thanks Paul, i will research it.

  3. jimmy1979 says:

    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!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.