PDA

View Full Version : NeoPixel (WS2812B) Demo



MichelJasmin
- 2nd December 2014, 21:42
In a previous thread (http://www.picbasic.co.uk/forum/showthread.php?t=18431) I've posted an example how to use those addressable RGB leds (WS2812B) aka NeoPixel. I've optimized the code and made a set of include files.

The NeoPixels can be used with almost any PIC running at 20MHz. The only limit is the available RAM: you need 3 arrays, one for each colour (RGB). The size of each array is the number of leds to control. With a large number of pixels I suggest using a PIC18F. See PicBASIC manual for more information on arrays limits.

A PIC running @20MHz is more than enough to make almost any animation. The values are pre-computed and then streamed in one shot. You have plenty of time to compute the next sequence unless you want to build a video screen!

Two gamma correction files are supplied for better fades in or out. One is for PIC18F and one for the others.
Ref.: https://learn.adafruit.com/led-tricks-gamma-correction/the-quick-fix
See NeoPixelDump.pbp for instructions.

The demo code show you how to run them on PIC12F683. Now the only limit is your imagination! Be creative!

http://youtu.be/QDAwFmu4YuM

Demo code:


'************************************************* ***************
'* Name : NeoPixelDemo.pbp *
'* Author : Michel Jasmin *
'* Notice : NO Copyright (c) 2014 Michel Jasmin ;) *
'* : No Rights Reserved *
'* Date : 2014-11-29 *
'* Version : 1.0 *
'* Notes : Demo how to use WS2812B (neoPixels) on *
'* : a PIC12F683 @20MHz *
'************************************************* ***************

#IF __PROCESSOR__ = "12F683"
#CONFIG
__config _HS_OSC & _WDT_OFF & _MCLRE_ON & _CP_OFF
#ENDCONFIG

#ELSE
#MSG "Wrong Processor selected!"
#ENDIF

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

'------------ Const -------------------------

NEO_NUM CON 18 'Number of pixels

'------------ Variables -------------------------

NeoGreen VAR BYTE[NEO_NUM]
NeoBlue VAR BYTE[NEO_NUM]
NeoRed VAR BYTE[NEO_NUM]
NeoPixel VAR BYTE 'Looping variable
NeoPixValue VAR BYTE 'Value to be bit-banged

'------------ ALIAS -------------------------

NeoPin VAR GPIO.2

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

Clear ' Clear RAM before entry

ANSEL = 0
CMCON0 = 7 'Comparator disabled
CCP1CON = 0
WPU = 0
TRISIO.2 = 0 'NeoPin

NeoPin = 0

GOSUB NeoInit

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

Main:

GOSUB NeoPixelDump
GOSUB NeoPixelRotate

PAUSE 50

GOTO Main

END

NeoInit:
'Init values for 18 leds string.
FOR NeoPixel = 0 TO (NEO_NUM - 1)

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

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

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

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

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

NEXT

RETURN

NeoPixelRotate:
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


INCLUDE "..\_Include\NeoPixelDump.pbp"

74977497

Demon
- 2nd December 2014, 23:17
Joyeux Halloween! LOL

Nice work.

Robert

Dave
- 3rd December 2014, 12:45
Where can I get the file NeoPixelDemo.ZIP as well as the INCLUDE file? I would like to try them.

pedja089
- 3rd December 2014, 12:51
Scroll down code and you will find link, or click here
http://www.picbasic.co.uk/forum/attachment.php?attachmentid=7497&d=1417555928

astanapane
- 12th August 2018, 08:21
That is really nice piece of code, even if i cannot understand the include asm file.

Have anyone used it with a 16 or 24 led WS2812 ring? (not the B version)

I've tried with the pic currently have 18F26K22 at 64 Mhz. On a 16 ring or 24 ring, i cannot set up all the led's to be functioned.

when i set


NEO_NUM CON 16 'Number of pixels in Cyrcle

Only 8 out of 16 LED are functioned.

In case i increase the number, to 29, only 14 LED's are working, then no matter what number i use.....30+, still 14 LED's are light.

The last two LED's are not working. Have been test it with 24 ring as well, and the last 2 LED's are not working.

If anyone have experienced the same, would be nice to share your comments.

richard
- 12th August 2018, 14:03
I've tried with the pic currently have 18F26K22 at 64 Mhz. On a 16 ring or 24 ring, i cannot set up all the led's to be functioned.

given that the include files expect a 20mhz clock what steps have you taken to compensate for running at more than 3 times the expected speed

astanapane
- 12th August 2018, 17:04
Ooops havent seen that. I might try a 20 Mhz crystal then. Should be easier. :)

astanapane
- 12th August 2018, 20:07
I used 4Mhz crystal to 4xPLL and it worked. I couldnt see in the datasheet of the PIC18F26K22 any 20Mhz configuration.

The code is really good. thanks the Author: Michel Jasmin

astanapane
- 17th August 2018, 12:18
May i ask something?

Could i use all this code as a secondary code?

I'm thinking to use it only as an effect when the PIC is powered up, the RGB led ring to do its pattern.

But the main program not to be affected by this code.

DT has given to us the interrupt function of a flashing LED without disturbing the main program.

But i really dont know how to import all this code or how to use this DT's interrupt method here.

Could anyone guide me? Thanks a lot.

richard
- 18th August 2018, 04:04
Could i use all this code as a secondary code
But the main program not to be affected by this code.
?


using that code it takes about 1mS to send data to 24 ws2812's . so if your main program can tolerate 1mS gaps in processing every 50mS it would work ok

if you used a more modern chip with a clc module then you could adapt my code
found here :-
http://www.picbasic.co.uk/forum/attachment.php?attachmentid=8485&d=1508279203
that updates the leds as a background interrupt driven process with very very little overhead

see this thread for that and other more efficient possibilities
http://www.picbasic.co.uk/forum/showthread.php?t=23399



But i really dont know how to import all this code or how to use this DT's interrupt method here.
what have you tried ?

astanapane
- 18th August 2018, 20:05
Many years ago, i did a simple RFID reader program.

What it does is to read the RFID tag and if the ID number is stored in the PIC's ram, then it will make a port high.

That is the whole program.

I haven't tried anything yet to embed the above RGB code. What i would like to do with this code, is to work on the backround as an effect, when:

The RFID tag is valid: to light the RGB ring in Green, then to continue working on the backround.
The RFID tag is not valid: to light up the RGB ring in LED.

I will try without interrupt and i will add the RFID code inside the main of the RGB code. Will let you know.

astanapane
- 18th August 2018, 21:07
this is the addition to the main:


serin2 rfid,84,[WAIT($02),str BUF\10]

Check_List:
FOR tagNum = 1 to 3 ' scan through known tags
FOR idx = 0 TO 9 ' scan bytes in tag
READ (((tagNum-1)*10) + idx), char ' get tag data from table
IF (char <> buf(idx)) THEN Bad_Char ' compare tag to table
NEXT
GOsub Tag_Found ' all bytes match!

Bad_Char: ' try next tag
NEXT

Bad_Tag:
tagNum = 0
FREQOUT porta.3, 1000 */ $100, 115 */ $100 ' groan