PDA

View Full Version : Addressable RGB LED's & LED strips



spcw1234
- 19th October 2013, 02:35
Has anyone messed with the addressable RGB LED strips based on the WS2812 5050 led's?

https://www.sparkfun.com/products/12027

I am interested in trying one of these, if anyone has any tips to get started on driving these things it is much appreciated. Looks like timing is critical to controlling these things.

The data transfer protocol use single NZR communication mode. After the pixel power-on reset, the DIN port receive data from controller, the first pixel collect initial 24bit data then sent to the internal data latch, the other data which reshaping by the internal signal reshaping amplification circuit sent to the next cascade pixel through the DO port. After transmission for each pixel,the signal to reduce 24bit. pixel adopt auto reshaping transmit technology, making the pixel cascade number is not limited the signal transmission, only depend on the speed of signal transmission.

Jerson
- 19th October 2013, 04:35
Hello Shawn

I have done a project using similar led chains. These, however, are done using a relative of the WS2812 you mention. The IC controller I worked with is the SM16716. These leds are pretty easy to control. If you search a bit, you will find a bit of code for each type of IC. Timing is not critical.

This is how the leds are controlled. (arduino code)


static void show() {
digitalWriteFast(DATA_PIN, LOW);
for (int i = 0; i < 50; i++) {
toggle_clock();
}
for (int i = 0; i < LIGHT_COUNT; ++i) {
write_pixel(i);
}
write_blank_pixel();
delay(1);
}

spcw1234
- 22nd October 2013, 16:14
As far as I can tell the SM16716 has 2 wires for communication, where the WS2812 only has one. To send a 0 bit you must drive the data pin high for 0.35us and then low for 0.8us. For a 1 bit you drive the data pin high for 0.7us then low for 0.6us. If the data line is low for longer then 50us the strip will reset. I am going to get one and play with it, I will post some code when I get one working :)

Datasheet (http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Components/LED/WS2812.pdf )

DavidK
- 23rd October 2013, 05:44
The translation for the data sheet is a little difficult to follow, it would be nice if there was a better explanation.

spcw1234
- 23rd October 2013, 18:23
The translation for the data sheet is a little difficult to follow, it would be nice if there was a better explanation.

Agreed! I will have a string on Friday to play with.

comwarrior
- 23rd October 2013, 22:13
SPCW pointed this thread out to me on mine, so, i'll fetch what i've got over here...

I purchased 10 of the little chips off ebay. Becarefull with the chips when soldering them as they are extremely sensitive to heat... I think i've killed 4 out of the 10 :(

The constant current chip is the WS2811. The chip itself has two speeds, 400KHz or 800KHz. the WS2812 runs at 400KHz and the WS2812B runs at 800KHz.
Communication to these devices is via a daisy chain with a NRZ type wave form. Each chip has 3 channels with 8 bit PWM.
So, at 800KHz to send a 1 bit you send a high pulse of duration 0.8uS and the a low of 0.45uS.
To send a 0 bit you send a high pulse of durations 0.4uS and then a low of 0.85uS.
Total bit lenght is 1.25uS +-300nS
The timing tolerances are +-150nS

Now, the arduino's run entire strings of these things with the MCU running at 8MHz so one would think a 64MHz 18F46K22 would not have an issue...

However, when i kick out a sequence manually like this...



LATD.0 = 1
ASM
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;10
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;20
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;30
nop
nop
nop
nop
nop
nop
nop
nop
;38


ENDASM
LATD.0 = 0
ASM
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;10
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;20
nop
nop
nop
nop
nop
nop
nop
nop
nop
;29

ENDASM


Everything works fine. Even using GOSUB's to the on and off bit subroutines works without an issue after a little trimming by trial and error (as above).
However, as soon as i use any sort of IF statement to read from an array, all the timings seem to go out the window and i can not adjust it enough to compensate.

My calcs say that the 46K22 @ 64MHz makes 64 instructions per uS.
Even if i cut off all the NOP's from the off time trailing sequence the pic still can not make the calculations (IF condition) within the required time.

I have tried everything i can think of so far...

I look forward to people's responses.

bucanian
- 26th December 2013, 18:08
Hi, everyone have a example how to use the WS2812 with a PICBASIC and Microchip microcontroller? Thanks!!!!

ChangChungLeds
- 1st January 2014, 15:40
Happy New Year to everybody... I buy a 240 leds strips of ws2812b, waiting for the controllers, that had a big delay from asia y buy a arduino to put this lights in action, but I think that I preffer use this lights with PICs, this is the reason why I am here. How is this program doing? Update? Thanks...

ainsley
- 6th January 2014, 11:41
You did not say what the pic voltage was , but assuming it at 5v i would connect the one side of the probe to the 5v and then to a resistor to ground and connect the joined point o the AN0 anaolog port

rnuke77
- 27th February 2014, 12:44
I ebay'd a couple of 60 led/m strips as I am interested in making a "wearable" safety vest for when I am biking. I played with a trinket - which worked fine in its limited capacity - but I wanted more and didnt want to learn another language. I hooked up an oscilloscope and tried getting the code in to light up a single led but PBP and a 16F819 @ 20mHZ coding was not fast enough for the WS2811 timing requirements. I tried using an asm subroutine within PBP for writing to the WS2811's and voila - but no time left for calculations. So, I started reading, more reading, finally ran across a thread with this link to an ASM file which uses the SPI in a 16F767 for a single LED:

http://wiki.hacdc.org/index.php?title=File:ColorStripTest_767.asm&oldid=8964

This guy (credits to David Kaufman) did a great job - I just adjusted config and pic# to my chip and was running in a couple minutes. Few minutes later I had the entire strand running. So I guess my plan is to try and go back to PBP and try to write my calculations out and then call his ASM subroutine for addressing to the led's. Thats the plan anyways - I am a horrible programmer - so if anyone else goes this route and wants to post some code so I can learn more efficient coding and tricks I would be most grateful!!

spcw1234
- 4th March 2014, 22:36
If you get something working please share it :) I had zero luck controlling these things.

rnuke77
- 5th March 2014, 11:20
This file is entirely in assembly (I'm not sure how to call assembly subroutines from PBP). The author taught how to light a single RGB, my progress to date is the start of a chaser so it will light 60 rgb's sequentially and do some color shifting (Still lots to learn here). Should load right up in MPLAB (v8.9 used) The changes you may need to make for it to run:

your chip (must have SPI and 20Mhz)
your chip config settings
change nLED for your length of string (60)
scroll down to delay subroutines to speed up, slow down ...

The original author taught how to light a single LED. You will easily detect my coding as the extent of my assembly knowledge when I opened his program was nop!7263

boroko
- 14th June 2014, 07:12
Any one had any luck yet? I just picked up a 8x string and want to play with them. The SPI sounds like and interesting approach.
Bo

RFEFX
- 22nd July 2014, 18:41
WOW, Nobody has provided code for an LED strip yet !?!?!?!?

Ok guys i will have working code for you before the weeks out. im thinking multi-color knight rider... sounds interesting. I will be using my trusty PIC16F877A Dev boards (http://www.picbasic.co.uk/forum/showthread.php?t=14210&highlight=RFEFX).

Till then, happy coding !

MichelJasmin
- 23rd July 2014, 03:35
This technique is very interesting:
Tutorial on Programming the NeoPixel (WS2812) RGB LEDs (http://thesignalpath.com/blogs/2014/07/14/watcheditdeletetutorial-on-programming-the-neopixel-ws2812-rgb-leds-equipment-giveaway/)

I'll test it with my oscilloscope someday...

ShoKre
- 24th July 2014, 17:18
Hi,
actually I had idea to put few passive component for making one-shout for short period and one shut for longer period
after that i timed mssp module to average carrier frequency (positive + negative periode) this can be done using add register i done it with 16f1827 + internal osc +PLL
intention was to make it on both MSSP modules, but i have problem using both paralell.....
ok, this is working, and now timing and hw-accelerated sending is piece of cake for basic timings.....
but i miss memory, so i have to port all onto 46k22 which is still dual mssp internal 64mhz, cheap, need to read erratas frequently but almost always there is workaround :)
why more memory ? because i want to have ability to change any led, so you need 3 byte per led, and for 100 leds, this is 300 byte of ram....

this days i obtained psoc4 and i want to organize UDB module for hardware accelerator for sw led, but ah.... this is totally hardCore

http://www.element14.com/community/blogs/markblog/2014/03/31/ir-remote-control-of-ws2812-rgb-leds-and-playing-with-the-psoc-4-pioneer-dev-kit
noone for now is'n sharing code/project, so i can learn from working project.... there is actually other shared article as arduino or others...

i hope i at least point you in some direction....
reagards

RFEFX
- 28th July 2014, 18:43
Well guys..

I have been messing around with this issue all weekend.

Still working on the timing control.. very tight timing needed to drive these strips.

till then.. happy coding.

boroko
- 9th August 2014, 00:53
The link that MichelJasmin posted is interesting in the the author found that the ON timing was the most critical, and the OFF time didn't seem to affect it. I would like to play with this more when I'm not busy with other things.

Mark

MichelJasmin
- 14th August 2014, 01:11
I need your help. I've converted the Tutorial on Programming the NeoPixel to PICBASIC. I’m using a PIC18F25K22 at 40MHz. I get the right timings (400ns & 800ns) but I don’t have a NeoPixel! I’ve ordered a Led strip from AliExpress but it takes one month to get it…

So, if anyone of you can give it a try please. Keep the data line as short as possible with a short ground return. This will improve the rise and fall time. The nice thing about these pixels is when data is forwarded, it is passed through the internal reshaping mechanism. (Ref: Understanding the WS2812 (http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/) ).

Thanks!



'************************************************* ***************
'* Name : NeoPixel
'* Author : Michel Jasmin
'* Notice : Copyright (c) 2014
'* : All Rights Reserved
'* Date : 2014-08-13
'* Version : 1.0
'* Notes :
'* :
'************************************************* ***************
'PIC18F25K22

#CONFIG
__CONFIG _CONFIG1H, _FOSC_HSHP_1H & _PLLCFG_OFF_1H & _PRICLKEN_ON_1H & _FCMEN_ON_1H & _IESO_ON_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _PBADEN_ON_3H & _CCP2MX_PORTB3_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L
__CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L & _CP2_ON_5L & _CP3_ON_5L
__CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_ON_5H
#ENDCONFIG

DEFINE OSC 40
DEFINE NO_CLRWDT 1 ' Don't waste cycles clearing WDT

'------------ ALIAS -------------------------
LedPin VAR LATC.3
NeoPin VAR LATC.5

'------------ Const -------------------------
NEO_NUM CON 60
CR CON 13
LF CON 10

'------------ Variables -------------------------
NeoGreen VAR BYTE[NEO_NUM]
NeoBlue VAR BYTE[NEO_NUM]
NeoRed VAR BYTE[NEO_NUM]
NeoPixel VAR BYTE
BitCount VAR BYTE
TempW VAR WORD

'Flags
AppFlags VAR BYTE
DataBit VAR AppFlags.0


'------------------------ Initialization -------------------------------

Clear ' Clear RAM before entry

TRISC.3 = 0 'Led Pin
TRISC.5 = 0 'NeoPin
TRISC.6 = 1 'TX1
TRISC.7 = 1 'RX1

'The serial port is used only for debugging purpose.
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 17 ' 9600 Baud @ 40 MHz -0.03%
SPBRGH = 4
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

PAUSE 100

HSEROUT [CR,LF,CR,LF,"Test NeoPixel v 17",CR,LF]

'Blink a LED just to say: Hello, I'm alive!
LedPin = 0
FOR TempW = 0 TO 4
TOGGLE LedPin
PAUSE 250
NEXT
LedPin = 0

DataBit = 0
GOSUB NeoInit

'------------ Main program -------------------------
Main:

'For testing purpose:
'DataBit = 1
'GOSUB NeoBit
'GOTO Main

GOSUB NeoDraw
GOSUB NeoRotate
PAUSE 25
GOTO Main

END

NeoBit:
IF DataBit = 1 THEN
'400ns pulse required
NeoPin = 1

'3 nop = 500ns @ 32MHz
'2 nop = 376ns @ 32MHz

'2 nop = 300ns @ 40MHz
'3 nop = 400ns @ 40MHz

ASM
nop
nop
nop
ENDASM
NeoPin = 0

ELSE
'800ns pulse required
NeoPin = 1

'5 nop = 740ns @ 32MHz
'6 nop = 880ns @ 32MHz

'6 nop = 700ns @ 40MHz
'7 nop = 800ns @ 40MHz

ASM
nop
nop
nop
nop
nop
nop
nop
ENDASM
NeoPin = 0
ENDIF

RETURN


NeoInit:
FOR NeoPixel = 0 TO NEO_NUM

IF NeoPixel < 10 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 64

ELSEIF NeoPixel < 20 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 0

ELSEIF NeoPixel < 30 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 64

ELSEIF NeoPixel < 40 THEN
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 0

ELSEIF NeoPixel < 50 THEN
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 64
ELSE
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 0
ENDIF

NEXT

RETURN

NeoDraw:
FOR NeoPixel = 0 TO NEO_NUM
FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoGreen.0[NeoPixel * BitCount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoRed.0[NeoPixel * BitCount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoBlue.0[NeoPixel * BitCount]
GOSUB NeoBit
NEXT

NEXT

NeoPin = 0

RETURN

NeoRotate:
FOR NeoPixel = 0 TO (NEO_NUM - 1)
NeoGreen[NeoPixel] = NeoGreen[NeoPixel + 1]
NeoBlue[NeoPixel] = NeoBlue[NeoPixel + 1]
NeoRed[NeoPixel] = NeoRed[NeoPixel + 1]
NEXT

NeoGreen[NEO_NUM - 1] = NeoGreen[0]
NeoBlue[NEO_NUM - 1] = NeoBlue[0]
NeoRed[NEO_NUM - 1] = NeoRed[0]

RETURN

MichelJasmin
- 14th August 2014, 04:02
Made a few mistakes, sorry...



'************************************************* ***************
'* Name : NeoPixel
'* Author : Michel Jasmin & The Signal Path dot com BLOG
'* Notice : Ref: The Signal Path dot com BLOG
'* : Tutorial on Programming the NeoPixel (WS2812) RGB LEDs
'* : http://thesignalpath.com/blogs/2014/07/14/watcheditdeletetutorial-on-programming-the-neopixel-ws2812-rgb-leds-equipment-giveaway/
'* Date : 2014-08-13
'* Version : 1.0
'* Notes :
'* :
'************************************************* ***************
'PIC18F25K22 @40MHz

#CONFIG
__CONFIG _CONFIG1H, _FOSC_HSHP_1H & _PLLCFG_OFF_1H & _PRICLKEN_ON_1H & _FCMEN_ON_1H & _IESO_ON_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _PBADEN_ON_3H & _CCP2MX_PORTB3_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L
__CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L & _CP2_ON_5L & _CP3_ON_5L
__CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_ON_5H
#ENDCONFIG

DEFINE OSC 40
DEFINE NO_CLRWDT 1 ' Don't waste cycles clearing WDT

'------------ ALIAS -------------------------
LedPin VAR LATC.3
NeoPin VAR LATC.5

'------------ Const -------------------------
NEO_NUM CON 60
CR CON 13
LF CON 10

'------------ Variables -------------------------
NeoGreen VAR BYTE[NEO_NUM]
NeoBlue VAR BYTE[NEO_NUM]
NeoRed VAR BYTE[NEO_NUM]
NeoPixel VAR BYTE
BitCount VAR BYTE
TempW VAR WORD

'Flags
AppFlags VAR BYTE
DataBit VAR AppFlags.0


'------------------------ Initialization -------------------------------

Clear ' Clear RAM before entry

TRISC.3 = 0 'Led Pin
TRISC.5 = 0 'NeoPin
TRISC.6 = 1 'TX1
TRISC.7 = 1 'RX1

'The serial port is used only for debugging purpose.
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 17 ' 9600 Baud @ 40 MHz -0.03%
SPBRGH = 4
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

PAUSE 100

HSEROUT [CR,LF,CR,LF,"Test NeoPixel v 18",CR,LF]

'Blink a LED just to say: Hello, I'm alive!
LedPin = 0
FOR TempW = 0 TO 4
TOGGLE LedPin
PAUSE 250
NEXT
LedPin = 0

DataBit = 0
GOSUB NeoInit

'------------ Main program -------------------------
Main:

'For testing purpose:
'DataBit = 1
'GOSUB NeoBit
'GOTO Main

GOSUB NeoDraw
GOSUB NeoRotate
PAUSE 25
GOTO Main

END

NeoBit:
IF DataBit = 1 THEN
'400ns pulse required
NeoPin = 1

'3 nop = 500ns @ 32MHz
'2 nop = 376ns @ 32MHz

'2 nop = 300ns @ 40MHz
'3 nop = 400ns @ 40MHz

ASM
nop
nop
nop
ENDASM
NeoPin = 0

ELSE
'800ns pulse required
NeoPin = 1

'5 nop = 740ns @ 32MHz
'6 nop = 880ns @ 32MHz

'6 nop = 700ns @ 40MHz
'7 nop = 800ns @ 40MHz

ASM
nop
nop
nop
nop
nop
nop
nop
ENDASM
NeoPin = 0
ENDIF

RETURN

NeoInit:
FOR NeoPixel = 0 TO (NEO_NUM - 1)

IF NeoPixel < 10 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 64

ELSEIF NeoPixel < 20 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 0

ELSEIF NeoPixel < 30 THEN
NeoGreen[NeoPixel] = 0
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 64

ELSEIF NeoPixel < 40 THEN
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 0

ELSEIF NeoPixel < 50 THEN
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 0
NeoRed[NeoPixel] = 64
ELSE
NeoGreen[NeoPixel] = 64
NeoBlue[NeoPixel] = 64
NeoRed[NeoPixel] = 0
ENDIF

NEXT

RETURN

NeoDraw:
FOR NeoPixel = 0 TO (NEO_NUM + 1)
TempW = (NeoPixel * 8)

FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoGreen.0[TempW + BitCount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoRed.0[TempW + BitCount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 STEP -1
DataBit = NeoBlue.0[TempW + BitCount]
GOSUB NeoBit
NEXT

NEXT

NeoPin = 0

RETURN

NeoRotate:
FOR NeoPixel = 0 TO (NEO_NUM - 1)
NeoGreen[NeoPixel] = NeoGreen[NeoPixel + 1]
NeoBlue[NeoPixel] = NeoBlue[NeoPixel + 1]
NeoRed[NeoPixel] = NeoRed[NeoPixel + 1]
NEXT

NeoGreen[NEO_NUM - 1] = NeoGreen[0]
NeoBlue[NEO_NUM - 1] = NeoBlue[0]
NeoRed[NEO_NUM - 1] = NeoRed[0]

RETURN

CuriousOne
- 9th November 2015, 10:54
Ordered strip recently, will see how this code works :)

Dave
- 9th November 2015, 11:56
Hey CuriousOne, Have a look at this thread.
http://www.picbasic.co.uk/forum/showthread.php?t=19694

CuriousOne
- 6th December 2015, 18:32
Well, all this is way too complicated.

I wanted something simple, to drive single rgb led via 1 pin :)

PhilXu007
- 9th December 2017, 06:52
you can use the digital strips with the built-in programs,
most digital led controllers can support the ws2812,sk6812 led,
or the Remote controller with program inside,it is much easy,
also the T-1000s,t300k controller are available too,use the lededit software to create the color changing effect,

ShoKre
- 17th December 2017, 09:56
Hi,
best HW driven solution, which i use for years, is that you use SPI internal hw,
you can make SPI2NRZ circuit with few external parts, digital way (74xxx) or
analog https://hackaday.com/2014/02/04/ws2811-spi-driver-using-one-transistor-and-passives/
like this, i had to tune resistors, for better voltage variation tolerance, but work like this to.

so, when you have hardware helper, and internal hardware, then you can paly in interrupt later.

for first step you have to initialise MSSP hardvare on 800kbs with propper flags and registers
based on your clock and device datasheet. (yes you have to read it few time until get proper setings)
i actualy deal with 2 mssp paralell in interrupt, so i have time in main loop to play with other things.



for WS_CNT = 0 to number_of_ws
SSP2BUF = R1[WS_CNT]
SSP1BUF = R2[WS_CNT]
SSP1IF = 0
' something litle can feet here if interrupt... i have serial receive routine..
WHILE SSP1IF = 0 : WEND
SSP2BUF = G1[WS_CNT]
SSP1BUF = G2[WS_CNT]
SSP1IF = 0
' something litle can feet here if interrupt... i have serial receive routine..
WHILE SSP1IF = 0 : WEND
SSP2BUF = B1[WS_CNT]
SSP1BUF = B2[WS_CNT]
SSP1IF = 0
' something litle can feet here if interrupt... i have serial receive routine..
WHILE SSP1IF = 0 : WEND
next WS_CNT
pauseus 60 ' for latch....

i hope you will understund directions, i have large code which i optimise for my work, so i
don't want to share it, but trust me this part i shared is core, all other is playing with it...

acrually , on slower pic, you can expirience for/next too slow, you can use goto instead, and
of course, today pic speed is 32mhz+ with internal rc osc+pll, already on .5$ parts, so forget
old 16f84 parts for this, use kind of 18f46k22 or 16f1827 or part like this....