首页 > 解决方案 > 不明白 Python 中 LED 条形矩阵的等离子效应对二维阵列的 Sin 方程

问题描述

我从Github成功获得了下面的代码,在 18 针上使用 PWM 处理树莓派和 8 x 16 LED 矩阵。由于它使用 sin 和 cos 函数来创建图形,我想尝试制作自己的效果。我从这个页面借用了效果,但是当我把它放到函数中时,我只得到红色的 LED。

Plasma 示例代码

import time
import math
import colorsys
from neopixel import *

# LED strip configuration:
LED_COUNT = 128      # Number of LED pixels.
LED_PIN = 18      # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10       # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 128  # Set to 0 for darkest and 255 for brightest
# True to invert the signal (when using NPN transistor level shift)
LED_INVERT = False

# Draws an animated horizontal bar test pattern for alignment
def bar(w,h,t):
    out = [ Color( 0, 0, 0 ) for x in range( w * h ) ]
    y = int(t * 4) % h
    for x in range(0, w):
        out[ x + y * w ] = Color( 10, 10, 10 )
    return out

# Draws an animated colorful plasma effect
def plasma (w, h, t):
    out = [ Color( 0, 0, 0 ) for x in range( w * h ) ]
    for x in range( w ):
        for y in range( h ):
            hue = 4.0 + math.sin( t + x ) + math.sin( t + y / 4.5 ) \
                + math.sin( x + y + t ) + math.sin( math.sqrt( ( x + t ) ** 2.0 + ( y + 1.5 * t ) ** 2.0 ) / 4.0 )
            hsv = colorsys.hsv_to_rgb( hue / 8.0, 1, 1 )
            out[ x + y * w ] = Color( *[ int( round( c * 10.0 ) ) for c in hsv ] )
    return out

# Main program logic follows:
if __name__ == '__main__':
    # Create NeoPixel object with appropriate configuration.
    strip = Adafruit_NeoPixel(
        LED_COUNT,
        LED_PIN,
        LED_FREQ_HZ,
        LED_DMA,
        LED_INVERT,
        LED_BRIGHTNESS
    )
    # Intialize the library (must be called once before other functions).
    strip.begin()

    t = 0.0                                                                       # time
    dt = 0.1                                                                      # speed of time

    for i in range( 0, strip.numPixels(), 1):                                     # iterate over all LEDs
        strip.setPixelColor( i, Color( 0, 0, 0 ) )                                # set LED to black (off)

    while True:
        t = t + dt                                                                # increment time
        pic = plasma( 8, 16, t )                                                  # render plasma of size 8x8 at time t
        #pic = bar( 8, 16, t )                                                    # remove comment for bar test pattern
        for i in range( 0, strip.numPixels(), 1 ):                                # iterate over all LEDs
            strip.setPixelColor(                                                  # set pixel to color in picture
                i,
                pic[ i ]
            )
        strip.show()                                                              # update LEDs
        time.sleep(0.01) 

等离子功能

def plasma (w, h, t):
    out = [ Color( 0, 0, 0 ) for x in range( w * h ) ]
    for x in range( w ):
        for y in range( h ):
            hue = 4.0 + math.sin( t + x ) + math.sin( t + y / 4.5 ) \
                + math.sin( x + y + t ) + math.sin( math.sqrt( ( x + t ) ** 2.0 + ( y + 1.5 * t ) ** 2.0 ) / 4.0 )
            hsv = colorsys.hsv_to_rgb( hue / 8.0, 1, 1 )
            out[ x + y * w ] = Color( *[ int( round( c * 10.0 ) ) for c in hsv ] )
    return out

修改后的函数只显示红色

色调方程发生了变化。本网站关于等离子图形的公式。

def plasma (w, h, t):
    out = [ Color( 0, 0, 0 ) for x in range( w * h ) ]
    for x in range( w ):
        for y in range( h ):
            hue = int(math.sin((x+y)/4.0)) # Throws error without int
            hsv = colorsys.hsv_to_rgb( hue / 8.0, 1, 1 )
            out[ x + y * h ] = Color( *[ int( round( c * 10.0 ) ) for c in hsv ] )
    return out

我也不明白这个数组符号是如何工作的。

out[ x + y * h ] = Color( *[ int( round( c * 10.0 ) ) for c in hsv ] )

我知道它正在展平阵列,但不知道如何。

请指教。谢谢你。

标签: pythonarraysmatrixtrigonometryled

解决方案


在朋友的帮助下,我想出了这个功能,现在可以制作自己的图案了。

我在https://lodev.org/cgtutor/plasma.html网站的第二个示例中输入错误。

我还意识到 HSV 颜色空间中的所有值都介于 0 和 1 之间,因此我必须除以 256 才能获得有意义的值。

hue = ((128 +(128*math.sin( y )/8.0)))))256

在示例函数中hsv = colorsys.hsv_to_rgb( hue / 8.0, 1, 1 ),hue 变量仅影响三元组的第一部分。我传递的值使色调变为红色。为了使 sin 模式像示例一样,必须将色调或像素值传递给 hsv 的“值”部分的第三部分。

hsv = colorsys.hsv_to_rgb( 1, 1, hue )这仍然是红色,因为第一个值是 1。如果你改变第一个值,那么你会得到不同的颜色。例如 .5 给出蓝色。

关键是将生成的 sin 值放入 hsv "value" 槽中以生成梯度。

out[ x + y * h ] = Color( *[ int( round( c * 10.0 ) ) for c in hsv ] )

我也理解这部分代码。令人困惑的部分是out[ x + y * h]部分。现在我明白这是分配要传递给 LED 链的阵列中像素值的位置。

我不得不修改这段代码,因为我的 LED 灯串是连线的,所以信号在矩阵中来回交替。

if y % 2 == 0: # if column even
    out[ x + (h * y)] = color ( *[int( round( c * plasmaBright ) ) for c in hsv ] )
else: # if column odd
    out[ (y * h) + (h -1 -x) ] = color ( *[int( round( c * plasmaBright ) ) for c in hsv ] )

此代码检查列是否是偶数并每隔一个翻转一次。


推荐阅读