TakwayBoard/tools/orangepi_spi_ws2812.py

133 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
# 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
def flatten_arrays(arrays):
return [element for sublist in arrays for element in sublist]
class WS2812:
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)]
wiringpi.wiringPiSPISetupMode(args.channel, args.port, args.speed, args.mode)
# 设置一下下拉,否则第一盏灯的时序可能不正确
wiringpi.wiringPiSetup()
wiringpi.pullUpDnControl(11, 1)
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
wiringpi.wiringPiSPIDataRW(args.channel, bytes(flatten_arrays(default_tx)))
def ws2812_light_led(self, red, green, blue, pix_led):
default_tx = self.ws2812_data
color = green << 16 | red << 8 | blue
for i in range(24):
if color >> (24 - i - 1) & 1:
default_tx[pix_led][i] = sig_1
else:
default_tx[pix_led][i] = sig_0
def ws2812_light_one_led(self, red, green, blue, pix_led):
self.ws2812_light_led(red, green, blue, pix_led)
self.ws2812_send_data()
def ws2812_light_all_led(self, red, green, blue):
for i in range(self.led_num):
self.ws2812_light_led(red, green, blue, i)
self.ws2812_send_data()
def ws2812_rainbow(self):
colors = [[0xff, 0, 0], [0, 0xff, 0], [0, 0, 0xff]]
for i in range(self.led_num):
cur_color = colors[i % 3]
self.ws2812_light_led(cur_color[0], cur_color[1], cur_color[2], i)
self.ws2812_send_data()
def ws2812_water_lamp(self, red, green, blue, interval_time):
self.ws2812_shutoff_all()
for i in range(self.led_num):
self.ws2812_light_one_led(red, green, blue, i)
time.sleep(interval_time)
self.ws2812_shutoff_all()
def ws2812_shutoff_led(self, n):
self.ws2812_light_led(0, 0, 0, n)
self.ws2812_send_data()
def ws2812_shutoff_all(self):
for i in range(self.led_num):
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_shutoff_all()
time.sleep(0.5)
ws2812.ws2812_water_lamp(0xff, 0, 0, 0.2)
time.sleep(0.5)