WS2812B - timings and accuracy

Deouss
Posts: 425
Joined: Tue Mar 20, 2018 11:36 am

WS2812B - timings and accuracy

Postby Deouss » Tue Apr 09, 2019 3:48 pm

So I am reading the documentation of WS2812B and see that sometimes they list different timing values f.ex.
T0H - 4us and 0.35us in othes docs T0L/T1H - 0.8/0.85us and 0.9us.
I am not sure what's going on and how those leds are properly controlled with what timings?
Are there some min/max values or discrepancy error? Maybe it all depends on manufacturer?
How accurate those times must be?
Can somebody maybe explain and help?
Thanks

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: WS2812B - timings and accuracy

Postby WiFive » Wed Apr 10, 2019 1:57 am

Not sure but there are several drivers on GitHub that use RMT or i2s to achieve high performance and accurate timing

Deouss
Posts: 425
Joined: Tue Mar 20, 2018 11:36 am

Re: WS2812B - timings and accuracy

Postby Deouss » Wed Apr 10, 2019 3:19 am

So I just investigated all those timings a little and I am able to use a simple SPI to fully control WS2812B 32*8 led matrix.
It is very simple and it seems like those timings are based on 1:4 ratio to 'lowest 0 high' )
Therefore 1 rgb bit of led is half a byte so one full rgb pixel is 12bytes - still good performance at 2.86Mhz.
1,000,000 / 0.35us (per specs) = 2,857,142.8571428571428571428571429 ~ 2.86Mhz
I will investigate more but code is so short and much more convenient that RMT which takes more memory too.

Deouss
Posts: 425
Joined: Tue Mar 20, 2018 11:36 am

Re: WS2812B - timings and accuracy

Postby Deouss » Sun Apr 14, 2019 1:49 am

I managed to display RGB full color bitmap from PC - actually a 8x32pixels chunk.
However the picture looks very very bright - seems like colors need calibration - I think it is contrast and saturation.
I must check that later
Here is the code that may help to experiment with SPI and WS281B matrix:

  1. spi_bus_config_t buscfg={
  2.         .flags              = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_SCLK,
  3.         .miso_io_num        = -1,
  4.         .mosi_io_num        = PIN_NUM_MOSI,
  5.         .sclk_io_num        = PIN_NUM_CLK, // - not used !
  6.         .quadwp_io_num      = -1,
  7.         .quadhd_io_num      = -1,
  8.         .max_transfer_sz    = 0
  9.     };
  10.  
  11.     spi_device_interface_config_t devcfg={
  12.         .clock_speed_hz =   2.86*1000*1000, // 1,000,000 / 0.35us ( 2,857,142.857142... ~ 2.86Mhz)
  13.         .mode           =   0,
  14.         .spics_io_num   =   -1,
  15.         .duty_cycle_pos = 255,
  16.         .queue_size     = 1,
  17.         .pre_cb         = 0,
  18.         .flags          = 0
  19.     };
  20.  
  21.     ESP_ERROR_CHECK( spi_bus_initialize(HSPI_HOST, &buscfg, 1) );
  22.     ESP_ERROR_CHECK( spi_bus_add_device(HSPI_HOST, &devcfg, &spi) );
Transmission code:

  1.  
  2.     const int stride=DISPLAY_WIDTH*3;
  3.     const int n_block_size = DISPLAY_WIDTH*DISPLAY_HEIGHT*3;
  4.  
  5.     static uint8_t* data = NULL;
  6.     static uint8_t* pixels = NULL;
  7.     static spi_transaction_t t =
  8.     {
  9.         .addr       = 0,
  10.         .cmd        = 0,
  11.         .flags      = 0,
  12.         .length     = 0,
  13.         .rxlength   = 0,
  14.         .user       = NULL,
  15.         .rx_buffer  = NULL,
  16.         .tx_buffer  = NULL
  17.     };
  18.    
  19.     if(data==NULL) data = (uint8_t*)malloc(n_block_size);
  20.     if(pixels==NULL) pixels = (uint8_t*)malloc(n_block_size*12);
  21.  
  22.    // HERE LOADYOUR RGB BITMAP TO *data BUFFER
  23.  
  24.     t.length=32*8 * 12*8;
  25.     t.tx_buffer=pixels;
  26.  
  27.     int x=0;
  28.     for(int offset=0; offset<stride;)
  29.     {
  30.         for(int row=7; row>=0; row--)
  31.         {
  32.             int n = (row*stride) + offset;
  33.             uint32_t pixel = (((uint32_t)data[n+1])<<16) | (((uint32_t)data[n+2])<<8) | ((uint32_t)data[n]);
  34.  
  35.             // 210 - byte order in data
  36.             // RGB
  37.             // GRB
  38.             for(int k=23; k>0; k-=2)
  39.                 pixels[x++] = (((pixel>>(k-1))&1) ? 0x0E : 0x08) | (((pixel>>k)&1) ? 0xE0 : 0x80 );
  40.                 //pixels[x++] = (((pixel>>(k-1))&1) ? 0b1110 : 0b1000) | (((pixel>>k)&1) ? 0b11100000 : 0b10000000 );
  41.         }
  42.  
  43.         offset+=3;
  44.  
  45.         for(int row=0; row<8; row++)
  46.         {
  47.             int n = (row*stride) + offset;
  48.             uint32_t pixel = (((uint32_t)data[n+1])<<16) | (((uint32_t)data[n+2])<<8) | ((uint32_t)data[n]);
  49.  
  50.             for(int k=23; k>0; k-=2)
  51.                 pixels[x++] = (((pixel>>(k-1))&1) ? 0x0E : 0x08) | (((pixel>>k)&1) ? 0xE0 : 0x80 );
  52.         }
  53.  
  54.         offset+=3;
  55.     }

This is for zigzag 8*32 led matrix (going from 8-down to next 8-up left to right pixels)
It works good but maybe there is some catch with colors. It uses 2 color bits per 1 byte so 12bytes gives a 24bit RGB (GRB) pixel
If anyone experiments - please share the results ;)

Who is online

Users browsing this forum: No registered users and 102 guests