I wrote a library for a 16x16 WS2812B RGB LED matrix board a few years ago (Controlling a WS2812B RGB LED Matrix), but they still fascinate me, so I wrote a program in Positron8 BASIC for a PIC18F26K22 device, that animates a flame image on the 16x16 LEDs. It is very low resolution (16x16), but gives a nice effect, and the lighting of a room looks just like a real flame.
The Positron8 BASIC code listing for the flame animator is listed below:
'
' /\\\\\\\\\
' /\\\///////\\\
' \/\\\ \/\\\ /\\\ /\\\
' \/\\\\\\\\\\\/ /\\\\\ /\\\\\\\\\\ /\\\\\\\\ /\\\\\\\\\\\ /\\\\\\\\\\\ /\\\\\\\\\
' \/\\\//////\\\ /\\\///\\\ \/\\\////// /\\\/////\\\ \////\\\//// \////\\\//// \////////\\\
' \/\\\ \//\\\ /\\\ \//\\\ \/\\\\\\\\\\ /\\\\\\\\\\\ \/\\\ \/\\\ /\\\\\\\\\\
' \/\\\ \//\\\ \//\\\ /\\\ \////////\\\ \//\\/////// \/\\\ /\\ \/\\\ /\\ /\\\/////\\\
' \/\\\ \//\\\ \///\\\\\/ /\\\\\\\\\\ \//\\\\\\\\\\ \//\\\\\ \//\\\\\ \//\\\\\\\\/\\
' \/// \/// \///// \////////// \////////// \///// \///// \////////\//
' Let's find out together what makes a PIC Tick!
'
' Interface to a 16x16 matrix display that uses WS2812B RGB chips for the pixel elements.
' Animate Fire images held in Flash memory, on the matrix, based upon converted .bmp files.
'
' Written by Les Johnson for the Positron8 BASIC Compiler.
'
Device = 18F26K22 ' Tell the compiler what device to compile for
Declare Xtal = 64 ' Tell the compiler what frequency the device is operating at (in MHz)
'
' Setup some $defines for the WS2812B matrix library
'
$define Matrix_Pin PORTC.0 ' The pin used for the WS2812B matrix chips
$define Matrix_X_Size 16 ' The amount of X axis pixels on the matrix display
$define Matrix_Y_Size 16 ' The amount of Y axis pixels on the matrix display
Include "WS2812B_Matrix.inc" ' Load the WS2812B Matrix library into the program
Include "Fire_Images.inc" ' Load the image data in flash memory tables
'
' Create a flash memory table of the addresses of the image data tables
'
Dim Images As Flash16 = {Fire_01, Fire_02, Fire_03, Fire_04, Fire_05,
Fire_06, Fire_07, Fire_08, Fire_09, Fire_10,
Fire_11, Fire_12, Fire_13, Fire_14, Fire_15,
Fire_16, Fire_17, Fire_18, Fire_19, Fire_20,
Fire_21, Fire_22}
'
' Create some global variables here
'
Dim bImage As Byte ' Holds which image to display
Dim wImageAddress As Word ' Holds the address of an image's flash memory data table
'---------------------------------------------------------------------------------------------
' The main program starts here
' Animate the fire images on the WS2812B 16x16 matrix panel
'
Main:
Setup() ' Setup the program and any peripherals
Do ' Create a loop
For bImage = 0 To Bound(Images) ' Create a loop for the amount of images to animate
wImageAddress = CRead16 Images[bImage] ' Get the address of an image's flash memory table
Display_Image(wImageAddress) ' Display a 24-bit RGB888 image on the matrix display
DelayMS 80 ' A delay between images, so the animation is not too fast
Next
Loop ' Do it forever
'-----------------------------------------------------------------------------
' Setup the program and any peripherals
' Input : None
' Output : None
' Notes : None
'
Proc Setup()
Oscillator_64MHz() ' Set the device to operate at 64MHz using the internal oscillator
Matrix_Setup() ' Setup the interface to the WS2812B RGB matrix controller chips
Matrix_Cls($000000) ' Clear the matrix display with none of the LEDs illuminated
EndProc
'-----------------------------------------------------------------------------
' Display a 24-bit RGB888 image on the matrix display
' Input : pImageAddr holds the 16-bit address of the flash memory image table
' Output : None
' Notes : None
'
Proc Display_Image(pImageAddr As Word)
Dim bIndex As Byte ' Holds the matrix pixels to read and write
Dim lPixel As Long ' Holds the 24-bit pixel colour
For bIndex = 0 To 255 ' Create a loop for the amount of pixels (LEDs) on the matrix
lPixel = CRead24 pImageAddr[bIndex] ' Read a 24-bit RGB888 value from the image flash table
Matrix_lDisplay[bIndex] = lPixel ' Fill the matrix array with the colour value
Next
Matrix_UpdateGamma() ' Update the matrix display, with Gamma
EndProc
'-----------------------------------------------------------------------------
' Set the PIC18F26K22 device to 64MHz operation using its internal oscillator
' Input : None
' Output : None
' Notes : None
'
Proc Oscillator_64MHz()
OSCCON = $70
OSCCON2 = $04
OSCTUNE = $40
DelayMS 100
EndProc
'---------------------------------------------------------------------------------------------
' Setup the fuses to use the internal oscillator on a PIC18Fx6K22 device.
' The OSC pins are general purpose I/O.
'
Config_Start
FOSC = INTIO67 ' Internal oscillator block. Port function on RA6 and RA7
PRICLKEN = Off ' Primary clock disabled
MCLRE = EXTMCLR ' MCLR Pin enabled
WDTEN = Off ' WDT disabled
Debug = Off ' Background debugger disabled. RB6 and RB7 configured as general purpose I/O pins
PLLCFG = Off ' Oscillator used directly
XINST = Off ' Extended Instruction Set disabled
FCMEN = Off ' Fail-Safe Clock Monitor disabled
IESO = Off ' Oscillator Switchover mode disabled
PWRTEN = On ' Power up timer enabled
BOREN = Off ' Brown-out reset disabled
BORV = 190 ' VBOR set to 1.9 V nominal
WDTPS = 8192 ' 1:8192 (approx 30 seconds)
HFOFST = Off ' The access clock is not held off until the HF-INTOSC is stable
PBADEN = Off ' PORTB<4:0> pins are configured as digital on reset
CCP2MX = PORTC1 ' CCP2 input/output is multiplexed with RC1
CCP3MX = PORTB5 ' P3A/CCP3 input/output is multiplexed with RB5
T3CMX = PORTC0 ' T3CKI is on RC0
P2BMX = PORTB5 ' P2B is on RB5
STVREN = On ' Stack full/underflow will cause a reset
LVP = Off ' Single-Supply ICSP disabled
Cp0 = Off ' Block 0 (000800-001FFF) not code protected
CP1 = Off ' Block 1 (002000-003FFF) not code protected
CPB = Off ' Boot block (000000-0007FF) not code protected
CPD = Off ' Data EEPROM not code protected
WRT0 = Off ' Block 0 (000800-001FFF) not write protected
WRT1 = Off ' Block 1 (002000-003FFF) not write protected
WRTB = Off ' Boot block (000000-0007FF) not write protected
WRTC = On ' Configuration registers (300000-3000FF) write protected
WRTD = Off ' Data EEPROM not write protected
EBTR0 = Off ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
EBTR1 = Off ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
EBTRB = Off ' Boot block (000000-0007FF) not protected from table reads executed in other blocks
Config_End
Below is the circuit for the display in the Proteus/Isis simulator, and it is running the flame animation demo. See how simple the circuit is? The newer PIC18F devices have an internal oscillator that is capable of running at 64MHz, so there is no need for an external resonator or crystal at all, and the single pin for the matrix display can be any of the device's pins because the code does not use any special peripherals, just good old bit-bashing created by a fast and efficient compiler. i.e. Positron8:
If you build the above circuit with the matrix board, make sure you have a 5 Volt Power Supply Unit that is capable of up to 4 Amps, or over, because when all the LEDs are illuminated fully on a 16x16 matrix, the display draws a lot of current, as I found out to my surprise. However, the flame animator draws approx 600mA.
Below is a video of the 16x16 WS2812B matrix board, animating the flame images. The board being used, is the Amicus8 development board, with a PIC18F26K22 device plugged into it:
The Positron8 Compiler source code and Proteus simulation files for the flame animator are available from here: WS2812B_Fire_Animate.zip