不理解 Python 中等离子对 LED 条矩阵二维阵列影响的 Sin 方程

Don't understand Sin equation of plasma effect to 2d array for LED strip matrix in Python

我成功地从 Github 获得了下面的代码,在 raspberry pi 和一个 8 x 16 LED 矩阵上使用引脚 18 上的 PWM 工作。因为它使用 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

修改后的函数只显示红色

色调方程已更改。关于等离子图形的website公式。

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 ] )

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

请指教。谢谢。

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

我在 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 ) 色调变量仅影响三元组的第一部分。我传递的值使色调变红。要使 sin 模式像示例一样,必须将色调或像素值传递给 hsv 的第三部分,即 "value" 部分。

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 ] )

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