Example code for 2d matrix

Hello, i’m trying to learn how to program my pixelblaze. I want to use it to make a porch light with a 16x16 neopixel matrix. For example i would like to make a spectrum analyser using the mic on the sensor board. Where a vertical row of leds shows the amplitude of each of the 16 frequency ranges. Or a snake that goes in random direction on the matrix.

I have been looking at downloaded patterns but I can’t figure them out. I’m used to code in c, so I’m kind of lost. I know there is a mapper but i have no idea how i can use it to accomplish the above.

Can anyone give me some example code with comment to accomplish something like described above to nudge me in the right direction.

Thanks

Hi @Alias,
The mapper tab has a dropdown for examples, pick the Matrix example and click Load Example.

On line 2, you’ll see the width = 8 setting, change that to 16.

Do you know if your matrix is wired zigzag, or straight across? Many matrix panels have alternating directions for how the data is wired. The example includes code to do that on line 7. If your panel is straight across, comment out that line.

Once the settings are dialed in, click Save just below the editor. Now you have a pixel map installed!

To use it, the pattern needs to implement a render2D function. There are some newer patterns on the pattern site that have 2d and 3d functions, check these out:

cube fire 3D
plasma 3D
sinpulse 3D
fast pulse 3d
honeycomb 3D
sound - spectromatrix optim

There are also some originals that do the pixel mapping in the pattern (change the width setting in the pattern code and save):
matrix 2D honeycomb
matrix 2D pulse

To make a spectrum analyzer, you’ll want to translate the x coordinate to some frequency. You can do this pretty easily since the pixel map scales the coordinates to fit, so x will be from 0.0 to 1.0. To get a frequency, you can multiply x by the number of elements in the frequencyData array from the sensor board, which is 32:

fx = frequencyData[x*32]

Now with a specific frequency in hand, you’ll want to draw LEDs up to some threshold based on y. Since the frequencyData value will usually be very small, you’ll want to scale that and play around with the value until it is responsive to your audio levels. Something like this:

v = fx > y * .05 ? 1 : 0

This will set v to 1 when it is above the threshold, and 0 otherwise.

That should get you a very basic spectrum analyzer. Beyond that, it might be interesting to slightly filter the frequencies to smooth out the response, or implement peak indicators. You might also want to borrow the automatic gain control using the PIController stuff from the other sound patterns so that it can adapt to different sound levels.

Let us know how it goes!

Hi Ben,

I understand what the code you gave does, but when i try to put it all together i get 1 row of the matrix light up with the highest pixels flickering. The rest of the matrix remaines off

export var frequencyData
export var energyAverage
export var maxFrequencyMagnitude
export var maxFrequency
export function render2D(index, x, y) {
h = 1
s = 1
fx = frequencyData[x*32]
v = fx > y * 0.05 ? 1 : 0
hsv(h, s, v)
}

function (pixelCount) {
width = 16
var map = []
for (i = 0; i < pixelCount; i++) {
y = Math.floor(i / width)
x = i % width
x = y % 2 == 1 ? width - 1 - x : x //zigzag
map.push([x, y])
}
return map
}

Hi Ben,

can you explain to me why this peace of code doesn’t work?

export function beforeRender(delta) {
t1 = time(.01)
}
export function render2D(index, x, y) {
if(x<5){
hsv(0.3, 1, 1)
}
else if(x>+5 && x<10){
hsv(0.6, 1, 1)
}
else if(x<=10 && x<15){
hsv(0.9, 1, 1)
}
}

I’m trying to display 3 different color bands on the matrix, but the “if(x<5)” writes all the leds not just the ones with a x position lower then 5. Am i misunderstanding how this function works? Is this function not run for every pixel in the matrix? (so once for x=0,y=0 / once for x=1,y=0 / … / x=15, y=14).
Sorry not used to programming in java.

Hi @Alias,
The .05 coefficient was way too high, and would only work with very loud volumes. The code works for me for a fairly quiet audio when I adjust the coefficient to a low value e.g.:

export var frequencyData

export function render2D(index, x, y) {
  h = 1
  s = 1
  fx = frequencyData[x*32]
  v = fx > y * 0.003 ? 1 : 0
  hsv(h, s, v)
}

This is where automatic gain control could help. The reason you have a line with a flicker on the second line is that y starts out zero, so fx is almost always > 0 on the first line, except for loud frequencies.

To answer your second question, the pixel map is scaled to world units. More information can also be found in the Mapper tab documentation, just below the editor. All coordinates are scaled to a value between 0.0 and 1.0, so x will always be less than 5. The idea is that patterns can be written to scale to any map, and wouldn’t have to be changed to work on different sized matrices (or any other layout).

If you want to go back to pixels, you can multiply by the width - 1, and round to the closest integer value like so:

xpx = floor(x*15 + .5) //xpx will be between 0 and 15 inclusive
1 Like