Well, I'm delighted to be able to report that things are bouncing along merrily in Max's World (where the colors are brighter, the butterflies are bigger, the birds sing sweeter, and the beer is plentiful and cold).
In the case of my Bodacious Acoustic Diagnostic Astoundingly Superior Spectromatic (BADASS) Display, for example, I've now got some jolly decent effects up and running. Anyone who wanders into our bay ends up standing in front of the little beauty drooling with desire. You wouldn’t believe how many people have asked: “Will you make one for me?” Sadly, I have too many other projects that are clamoring for my attention, plus I only ever make one of anything because I'm easily distra… (Ooh, Shiny!)
In a moment, I'm going to give you a text file containing the code I have thus far, because I'm hoping to persuade you to suggest and/or create some additional effects for me to run on the display. But first, cast your orbs over This Video, which showcases my latest and greatest effects.
Ignore the man behind the curtain (or lying on the floor, in this case). That's just my chum Ivan who is pressing the buttons to switch between effects for me (I can’t wait to get my sticky little hands on some Simblee Modules so I can control the BADASS Display wirelessly using my iPad).
As you'll see, we commence with a little self-test sequence, which involves all of the LEDs “breathing” a few times, then lighting columns of LEDs from left-to-right and rows of LEDs from bottom-to-top. (There are some additional “rainbow” effects in the code, but the calls to these have been commented out to speed the initialization sequence).
There are a number of other effects I've thought of, but not yet implemented. For example, we could have white “raindrops” randomly falling down the various columns and “splashing” when they reach the bottom. Alternatively, we could have “rockets” randomly shooting up from the bottom and “exploding” at random heights into cascades of randomly colored “sparkles.” Another good one might be a “snake” formed from a short chain of pixels that randomly wanders around the display. Do you want to code any of these effects and/or can you think of any others we should try?
Next, we move on to the spectrum analyzer portion of the show, but before we go any further, it might be useful for me to describe how we visualize the display.
Our array comprises 16 rows and 16 columns. We can think of the columns as being on the x axis and the rows as being on the y axis. Each column is formed from a strip of NeoPixels. These are referenced as strip through strip in the code.
As you may recall from an earlier column — Using WS2812-based NeoPixels in embedded systems — the way NeoPixels work is that we first use setPixelColor commands to set the values of the pixels in the Arduino's memory. Once we've set all the values the way we want them, we use a show command to upload these values into the pixels themselves.
For example, let's assume that all of the pixels are initially off. If we wished to light up a single pixel at location x=3, y=6, then — assuming we have two integer variables called x and y that we've already loaded with the appropriate values — we could do this as follows:
In this case, we're assuming that R , G , and B (for the red, green, and blue sub-pixel elements) are byte or integer values in the range 0 to 255.
Now let's assume that we wish to light up the entire x=3 column. We could achieve this as follows:
for (int y=0; y < 16; y++)
Alternatively, if we wished to light up the entire y=6 row, we could achieve this as follows:
for (int x=0; x < 16; x++)
for (int x=0; x < 16; x++)
Since we often need to perform the second for() loop, I've created a simple showAll() function, which would allow us to re-write this as follows:
for (int x=0; x < 16; x++)
One last point before we proceed is that our main program loops around and around, first reading the audio spectrum data and then displaying it. We use the readMSGEQ7s() function to access the audio spectrum data. This stores the data in a global array of integers called bands through bands . Bands 0-through-7 and 8-through-15 are used to store the base-through-treble data from the left- and right-hand channels, respectively.
Each of these values comes in through an analog input pin and is in the range 0-to-1023. Also observe that, since the MSGEQ7 chips only actually give us seven frequency bands, we interpolate an additional band for each channel to give us eight bands per channel.
OK, now back to the video. The first effect just involves all-white columns; the second effect is much the same, except that the top-most pixel on each column is red; and the third effect swaps this around so the body of the columns is red and the top-most pixel on each column is white as shown below:
Actually, the middle image above gives me pause for thought. It looks as though there are multiple red LEDs in some of the columns. This is the way it appears in real life also, but I'd assumed it was an optical illusion. On the other hand, I can’t see how this can happen in my code. Speaking of which, all of these effects are achieved using the dispVertSolid() function as shown below:
We pass six parameters into this function — Rm , Gm , and Bm are the RGB values for the main body of the column, while Rt , Gt , and Bt are the RGB values for the top-most pixel in each column.
The first thing we do is to filter out any noise when nothing is playing. I'm currently using a cutoff value of 80. Next we rescale the remaining value from cutoff-to-1023 to map onto the number of pixels we have in each column (1-to-16). Originally I performed this task in the readMSGEQ7s() function, but I ended up moving it out into the display functions because sometimes we wish to map onto a different number of pixels. Finally, we set the required pixel colors in the Arduino's memory, then call the showAll() function to update the display.
We now move onto some more colorful effects. We start with columns 0-to-7 being associated with the left-hand channel and columns 8-to-15 being associated with the right-hand channel. Both channels transition from base/red on the left to treble/yellow on the right as illustrated below:
Next, we implement a small variation on this theme by swapping the ordering of the right hand channel such that is now transitions from base/red on the right to treble/yellow on the left . This leaves us with base/red from both channels on the outside edges of the display working through to treble/yellow from both channels in the middle of the display as illustrated below:
For our next effect, we interleave the channels, starting with the base band from the left channel in column 0 and the base band from the right channel in column 1, and working our way up to the treble band from the left channel in column 14 and the treble band from the right channel in column 15. We also use 16 different hues to range from base/red on the left to treble/yellow on the right as illustrated below:
In this case, all of the above effects are achieved using the dispVertBasic() function as shown below:
The reason for the “Basic” portion of this function's name is that I intend to create a more advanced implementation in which the top-most pixel in a column holds its position for a fraction of a second and then starts to fall until it's overwhelmed by a new surge in that column.
In order to make much sense out of the above function, you need to be aware of two multi-dimensional arrays called xref and colors as illustrated below:
The xref array is used to map the frequency bands onto the columns. Row 0 of this array corresponds to our original scheme, with the bands from the left channel being displayed on the left-most 8 columns and the bands from the right channel being displayed on the right-most 8 columns, both going from base/left to treble/right. Row 1 of the array corresponds to the right hand channel being flipped so that its base band (8) is displayed in column 15, while its treble band (15) is displayed in column 8. And row 2 of the array corresponds to having the bands from the channels interleaved.
Meanwhile, the colors array is used to map colors onto the frequency bands. From this point on, I'll leave understanding the way this all works as “an exercise for the reader” (which would be you, LOL).
OK, so now it's your turn. Here's a link to a text file containing the current state of play with regard to my code. Can you think of any interesting effects you'd like me to implement. Better still, do you want to create the code to generate some interesting effects and send it to me at ? You don’t need to send the entire program — just any definitions and global variables you declare — the call(s) to your function(s), and the function(s) themselves, and I'll take it from there.
I'll add anything anyone sends into the main program and then post another video showing all of these little rascals in action. I can’t wait to see what you come up with!