带Python和Raspberry Pi的FFT LED条形矩阵

带Python和Raspberry Pi的FFT LED条形矩阵,python,arrays,numpy,raspberry-pi,led,Python,Arrays,Numpy,Raspberry Pi,Led,我被Python和LED条卡住了。具有WS2801芯片且可通过SPI寻址的LED条被布置为如下矩阵: ---- ---- ---- ---- 140 | | | | | | | | 15 | | | | | | | | | | | | | | | | | | | | | |

我被Python和LED条卡住了。具有WS2801芯片且可通过SPI寻址的LED条被布置为如下矩阵:

     ----      ----      ----      ----
140 |    |    |    |    |    |    |    | 15
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
155 |    |    |    |    |    |    |    | 0
          ----      ----      ----
每个虚线代表一个LED(一个像素)。一列中有16个像素,共8行

编号从右下角开始。因此,最右边的列以索引0开始,以索引15结束。行之间的四个像素将不会点亮。因此,第二个最右边的列从索引20的顶部向下到索引35的底部。 最左边的列的范围从顶部的140到底部的155

我想做的是想象一首歌在播放时的频谱。较低的频率应显示在左栏中,较高的频率应显示在右栏中

我的代码基于PixelPi()。我省略了FFT部分,因为这部分不是问题所在

# Each pixel consumes 3 bytes
PIXEL_SIZE = 3 

# Lots of colors
BLACK = bytearray(b'\x00\x00\x00')
AQUA = bytearray(b'\x00\xff\xff')
AQUAMARINE = bytearray(b'\x7f\xff\xd4')

def filter_pixel(input_pixel, brightness):
    output_pixel = bytearray(PIXEL_SIZE)

    input_pixel[0] = int(brightness * input_pixel[0])
    input_pixel[1] = int(brightness * input_pixel[1])
    input_pixel[2] = int(brightness * input_pixel[2])

    output_pixel[0] = gamma[input_pixel[0]]
    output_pixel[1] = gamma[input_pixel[1]]
    output_pixel[2] = gamma[input_pixel[2]]
    return output_pixel

# Initialize LED strip matrix
height  = 16
base    = [155, 120, 115, 80, 75, 40, 35, 0]
# Do the indexes of this column go from bottom to top?
up      = [False, True, False, True, False, True, False, True]
color   = [NAVY, RED, MAROON, DARKBLUE, DARKCYAN, PALEGREEN, YELLOWGREEN, YELLOW]

# Output matrix, filled with black pixels
empty_output = bytearray(args.num_leds * PIXEL_SIZE + 3)
for led in range(args.num_leds):
    empty_output[led * PIXEL_SIZE:] = filter_pixel(BLACK, 1)

current_color = bytearray(PIXEL_SIZE)
corrected_color = bytearray(PIXEL_SIZE)

while True: # (Actually while song is playing)

    # Returns an array of length 8 with values between 0 and 4095
    matrix = calculate_levels(matrix, weighting, data, CHUNK_SIZE, sample_rate)

    # Copy the matrix with only black pixels. Copying seems to be faster than resetting all not needed pixels to black
    pixel_output[:] = empty_output


    for col in range(len(base)):
        current_color[:] = color[col][:]
            # Do some gamma correction
        corrected_color[:] = filter_pixel(current_color[:], 1)

            # Each column is 16 pixels high. The maximum value of the FFT to be returned for each column is 4095. 4096 / 256 = 16
        lighted_height = round(matrix[col]/float(1 << 8), 2)

        for row in range(max(16, int(lighted_height) + 1)):
            pixel_index = base[col] + row if up[col] == True else base[col] - row
            pixel_index = pixel_index * PIXEL_SIZE

            if (row < int(lighted_height)):
                # Pixel's brightness in 100%
                pixel_output[pixel_index:] = corrected_color[:]
            elif (row <= int(lighted_height) and row + 1 > int(lighted_height)):
                # Pixel's brightness is between 0 and 1
                pixel_output[pixel_index:] = filter_pixel(current_color[:], lighted_height - int(lighted_height))

            #print "[col:", col, ", row:", row, "] : ", pixel_index, "lighted_height:", lighted_height, "int(lighted_height)", int(lighted_height), "lighted:", lighted

            # As I uncomment these two lines, at least all pixels on the other columns are displayed.
            #spidev.write(pixel_output)
            #spidev.flush()

    spidev.write(pixel_output)
    spidev.flush()
这实际上应该将像素0点亮到最后一个,并在循环执行16次后去掉4个像素。但是,它没有遗漏一个像素,因此在到达最后一个像素之前停止。

找到了它

pixel_output[pixel_index:] = filter_pixel(WHITE, 1)
并不像我预期的那样只复制3个数组元素。它将filter_pixel返回的值从整个缓冲区的pixel_索引复制到最后

设置复制的上限解决了我的问题

pixel_output[pixel_index:(pixel_index + PIXEL_SIZE)] = filter_pixel(WHITE, 1)

您需要后退一步,简化您的测试用例。摆脱对音乐文件的依赖,只需生成具有已知值的测试模式。这样你会发现你的虫子。
pixel_output[pixel_index:(pixel_index + PIXEL_SIZE)] = filter_pixel(WHITE, 1)