From ecf8180661982172cd4a86f0c7e899f38f8b3676 Mon Sep 17 00:00:00 2001 From: IrvingGao <1729854488@qq.com> Date: Wed, 26 Jun 2024 23:40:26 +0800 Subject: [PATCH] [tool] spi ws2812 --- tools/orangepi_spi_ws2812.py | 61 ++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/tools/orangepi_spi_ws2812.py b/tools/orangepi_spi_ws2812.py index c05aa90..6a44af9 100644 --- a/tools/orangepi_spi_ws2812.py +++ b/tools/orangepi_spi_ws2812.py @@ -1,16 +1,31 @@ -import time -import spidev import wiringpi +import argparse +import time + +parser = argparse.ArgumentParser(description='') +parser.add_argument("--channel", type=int, default=1, help='specify the spi channel') +parser.add_argument("--port", type=int, default=0, help='specify the spi port') +parser.add_argument("--speed", type=int, default=6400000, help='specify the spi speed') +parser.add_argument("--mode", type=int, default=0, help='specify the spi mode') +args = parser.parse_args() # 0码 t0H 220ns~380ns -# (python 中GPIO口无法翻转这么快,python 可能执行一行代码需要800ns) +#(python 中GPIO口无法翻转这么快,python 可能执行一行代码需要800ns) # ws2812 波特率如果设置为800kHZ, 1/0.8M=1.25us (0码或者1码所需要的时间) +# 方案1. # 使用SPI产生ws2812时序,产生1码和0码,则可以使用传输一个byte 来代表一个0码或者1码,如下: # 1111 1000 0xF8 #1码 高电平时间长,低电平时间短 # 1100 0000 0xC0 #0码 高电平时间短,低电平时间长 # 则得出SPI 波特率应该设置为800K*8 +# 方案2. 见led_bak.py +# 使用SPI产生ws2812时序,产生1码和0码,则可以使用传输一个半个byte 来代表一个0码或者1码,如下: +# 1100 0x0c #1码 高电平时间长,低电平时间短 +# 1000 0x08 #0码 高电平时间短,低电平时间长 +# 则得出SPI 波特率应该设置为800K*4 + + sig_1 = 0xf8 sig_0 = 0xc0 @@ -20,23 +35,22 @@ def flatten_arrays(arrays): class WS2812: - def __init__(self, led_num=1): + def __init__(self, led_num=10): self.led_num = led_num self.ws2812_data = [[sig_0 for _ in range(24)] for _ in range(led_num)] - spi = spidev.SpiDev() + wiringpi.wiringPiSPISetupMode(args.channel, args.port, args.speed, args.mode) # 设置一下下拉,否则第一盏灯的时序可能不正确 wiringpi.wiringPiSetup() wiringpi.pullUpDnControl(11, 1) - spi.open(0, 0) - spi.max_speed_hz = 6400000 - spi.mode = 0 - self.spi = spi + print("ws2812_data len", len(self.ws2812_data)) + print("spi mode: 0x%x" % args.mode) + print("max speed: %d Hz (%d KHz)\n" % (args.speed, args.speed / 1000), end='') def ws2812_send_data(self): default_tx = self.ws2812_data - self.spi.xfer2(bytes(flatten_arrays(default_tx))) + wiringpi.wiringPiSPIDataRW(args.channel, bytes(flatten_arrays(default_tx))) def ws2812_light_led(self, red, green, blue, pix_led): default_tx = self.ws2812_data @@ -82,17 +96,38 @@ class WS2812: self.ws2812_light_led(0, 0, 0, i) self.ws2812_send_data() - + + def ws2812_gradient_run(self, start_red, start_green, start_blue, end_red, end_green, end_blue, steps, delay): + for step in range(steps): + # 计算当前步的颜色 + curr_red = start_red + (end_red - start_red) * step // steps + curr_green = start_green + (end_green - start_green) * step // steps + curr_blue = start_blue + (end_blue - start_blue) * step // steps + + # 清除当前颜色并应用新的渐变色 + self.ws2812_shutoff_all() + for i in range(self.led_num): + self.ws2812_light_led(curr_red, curr_green, curr_blue, (i + step) % self.led_num) # 循环显示渐变色 + + self.ws2812_send_data() + time.sleep(delay) if __name__ == '__main__': ws2812 = WS2812(8) while True: + # 示例:从蓝色渐变到红色,再从红色渐变回蓝色,每种颜色渐变10步,每步间隔0.1秒 + ws2812.ws2812_gradient_run(0, 0, 0xff, 0xff, 0, 0, 10, 0.02) + time.sleep(1) # 等待1秒后开始反向渐变 + ws2812.ws2812_gradient_run(0xff, 0, 0, 0, 0, 0xff, 10, 0.02) + time.sleep(1) # 再次等待1秒,形成完整的循环 ws2812.ws2812_light_all_led(0, 0, 0xff) time.sleep(0.5) ws2812.ws2812_light_all_led(0xff, 0, 0) time.sleep(0.5) ws2812.ws2812_light_all_led(0, 0xff, 0) time.sleep(0.5) - # ws2812.ws2812_water_lamp(0xff, 0, 0, 0.2) - # time.sleep(0.5) \ No newline at end of file + ws2812.ws2812_shutoff_all() + time.sleep(0.5) + ws2812.ws2812_water_lamp(0xff, 0, 0, 0.2) + time.sleep(0.5) \ No newline at end of file