PDA

View Full Version : WS2811 and WS2812 One-Wire Communication Assembly Help



rsocor01
- 8th October 2017, 21:48
Hi all,

I'm working on a project with the WS2812B (http://www.seeedstudio.com/document/pdf/WS2812B%20Datasheet.pdf) LED lights. The PIC needs to send 24 bits for every LED that is connected in series. The 1st byte being for the green, the 2nd byte being for the red, and the 3rd byte being for the blue component. The 24 bits for the first LED look like this,



'###### WS2812 HIGH BIT (1 CODE) ######
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T1H #######
ASM
nop ; ~97 nSecs
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T1L #######
ASM
nop
nop
nop
ENDASM
'#####################################




'###### WS2812 LOW BIT (0 CODE) ######
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
'#####################################





'###### WS2812 LOW BIT (0 CODE) ######
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
PORTD.0 = 1 'WS2812 DRIVE LINE
'####### T0H #######
ASM
nop ; 97 nSecs
nop
nop
ENDASM
PORTD.0 = 0 'WS2812 DRIVE LINE
'####### T0L #######
ASM
nop
nop
nop
nop
nop
nop
nop
nop
ENDASM
'#####################################



Here, I'm sending [255,0,0] for a pure green output. As you can see this code is not the most effective one. Specially, when you need to send data to 100+ WS2812B LEDs. If you add any FOR..NEXT, or IF...ENDIF loops, the precise timing of the HIGH and LOW bits is messed up. Actually, I think that any PICBasic command wouldn't help with the timing. Any help to implement this code in assembly would be appreciated. I'm using a PIC18F4550 at 48MHz.

Thank you,

Robert

richard
- 9th October 2017, 00:25
basic looping structures are the very essence of good programing ,try this

its based on one of those 8x8 ws2812 panels and sends data TO 64 leds
it can handle upto 256/3 leds , and can take the data from sram and/or the flash rom

rsocor01
- 10th October 2017, 12:15
Thanks. Assembly is not something that I'm very familiar with. I'll go over this code. It seem to do what I need.

Robert

Ioannis
- 14th October 2017, 20:48
I am after such a project too. Unfortunately Assembly is not too friendly.

I found this AN from Microchip, AN1606 that uses the CLC module on some new chips, like the 16F1509.

After a cryptic analysis of the timing using TMR, PWM and CLC modules, the AN claims that can produce the strict timing required for the WS2811 chip.

Well, only the setting is shown and not the use of this settings on the PIC.

Anyone has any idea how to use the PIC for sending the RGB data?

Following is the settings for the 1509 registers to obtain the correct timing on the RC4/CLC4 port pin #6, based on the slow mode of WS2811.



' Initialize PIC16(L)F1509 CLC2, CLC4, Timer2, and MSSP
' for WS2811 signal transmission protocol
' Loading SSP1BUF register sends that data byte out the RC4/CLC4 pin
' PWM1 routed straight through CLC2
CLC2GLS0 = $20
CLC2GLS1 = $00
CLC2GLS2 = $00
CLC2GLS3 = $00
CLC2SEL0 = $00
CLC2SEL1 = $06
CLC2POL = $0E
CLC2CON = $82;

' (SPI SDO & SPI CLK) || (nSPI SDO & SPI CLK & PWM1)
' PWM1 comes through CLC2
CLC4GLS0 = $44
CLC4GLS1 = $10
CLC4GLS2 = $80
CLC4GLS3 = $20
CLC4SEL0 = $50
CLC4SEL1 = $05
CLC4POL = $01
CLC4CON = $C0

' Adjust Timer2 period for desired baud rate
' One bit period is two Timer2 periods
T2CON = $04
PR2 = 5
' Adjust PWM1 duty cycle for desired "0" data-bit duty cycle
' ‘1’ data-bit duty cycle is automatically 50%
PWM1CON = $E0
PWM1DCH = 2
PWM1DCL = 0

' MSSP configured for SPI master with Timer2_Period/2 clock
SSP1CON1 = $23

' Output on RC4/CLC4
TRISC = $EF


Any help appreciated.

Ioannis

richard
- 16th October 2017, 04:26
interesting find ioannis.

the an seems to lack many details not just how to use it ,I tried it out on a pic16f1619 and discovered that the an description of the clc cells setup is quite misleading

the reality is they are set like in these images


I'm not sure I have this exactly correct but it looks to work

i have included my working example it spits out data for 64 leds [192 bytes] in 2mS.

I cant see much advantage to it over my earlier routine you only have a few uS between bytes barely enough time for a pbp style dt interrupt

richard
- 16th October 2017, 05:38
a small refinement
CLC1 can be released from use its not needed with a 16f1619

by

CLC2SEL1 = $0E; in lieu of 04

Ioannis
- 16th October 2017, 08:20
Richard, thanks for looking into this.

For 64 led's I think the timing for each frame is 3,84ms. Does it work with 2ms?

Anyway, you did a great job on this. Really fast!

Well, the AN implied, or at least I wanted to be that way, this solution would be fast enough for the MCU to do other tasks.

But as you tested, yes, seems there is not enough time.

I want to use this strips for a 60 led's (1m bar) for medical purposes and the timing is very strict.

Thanks,
Ioannis

richard
- 16th October 2017, 08:41
I may have measured that wrong, its more like 5mS now for 192 bytes


the spi takes 25uS per byte and there is a 5us gap between bytes as is

I think the gap between bytes needs to be less than 50uS

so an isr has 60us to get in do something and get out again

conversely an asm isr could feed the spi buffer every 60uS or so

richard
- 16th October 2017, 08:48
just for a joke I upped the osc to 32mHz ,
it still works , its less than 3mS now for 192 bytes
these things aren't that fussy

richard
- 16th October 2017, 09:00
just remembered de morgan equivalents , have not done Boolean algebra since ttl was in vogue

Ioannis
- 16th October 2017, 10:13
It seems that the chips WS2811 are quite tolerant on the timing specs.

Ioannis

mark_s
- 17th October 2017, 16:48
Did you guys see this example/thread?

http://www.picbasic.co.uk/forum/showthread.php?t=19597

richard
- 17th October 2017, 23:28
Did you guys see this example/thread?

indeed . the point of my posts are to demonstrate tight loop routines that achieve the same task without all that spaghetti code


here is an interrupt driven version of the clc method using linear sram memory access to facilitate a 240 byte buffer on a pic16

mark_s
- 17th October 2017, 23:59
Yes, I understand what your goal is and want to try your code out. I have a 8x8 neopixel to run it on.

I referenced the other thread for the op who said he wasn't great at assembly code.

Thanks

richard
- 18th October 2017, 00:43
Yes, I understand what your goal is and want to try your code out. I have a 8x8 neopixel to run it on.




I would love to hear how you get on

mark_s
- 19th October 2017, 00:58
Richard I gave the code in post #2 a try. I don't have a 12mhz crystal so I am having problems configuring 4550 for 48mhz internal osc. My test board has a 10mhz resonator. The usb pre-scale stuff is throwing me off. If you could help me with the configurations for internal osc 48mhz or 40mhz using the pll and the 10mhz resonator. I may have it set ok I'm getting the signal on portc.0

Also as posted the code makes one pass and stops. Is this the way it is intended to function? The neopixel did nothing so I added "goto aloop"
above "stop" and get continuous pulse train on c.0. A few of the leds light. Unable to try your other code because I don't have that pic. Tomorrow I will give it another go.
Thanks



aloop:


p_pc=nows ;set number of leds to load
@ Flash2Ram _pixels,_rw1' Get a String from flash memory
p_pc=nows ;set number of leds to show
call showpix

goto aloop '????????????????
stop
end

richard
- 19th October 2017, 02:32
I don't have a 12mhz crystal so I am having problems configuring 4550 for 48mhz internal osc. My test board has a 10mhz resonator. The usb pre-scale stuff is throwing me off. If you could help me with the configurations for internal osc 48mhz or 40mhz using the pll and the 10mhz resonator.


the pll input needs to be 4MHz if you are going to use it . a 10MHz resonator
cant be divided down to 4MHz using plldiv to keep pll input within specs .

the xtal/res needs to be a multiple of 4 for correct use, my board has a 20MHz xtal

out of spec operation may be possible but may lack stability required for this use


Also as posted the code makes one pass and stops

yep that's all that code did , you should see a white "R" , a loop serves no
purpose here, the other examples are more elaborate




if you want text scroll



aloop:

for p_offset=0 to 1536 step 24
p_pc=nows ;set number of leds to load
@ Flash2Ram _pixels,_rw1' Get a String from flash memory
p_pc=nows ;set number of leds to show
call showpix
pause 200
next

goto aloop
stop
end
rw1:
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;192
@ DW 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0 ;23
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0 ;47
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0 ;71
@ DW 0,0,0, 50,50,50, 50,50, 50,50,50, 50,0,0,0, 0,0,0, 0,0,0, 0,0,0 ;95
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0 ;119
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0 ;143
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0 ;167
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0 ;191
;384
@ DW 0,0,0, 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;576
@ DW 0,0,0, 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;768
@ DW 0,0,0 ,50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;960
@ DW 0,0,0, 0,0,0, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;1152
@ DW 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;1344
@ DW 0,0,0 ,50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 50,50,50, 0,0,0, 0,0,0, 50,50,50, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0 ,50,50,50, 50,50,50, 50,50,50, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
;1536
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0
@ DW 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0

mark_s
- 19th October 2017, 21:38
Richard

I changed the crystal to 20mhz and added the scroll code above. It's now working, so thanks for your efforts.

I'll study the other code and see what I can do.

Mark

Ioannis
- 15th November 2017, 22:25
Similar to WS2811/2812 is the APA102C led chip, produced as a strip too.

The Datasheet is unclear of the timing specs.

I tried many hours to make it work but in vein. No led so far is under my control. Any ideas, welcome.

An example code is this:


arraywrite leds,[0,0,0,0,$f0,128,128,128,255,255,255,255]

shiftout led_data,led_clock,1,[leds[0],leds[1],leds[2],leds[3],leds[4],leds[5],leds[6],leds[7],leds[8],leds[9],leds[10],leds[11]]

Lcdout $fe,$1,"Stoped"
stop


Any help?
Ioannis

richard
- 15th November 2017, 23:16
this may help
https://www.youtube.com/watch?v=UYvC-hukz-0

Ioannis
- 16th November 2017, 20:20
Hi Richard.

Thanks for the link. The real help was ... the color of the cables. On my strip the ground is Blue and +5V is Black. Really! They made +5V Black!

Of course I used Black as ground and that was the problem.

Be careful if color is not red then,

Black is +5, NOT ground.
Blue is Ground.

Chinese people might have a different color preferences...

I had it working now. Almost got crazy, since logic analyzer was showing all was OK!

This type of LED's is more easy to control since they do not need strict timings. Just spit out at whatever pace you like or can and LED's follow. Very easy for any MCU.

People have reported driving SPI up to 60MHz on these strips.

Ioannis

Ioannis
- 17th November 2017, 08:35
The following is a simple test program to demonstrate how to use of APA-102 leds.

It lights the Blue led and shifts it ten places in 100ms interval.

To successfully manage this, tens of hours were spent... Datasheet sucks.

But in general is much easier to control as the timings are those of an SPI interface and can be really fast driven if you have the resources.



arraywrite red_a,[0,0,0,0,0,0,0,0,0,0,0]
arraywrite green_a,[0,0,0,0,0,0,0,0,0,0,0]
arraywrite blue_a,[255,0,0,0,0,0,0,0,0,0,0]

gosub display_led

stop

display_led:
for k=0 to led_num
for i=0 to led_num
shiftout led_data,led_clock,1,[lum,blue_a[i],green_a[i],red_a[i]]
next i
gosub shift_sub
next k
pause 1000 'delay from one color to another
return

shift_sub:
shiftout led_data,led_clock,1,[%11100011,0,0,0,0,0] 'END of Frame
pause 100'led move step delay
temp=red_a[k]:RED_A[k]=RED_A[k+1]:RED_A[k+1]=temp
temp=green_a[k]:green_a[k]=green_a[k+1]:green_a[k+1]=temp
temp=blue_a[k]:blue_a[k]=blue_a[k+1]:blue_a[k+1]=temp
return


Ioannis

richard
- 18th November 2017, 10:15
But in general is much easier to control as the timings are those of an SPI interface and can be really fast driven if you have the resources.


I had 3 in the parts bin , so I had a go using mssp module . @64mhz with the fastest spi clk its no problem at all .
a complete 3 led frame is less than 80uS . heaps easier than ws2812:smile:

Ioannis
- 18th November 2017, 11:10
Great job on the asm Richard.

Though this kind of LED's are easier most people look after the WS28xx series.

Ioannis

louislouis
- 1st December 2019, 19:57
Hello all,
here is, if someone interested my simple one (or more) neopixel driver. In demo it fades through basic RGB colours. Code is simply modifiable to lit up any kind of colour. Only changing the NeoRed, NeoGreen, NeoBlue variables.


'************************************************* ***************
'* Name : One_Neopixel_driver *
'* Author : Louis *
'* Notice : Copyright (c) 2019 *
'* : All Rights Reserved *
'* Date : 1. 12. 2019 *
'* Version : 1.0 *
'* Notes : *
'* : 12F1840 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
__config _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32 ; Use internal clock 32MHz
OSCCON = %11110000 ; 8 MHz internal x 4
OSCTUNE = %00000000 ; Internal osc tunning

WHILE !OSCSTAT.3 ; Wait for stable OSC
WEND

TRISA = 0
ANSELA = 0
OPTION_REG.7=1 ; disable internal pull-ups
ADCON0 = 0
ADCON1 = 0


;------------ Variables ---------------------

NeoGreen VAR BYTe
NeoBlue VAR BYTE
NeoRed VAR BYTE
NeoPixel VAR BYTE
BitCount VAR BYTE
DataBit VAR byte
Cnt var byte
n var byte
Flag var bit

;------------ ALIAS -------------------------

NeoPin VAR porta.2

;----------- Initialization ----------------

Clear ; Clear All

;------------ Main program ------------------
Main:
pause 10

if flag = 0 then
n=n+1
else
n=n-1
if n=0 then
flag = 0
cnt = cnt + 1
endif
endif

if n = 254 then flag = 1
if cnt > 2 then cnt = 0

if cnt = 0 then
NeoGreen = n ; value 0-254 for green color
else
NeoGreen = 0
endif

if cnt = 1 then
Neoblue = n ; value 0-254 for blue color
else
Neoblue = 0
endif

if cnt = 2 then
Neored = n ; value 0-254 for red color
else
Neored = 0
endif

gosub NeoDraw

GOTO Main

END

;------------ Extract bites ---------------
NeoDraw:
FOR BitCount = 7 TO 0 step -1
DataBit = NeoGreen.0[bitcount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 step -1
DataBit = NeoRed.0[bitcount]
GOSUB NeoBit
NEXT

FOR BitCount = 7 TO 0 step -1
DataBit = NeoBlue.0[bitcount]
GOSUB NeoBit
NEXT
RETURN

;------------ Pulse generator ---------------
NeoBit:
IF DataBit = 1 THEN
;generate 800ns pulse
NeoPin = 1
ASM
nop
nop
nop
nop
nop
ENDASM
NeoPin = 0
ELSE
;generate 400ns pulse
NeoPin = 1
ASM
nop
nop
ENDASM
NeoPin = 0
ENDIF
RETURN