Category Archives: ws2811b

Deep Sea LED Creatures

wpid-20150923_160131-1.jpg

With thanks to Aerie from Kamp Kraken, who put together the creatures bodies, i was able to make these awesome looking bases:

wpid-20150922_225209.jpg

No, get your mind out of the gutter :) its not what you think:

The will be decorated and hug on a big hoop. I really hope everyone at Burning Seed likes these!

A couple of new pieces

First off we have the lovely pink lady from many a Coco Poco Loco party:

wpid-20150915_114513.jpg This is in fact a very silly looking fiber glass model of a naked lady. It has a base with a normal bulb inside.

The outside is covered in small glass pieces and the inside is covered in jagged fiber glass that cut my arm up pretty badly

I was asked to work my magic and here it is:

I put a strip in the head, onto the bust, all the way up the spine and along the lower parts of the front facing legs. The whole thing uses about 68 LEDs from a WS2812b strip. I used a NodeMCU for this, just for shits and giggles and to see if i could get it to drive WS2812B strips. I used THIS modified NeoPixel driver with the NodeMCU module running at 160Mhz. Note you must use the UART driven library on Pin 4. Here is another example:

Next up is Jords Disco Shoulder Pads

wpid-20150917_230735-1.jpg Disco Pads?

I used a Arduino Nano for this along side a WS2812B LED Strip. The results is hillarious:

My best piece to date in my opinion:

Here are some #discopads please enjoy them #burningmanaustralia #burningseed #ledwearables #arduino #apa102 #ledstrip A video posted by Elec Dash Tron Dot Org (@wow_elec_tron) on

The Orbitron

The main part of the Orb is complete. I have gently sealed in all the glass prisms and stretched Cotton/Lycra over the top part of the sphere:

wpid-20150826_215818-1.jpg wpid-20150826_215828-1.jpg

I was able to crunch the code down to the Nano module. I’m left with just over 400 Bytes free. Here are 2 short demo patterns:

 

I still need to cut out a section of the sphere to store the Arduino Nano and then cut out a mounting hole for a staff.

Production Update – LED Orb

I Still don’t have a good name for this piece, however it is coming along nicely. I was able to get all the inside LEDs into the sphere and wire everything up:

wpid-20150826_001018-1.jpgI will shortly begin adding the outer LEDs. I ended up scrapping the center strip as it made the entire bitmap too large for the Arduino Nano to drive.

wpid-20150826_001007.jpgHere is a nice preview of the orb with the glass jewels placed on top, but not yet secured

Public Reveal @ Darkmofo Arts Festival

image

I was lucky enough to attend Blacklist on Friday the 19th June at the Dark Mofo Festival. An amazing response from the crowd, people really loved it.

Here is a video i found from an Instagram user:

A video posted by @postonmark on


Here is a few more videos from the night:

And another one:

Here is one from Rebecca Fitzgibbon, thanks dude:

And here is one more Video of the mask running on its own after the event

Driving an LED Strip with SPI

Driving Chart for the WS28XX series ICs

WS2811 ws2811 0
0.5μs H
2.0μs L1
1.2μs H
1.3μs LReset Time
Above 50μs
 WS2812B  ws2811 0
0.40μs H
0.85μs L1
0.85μs H
0.40μs LReset Time
Above 50μs

Because I would like to use the Galileo, I’m limited in not being able to use the FastLED library, as its intended for AVR.  One approach is to use SPI at a very high frequency, and send whole Byte sequences to imitate a tight timing sequence for the above:

For the WS2811 1 bit is transmitted in 2.5μs. So if We set up an SPI driver to push out the 8 bit number 255 , 11111111 in binary, at 400khz

ws2911spiex1

Now as a whole pulse that’s useless to us. Because we need to pulse a HIGH and LOW in a specific pattern. To do this, we can mimic the signal by increasing the SPI frequency and sending in BYTES with specific patterns. For example If we double the frequency to 800Khz we can now send in 2 bytes in the same time frame. So if we send in a 255 and a 0:

ws2911spiex2

We get the above. Which is almost to a point where we can start making up masks. In the above example each BYTE, that’s 8 bits, takes 1.25μs to transmit, and looks like a continuous HIGH signal for that amount of time. This means that each BIT takes 1.25μs/8 = 0.15625μs to transmit…

ws2911spiex3

To get a correctly timed pulse for the WS2811 we will need to adjust a few things. 1st we need to find out a nice round number for each Bit to sent out at.  We need to be able to add multiple bits transmition time together to get exactly 1.2μs and 1.3μs. As well as 0.5μs and 2μs. For example…

Time Required for 1 Bit to Transmit = 0.1μs

Time required for 1Byte = 0.8μs

At 1,250,000Hz a single Byte takes 0.8μs to transmit and a Single bit takes 0.1μs to transmit. So…

ws2911spiex4

Above we transmitted 4Bytes over SPI [255,240,0,0] to get a Logic 1

ws2911spiex5And here we transmitted 4Bytes over SPI [248,0,0,0] to get Logic 0

What this means is that we have to transmit 4 Bytes for each BIT in a standard Byte of representation Data. If I have to control 1 LED i need 3 bytes to control Red, Green and Blue. That means I need:

3bytes x 8bits x 4spi-block-bytes = 96Bytes per LED!!!! With my current suit layout that has 288 RGB LEDs, I need 864 Bytes of control data. With the Above protocol, ill need 27,648 Bytes per FRAME….Now what I’m getting at here is that Using SPI to control these drivers is probably not a great idea. It will take 22.1184 milliseconds per frame which is at best around 5 frames per second.

My other concern is that the Galileo probably wont allow such tight control over the SPI frequency. I will be able to set it at 1mhz and 2mhz but not anywhere in between with any kind of certainty. I spent some time on my oscilloscope last night to see if the SPI frequency actually changes in between MHz but saw no difference unless the change was significant .

Here is the same diagrams but using the WS2812B timing, which is the same as the WS2811 but using the double data rate:

Set SPI to 2,500,000Hz Use 4SPI Bytes per LED BYTE:

To send  Logic 1 you send [255,255,128,0]

ws2812sendhighTo send Logic 0 you send [255,0,0,0]

ws2812sendlow

I can confirm that the 144LED strips uses fast mode… This was sent ot me directly from WorldSemi

“The 144LED Strip uses the WS2812B chipset(built-in IC), and HIGH speed mode”

Their Web page states they use the WS2811 chip but they also say that they use High Speed  mode in prepackaged systems… Using High Speed mode I can get maybe 10 frames per second with the same number of LEDs.

Here is some NodeJS code I wrote that will grab an array of Bytes and create a Buffer() of bytes with the appropriate bit pattern to be pushed out to the SPI bus.

var ledBytes = 1*3;
var ledBar = new Array(ledBytes);
var aBuffer = new Buffer(0);
var counter = 0;

init();
runMain();

function init()
{
 //clear the led array
 clearSuit();
}

function runMain()
{
 var testBuffer = WS2811b_SPI();
 
 for(counter=0; counter<testBuffer.length; counter++)
 {
 console.log("Index "+counter+"->"+testBuffer[counter]);
 }
 
}

function WS2811b_SPI()
{
 var spiBuffer = new Buffer(ledBytes*8*4);
 var currentByteSPIBlock = new Buffer(8*4);
 var spiBufferIndex = 0;
 
 for(counter=0; counter<ledBytes; counter++)
 {
 currentByteSPIBlock = createSPIBlockFromByte(ledBar[counter]);
 currentByteSPIBlock.copy(spiBuffer,spiBufferIndex,0,currentByteSPIBlock.length);
 spiBufferIndex+=currentByteSPIBlock.length;
 }
 return spiBuffer;
}

function createSPIBlockFromByte(dataToPush)
{
 var mask=1, bitResult=0, cnt=0, bufferIndex=0; 
 var tempBuffer = new Buffer(4*8);
 var spiBlock = new Buffer(4);
 
 mask = mask << 7; 
 for(cnt=0; cnt<8; cnt++) 
 { 
 bitResult = dataToPush & mask; 
 bitResult = bitResult >> (7-cnt); 
 spiBlock = createSPIBit(bitResult);
 spiBlock.copy(tempBuffer,bufferIndex,0,spiBlock.length);
 bufferIndex+=spiBlock.length;
 mask = mask >> 1; 
 } 
 return tempBuffer;
 
}

function createSPIBit(value)
{
 var spiBitBlock = new Buffer(4);
 
 if(value==1)
 {
 spiBitBlock[0] = 255;
 spiBitBlock[1] = 255;
 spiBitBlock[2] = 128;
 spiBitBlock[3] = 0;
 }
 else
 {
 spiBitBlock[0] = 255;
 spiBitBlock[1] = 0;
 spiBitBlock[2] = 0;
 spiBitBlock[3] = 0;
 }
 return spiBitBlock;
}

function clearSuit()
{
 for(counter=0; counter<ledBytes; counter++)
 {
 ledBar[counter] = 0;
 }
}