Having checked that there was on-line support I ordered a WS2812 8x8 RGB LED matrix expecting it to be addressed as an XY coordinate structure, not a daisy chain (tape) of 64 LEDs wrapped into 8 rows of 8!
A “WS2812 Led animation” search yielded little that I could readily and immediately understand. When I found a YouTube video produced by Kevin Darrah he was addressing a 16 x 16 matrix (256LEDs daisy chained) as though it was an XY coordinate system.
His Excel utility compiled text code for copy/paste to his sketch within which were all necessary functions; no libraries needed to be imported.
When he selected cells within his utility and RGB values were added, they applied to those selected cells without discrimination; not what I desired so I redesigned and rebuilt it. That also meant that I had to alter his sketch for 8x8 compatibility.
As I asked more of my WS2812 I had to continually modify my Excel application, LED_Utility.xlsm.
The Excel Workbook now offers:
- LED RGB properties to be addressed individually.
- Dynamically altering those properties through programming.
- XY relocation of those properties to simulate motion.
- RGB values to be addressed as well as altering the XY location.
- Both 8x8 and 16x16 LED addressing.
- A small collection of RGB values for quick reference.
- Develop a red hollow square and turn it on and off.
- Overlay another square with a layer of a different colours and alternate between them.
- Grow the Red square and play with it.
- Consider thoughts on use of functions to hold display elements; I’ll build a fading spiral.
- Create a design where colours fade in and out.
- Bring motion into the design.
- Address 16x16 arrays.
I do recognize that programming knowledge will create issues. I have offered some guidance but suggest research or ask of someone who might personally advise you.
TO BEGIN
Assemble the hardwareIf your matrix comes without header pins solder the bank of header pins to the rear of the Matrix at the lower location (DIN, +5V, GND). Connect the DIN pin to pin 8 on the right of the Arduino and the other two to matching locations on the other side of the board.
For this board, and the utility, XY (0, 0) is the top left.
The Excel UtilityOpen the LED_Utility.xlsm file.You will see three sheets, “Eight”, “Sixteen” and “ColMap”.
The last is a small sample of RGB codes provided for reference.
I have set LED_Utility.xlsm to read-only to prevent both overwriting but also to encourage utilizing the “SaveAs” to retain a file for possible reuse. Some other “error trappings” have been built in as well.
Select the “Eight” Worksheet.
Notice that the right hand grid is filled with zeroes. That is important as the sketch will not accept‘null’ values.
There are four buttons as shown above (on “Sixteen” they will probably be off screen to the right, one below the other, but will function as described below).
To produce text code:
“Show” displays the RGB of values in the left grid. It only handles values from 0-255. It will alert to values above 255 or any variables.
“Var Map” accepts numeric and variables but offers no display.
“Wrap Map” is two-tiered. It accepts RGB values typically entered for a “Show” display. It then adds a modulus function for sketch coding to allow for overrun of the matrix. Secondly variables may be added but must be later programmed in the sketch. I am not addressing that here.
Each generates ‘Red’ text below the grids (in both Worksheets) compatible with a sketch designed to accept it.
“Clear” obviously voids both grids.
These will all be described later.
When you are working with the Excel utility, I recommend that you use the File/SaveAs... after you have generated your code so that you don’t have to recreate your design at some other point, and especially if the design is reasonably complex. Also, your original LED_Utility.xlsm has been set to read-only to protect it from being overwritten.
The SketchThe code is offered below with a cautionary note to save with a Read-Only property.
Open Arduino IDE and load the ‘LED_Arduino.ino’ sketch.
You will see that:
- Line 3 defines the Arduino pin in use. This set as Pin 8.
- Line 4 defines the LED units on the board. These are 64.
- Line 5 however multiplies that figure by 3 to take account of the RBG count, thus 192.
- Lines 8, 10 and 25 define functions in use.
Between lines 3 and 19 the original text has been altered but you may edit to address a 16x16 matrix. That said, I have provided LED_Ardino16.ino in the software and LED_Utility.xlsm will accommodate it.
Frequently I will advise that you open the ‘LED_Arduino.ino’ and then “Save As” with some name. That will ensure that ‘LED_Arduino.ino’ is unchanged if you haven’t set the appropriate property to ‘Read-Only’. [I found that my newly created file still had the Read-Only property set; release that to ensure future edit and saves].
At the same time a newly created sketch probably needs to have either or both the port and board redefined; an error message will appear but may not be immediately clear.
Project 1Load the LED_Arduino.ino into the Arduino IDE and save it as Red_Square (ino will be added automatically).
Initially I am proposing to build a 3x3 red square and put that code in Line 40 of the sketch. CellsN8, O8, P8, N11, P11, N14, O14 and P14 will hold the value of 255.
When the red text of LED_Utility,
mapLEDXY(2,2,255,0,0);mapLEDXY(2,3,255,0,0);mapLEDXY(2,4,255,0,0);mapLEDXY(3,2,255,0,0);mapLEDXY(3,4,255,0,0);mapLEDXY(4,2,255,0,0);mapLEDXY(4,3,255,0,0);mapLEDXY(4,4,255,0,0);
is copied into Line 40, the text below it will naturally be moved down.
When you upload the sketch to your Arduino your matrix will turn that square on and off.
Before moving on you consider:
- Clearing both grids.
- Change some colours within that square.
- Add a different coloured square around the original.
I suggest that you open the sketch Red_Square.ino and save it as Colour_Sq (‘.ino’ will be added automatically) to prevent overwriting Red_Square.ino.
With Colour_Sq.ino loaded into the IDE, go to the Red_Square in the Utility and modify the mid squares. MakeO8, O10, O14 and O16 ‘255’. N11 and P11 are ‘0’ but N12 and P12 are ‘255’. Press“Show”.
After you have added the new code at, I’d anticipate line 47 in the IDE, you need to follow it with this block of code:
RGB_update(-1, 0, 0, 0);
delay(1000);
clearLEDs();
RGB_update(-1, 0, 0, 0);
delay(1000);
Note that you may change the delay value to suit yourself; 1000 equates to 1 second.
Project3Reload Red_Square.ino and save it as Grow.
Recreate the Red square in the Utility. Around that square add values of your choice to create a border, they can be anywhere from 0 to 255 but lower than 32 may be very dim. This is my creation in ‘LED_Utility.xlsm’:
Now delete the values for that inner red square and press “Show”. Copy the generated code to Line 47 in theIDE and copy/paste the lines 42 to 46 after that. Upload to the Arduino for an alternation of an inner red square and then one surrounded by various colours.
Try expanding to another border if you desire.
Project4You may have become aware that as we add code into “Loop” there is a tendency for it to become lengthy and possibly pose difficulty to edit later.
Here I am building a Spiral.
The image is from Workbook“spir5.xlsm”. It is the culmination of 4 earlier Workbooks.
“spir1.xlsm” was the centre with bright (255) blocks, “spir2.xlsm” used the values of the inner 4x4 square, with“spir3.xlsm” being the 27 square block, etc. At each stage I copied the code to my sketch but not to “loop”.
Instead I created 5 void functions below “loop” and referenced them within “loop”:
Void loop(){
Sp1();
Sp2();
Sp3();
Sp4();
Sp5();
clearLEDs();
delay(1000);
}
My first function, void Sp1(), is:
void Sp1(){
mapLEDXY(3,3,255,0,0);mapLEDXY(3,4,255,0,0);
mapLEDXY(4,3,255,0,0);mapLEDXY(4,4,255,0,0);
RGB_update(-1, 0, 0, 0);
delay(100);
clearLEDs();
RGB_update(-1, 0, 0, 0);
delay(10);
}
Each successive function will be the same except for the two lines of “mapLEDXY…”.
It may seem trivial from this example to suggest opening “spir4.xlsm” to edit the colours of the outer tips to edit a dedicated function rather than editing within the “loop”.
Bordering upon the ridiculous, suppose you wanted to display the letters of the word “MISSISSIPPI” successively one at a time. There are 11 characters so that means 77 lines of code for ‘void loop()’ to handle. If you decide to alter the “S”, then you must make 4 edits. There are only 4 characters used in the word. It therefore makes sense to create a function for each of them and call them appropriately from “loop”.
Project5This project takes account of another function of the LED_Utility, “Var Map”. Here variables will be introduced and therefore some basic programming knowledge will be required.
The “For Loop” syntax will be employed as well as the “If” condition.
The “for” will be used to increase or decrease an RGB value such as:
for (int r=0; r<= 256; r++) {} or
for (int r=255; r>=0; r--) {}
“If” will modify proceedings as necessary.
Let us begin simply, and I do mean simply.
Create a 2x2 red square in the middle of the LED_utility and “Show”, and here is the code:
mapLEDXY(3,3,255,0,0);mapLEDXY(3,4,255,0,0);
mapLEDXY(4,3,255,0,0);mapLEDXY(4,4,255,0,0);
Now change all of the 255 values to ‘r’. Press “Show” …. Oooow! It doesn’t like that. That’s OK, it’s a protection that I have added. Press “Var Map” and check the generated code:
mapLEDXY(3,3,r,0,0);mapLEDXY(3,4,r,0,0);
mapLEDXY(4,3,r,0,0);mapLEDXY(4,4,r,0,0);
the 255’s have been replaced with ‘r’.
In the IDE open the archived LED_Arduino.ino and save it as “changes”.
At line 40 enter:
for (int r=0; r<256;r++){
}
/// followed by:
for (int r=255;r>=0;r--){
}
Note that there is blank line after each ‘for’ statement.
At line 41 paste your Excel code:
mapLEDXY(3,3,r,0,0);mapLEDXY(3,4,r,0,0);
mapLEDXY(4,3,r,0,0);mapLEDXY(4,4,r,0,0);followthat with:
RGB_update(-1, 0, 0, 0);
delay(50);
Now copy/paste that same 4-line block of code into that second “for”block.
After that “for” block, below the “}” add ‘delay(200);’. I found that necessary for my eyes to know that the second block had closed!
Upon upload the red block increases to full brightness and then decreases, turns off and then repeats.
Project6Let us now make use of the “If” condition.
Recreate that previous red square in the LED_utility but surround it with blocks of a ‘skyblue’ using 255’s for both the G and B values. Use the“Show”.
Leave the Red 255’s alone but change all of the G 255’s to a ‘g’ and the B 255’s to a ‘b’,
and then press “Var Map”.
Reload “LED_Arduino.ino” into the IDE and Save As “FadeBorder”.
Now we are going to have some issues. We have two variables, 'g' and 'b', and each must be given a value. They also have to be declared in the program. I intend to declare the ‘g’ in a ‘for’ statement, but I need to declare the ‘b’ earlier in the sketch. In the sketch at line 5 is the declaration BYTE RGB[192]. Below that enter ‘int b=0;’.
As a point of explanation one cannot use two “for” loops as will be necessary later. Here every ‘b’ value must be the same as the ‘g’ value generated by the “for” loop.
My “loop” is structured as below but without my Map code:
void loop() {
delay(50);
for (int g=0; g<256;g++){
b=g;
[Add Map Code here]
RGB_update(-1, 0, 0, 0);
delay(50);
}
for (int g=255;g>=0;g--){
b=g;
[Add Map Code here]
RGB_update(-1, 0, 0, 0);
delay(50);
}
}
Note that the B value is linked to the G value with the statement ‘b=g;’. The R value remains static at 255 while the border fades up and down in brightness.
Project7It is now time to make use of the “if” statement.
Create and ‘Show’ the following using 255’s where variables appear in the right grid. Notice that a minuscule ‘L’ appears in the cells which are adjacent to Red cells. That will allow the program to take control of those cells when appropriate.
This time the LEDs will fade up as green and red until the value 64 is reached and then those mid-border cells will change to yellow with the board continuing to increase in brightness. Then the process will be reversed.
Again I will offer the base structure of my ‘loop’. I called this sketch ‘FadeColourChange.ino’.
void loop() {
delay(50);
for (int r=0; r<256;r++){
g=r;
if(g>64){
g=65;
l=r;
}
[AddMap Code here]
RGB_update(-1, 0, 0, 0);
delay(50);
}
for (int r=255;r>=0;r--){
if(r<65){
g=r;
l=0;
}
[Add MapCode here]
RGB_update(-1, 0, 0, 0);
delay(50);
}
}
Project8For this last project I will not change the colours but introduce movement; I have an arrow which moves across the board but will reappear from the left.
Here I only want to generate code using “Show”.
Since I want the arrow to move from its present position to each next position I need to change the ‘x’ value.
This is code generated at G29:G33:
mapLEDXY(0,3,0,255,255);
mapLEDXY(1,1,255,128,128);mapLEDXY(1,3,0,255,255);mapLEDXY(1,5,255,128,128);
mapLEDXY(2,2,255,128,128);mapLEDXY(2,3,0,255,255);mapLEDXY(2,4,255,128,128);
mapLEDXY(3,3,255,128,128);
Since ‘1’ is my least value for X coords I am referring to that as ‘x’ and decrementing all other values by 1.
mapLEDXY(x+0,3,0,255,255);
mapLEDXY(x+1,255,128,128);mapLEDXY(x+1,3,0,255,255);mapLEDXY(x+1,5,255,128,128);
mapLEDXY(x+2,2,255,128,128);mapLEDXY(x+2,3,0,255,255);mapLEDXY(x+2,4,255,128,128);
mapLEDXY(x+3,3,255,128,128);
My ‘for (int x…loop’ does well, except that the arrowhead overflows to the lower row for a few passes of the loop!
Solution! If a value overruns ‘8’ I need its modulus value. That forced me to create the “Wrap Map” button. The code for one LED now appears like:
mapLEDXY((x +1) % 8, (y +1) %8, 255, 128, 128);
To address an XY layout I feel it is best to nest two ‘for’ loops even if one will not be used (yes, I found an awkward alternative).
for(int x=0;x<8;x++){
for(int y=0;y<8;y++){
[mapcode]
}
}
If I make ‘y<1’ in the second loop the ‘y’ is disregarded.Conversely, changing ‘y’ to 8 and ‘x’ to 0 has a different effect.
As a last thought, “Wrap Map” will accept RGB variables. See above where I have referenced. One with basic programming should be able to deal with that. I have added an INO sketch, ArrowVar.ino, where the arrowhead front changes in brightness as a minor demo.
16x16 Matrix usage.Everything noted above is applicable for the 16x16 WS2812 matrix. The ‘LED_Arduino16.ino’ sketch however must be used.
The sketches that are provided are designed for the 8x8 Matrix except for one, the ‘Spiral16.ino’. It delivers a larger display than does the ‘Spiral.ino’.
This spiral, 16x16 matrix, had 2 sheets of printer paper as a light diffuser. The display was paused for about 10 secs to capture a reasonable image.
To develop your code open LED_Utility.xlsm and select the “Sixteen” tab at the bottom of the page.
If, as with me, your display is too large and you need to scroll, then use a zoom out option. Even then some scrolling will be necessary to copy your code.
Extensions?Is it possible to address Matrices of other sizes?
I am wondering why my ‘LED_Arduino.ino’ and ‘LED_Arduino16.ino’ are so different in their opening lines. I have certain lines commented out in my first; both sketches work as I desire.
I am not about to write a Worksheet for an ‘8x32’ even though I have just acquired a board. I will direct you to “The Sketch” above. There are parameters that need to be addressed. Be particular about lines 15 and 18 as well.
NB: I am also considering smaller options than a UNO type board.
Comments