#!/usr/bin/env python3 """ WS2812B LED特效展示脚本 基于精确时序的多种LED效果 """ import time import random import math import RPi.GPIO as GPIO from rpi_ws281x import Color, PixelStrip class WS2812B_WS281X: def __init__(self, led_count=10, brightness=100): self.led_count = led_count self.brightness = brightness # WS2812B配置 LED_PIN = 10 # GPIO引脚(SPI模式) LED_FREQ_HZ = 800000 # LED信号频率 LED_DMA = 10 # DMA通道 LED_INVERT = False # 是否反转信号 LED_CHANNEL = 0 # PWM通道 # 创建PixelStrip对象 self.strip = PixelStrip(led_count, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, brightness, LED_CHANNEL) self.strip.begin() # 初始化后清空 time.sleep(0.1) for i in range(led_count): self.strip.setPixelColor(i, Color(0, 0, 0)) self.strip.show() time.sleep(0.1) def show(self, colors): """显示颜色""" for i, (r, g, b) in enumerate(colors): self.strip.setPixelColor(i, Color(r, g, b)) self.strip.show() def cleanup(self): """清理资源""" # 清空所有LED for i in range(self.led_count): self.strip.setPixelColor(i, Color(0, 0, 0)) self.strip.show() # ===== 新增LED特效函数 ===== def breathing_effect(ws, color=(255, 0, 0), cycles=5, min_brightness=0.1, max_brightness=0.8): """呼吸灯效果""" print("呼吸灯效果开始...") steps = 50 for cycle in range(cycles): print(f" 呼吸循环 {cycle + 1}/{cycles}") # 呼吸(渐亮) for i in range(steps): brightness = min_brightness + (max_brightness - min_brightness) * (i / steps) r = int(color[0] * brightness) g = int(color[1] * brightness) b = int(color[2] * brightness) colors = [(r, g, b)] * ws.led_count ws.show(colors) time.sleep(0.02) # 呼吸(渐暗) for i in range(steps): brightness = max_brightness - (max_brightness - min_brightness) * (i / steps) r = int(color[0] * brightness) g = int(color[1] * brightness) b = int(color[2] * brightness) colors = [(r, g, b)] * ws.led_count ws.show(colors) time.sleep(0.02) ws.show([(0, 0, 0)] * ws.led_count) print("呼吸灯效果完成!") def color_wipe(ws, color=(255, 0, 0), delay=0.1, cycles=3): """颜色擦除效果""" print("颜色擦除效果开始...") for cycle in range(cycles): print(f" 擦除循环 {cycle + 1}/{cycles}") # 正向擦除 for i in range(ws.led_count): colors = [(0, 0, 0)] * ws.led_count for j in range(i + 1): colors[j] = color ws.show(colors) time.sleep(delay) # 反向擦除 for i in range(ws.led_count - 1, -1, -1): colors = [(0, 0, 0)] * ws.led_count for j in range(i + 1): colors[j] = color ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("颜色擦除效果完成!") def theater_chase(ws, color1=(255, 0, 0), color2=(0, 0, 0), delay=0.1, cycles=10): """剧院追逐效果""" print("剧院追逐效果开始...") for cycle in range(cycles): print(f" 剧院循环 {cycle + 1}/{cycles}") for i in range(3): colors = [] for j in range(ws.led_count): if (j + i) % 3 == 0: colors.append(color1) else: colors.append(color2) ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("剧院追逐效果完成!") def rainbow_cycle(ws, delay=0.02, cycles=3): """彩虹循环效果""" print("彩虹循环效果开始...") for cycle in range(cycles): print(f" 彩虹循环 {cycle + 1}/{cycles}") for i in range(256): colors = [] for j in range(ws.led_count): pixel_index = (i * 256 // ws.led_count + j) % 256 colors.append(wheel(pixel_index)) ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("彩虹循环效果完成!") def wheel(pos): """生成彩虹颜色""" pos = 255 - pos if pos < 85: return (255 - pos * 3, 0, pos * 3) elif pos < 170: pos -= 85 return (0, pos * 3, 255 - pos * 3) else: pos -= 170 return (pos * 3, 255 - pos * 3, 0) def fire_effect(ws, delay=0.1, cycles=10): """火焰效果""" print("火焰效果开始...") for cycle in range(cycles): print(f" 火焰循环 {cycle + 1}/{cycles}") colors = [] for i in range(ws.led_count): # 随机生成火焰颜色(红、橙、黄) rand = random.random() if rand < 0.3: colors.append((255, 0, 0)) # 红 elif rand < 0.6: colors.append((255, 100, 0)) # 橙 else: colors.append((255, 255, 0)) # 黄 ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("火焰效果完成!") def sparkle_effect(ws, base_color=(50, 50, 50), sparkle_color=(255, 255, 255), delay=0.1, cycles=20): """闪烁效果""" print("闪烁效果开始...") for cycle in range(cycles): colors = [base_color] * ws.led_count # 随机选择几个LED进行闪烁 sparkle_count = random.randint(1, 3) for _ in range(sparkle_count): pos = random.randint(0, ws.led_count - 1) colors[pos] = sparkle_color ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("闪烁效果完成!") def pulse_effect(ws, color=(255, 0, 0), cycles=5): """脉冲效果""" print("脉冲效果开始...") for cycle in range(cycles): print(f" 脉冲循环 {cycle + 1}/{cycles}") # 从中心向外扩散 for i in range(ws.led_count // 2 + 1): colors = [(0, 0, 0)] * ws.led_count # 设置左右对称的LED if i < ws.led_count: colors[i] = color colors[ws.led_count - 1 - i] = color ws.show(colors) time.sleep(0.05) # 从边缘向中心收缩 for i in range(ws.led_count // 2, -1, -1): colors = [(0, 0, 0)] * ws.led_count if i < ws.led_count: colors[i] = color colors[ws.led_count - 1 - i] = color ws.show(colors) time.sleep(0.05) ws.show([(0, 0, 0)] * ws.led_count) print("脉冲效果完成!") def color_mixing(ws, color1=(255, 0, 0), color2=(0, 0, 255), delay=0.1, cycles=10): """颜色混合效果""" print("颜色混合效果开始...") for cycle in range(cycles): print(f" 混合循环 {cycle + 1}/{cycles}") # 计算混合比例 ratio = (cycle % 20) / 20.0 if ratio > 0.5: ratio = 1.0 - ratio # 混合颜色 r = int(color1[0] * (1 - ratio) + color2[0] * ratio) g = int(color1[1] * (1 - ratio) + color2[1] * ratio) b = int(color1[2] * (1 - ratio) + color2[2] * ratio) colors = [(r, g, b)] * ws.led_count ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("颜色混合效果完成!") def running_light(ws, colors=None, delay=0.15, cycles=2): """跑马灯效果(保留原有函数)""" if colors is None: colors = [(150, 0, 0), (0, 150, 0), (0, 0, 150)] print("跑马灯效果开始...") for cycle in range(cycles): print(f" 跑马灯循环 {cycle + 1}/{cycles}") ws.show([(0, 0, 0)] * ws.led_count) time.sleep(0.2) for i in range(ws.led_count): led_colors = [(0, 0, 0)] * ws.led_count for j, color in enumerate(colors): pos = (i + j) % ws.led_count led_colors[pos] = color ws.show(led_colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("跑马灯效果完成!") def simple_single_chase(ws, color=(255, 0, 0), delay=0.15, cycles=2): """简化版单点追逐效果(保留原有函数)""" print("简化版单点追逐效果开始...") color = (min(color[0], 150), min(color[1], 150), min(color[2], 150)) for cycle in range(cycles): print(f" 循环 {cycle + 1}/{cycles}") ws.show([(0, 0, 0)] * ws.led_count) time.sleep(0.3) for i in range(ws.led_count): colors = [(0, 0, 0)] * ws.led_count colors[i] = color ws.show(colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) time.sleep(0.2) ws.show([(0, 0, 0)] * ws.led_count) time.sleep(0.2) print("简化版单点追逐效果完成!") def rainbow_effect(ws, delay=0.2, cycles=3): """彩虹效果(保留原有函数)""" print("彩虹效果开始...") rainbow_colors = [ (150, 0, 0), # 红 (150, 75, 0), # 橙 (150, 150, 0), # 黄 (0, 150, 0), # 绿 (0, 0, 150), # 蓝 (50, 0, 100), # 靛 (100, 0, 150) # 紫 ] for cycle in range(cycles): colors = [] for i in range(ws.led_count): color_index = i % len(rainbow_colors) colors.append(rainbow_colors[color_index]) for shift in range(len(colors)): shifted_colors = [] for i in range(ws.led_count): color_index = (i + shift) % len(rainbow_colors) shifted_colors.append(rainbow_colors[color_index]) ws.show(shifted_colors) time.sleep(delay) ws.show([(0, 0, 0)] * ws.led_count) print("彩虹效果完成!") def rainbow_simple(ws, wait_ms=20, iterations=1): """简单彩虹效果(基于原始文件)""" print("简单彩虹效果开始...") for j in range(256 * iterations): colors = [] for i in range(ws.led_count): colors.append(wheel((i + j) & 255)) ws.show(colors) time.sleep(wait_ms / 1000.0) ws.show([(0, 0, 0)] * ws.led_count) print("简单彩虹效果完成!") def reset_strip(ws): """重置LED灯带""" print("重置LED灯带...") for i in range(ws.led_count): ws.strip.setPixelColor(i, Color(0, 0, 0)) ws.strip.show() time.sleep(0.1) def test_single_color_with_reset(ws, color, color_name): """测试单个颜色并立即重置""" print(f"测试{color_name}...") try: # 设置颜色 for i in range(ws.led_count): ws.strip.setPixelColor(i, color) ws.strip.show() time.sleep(0.001) # 短暂显示 time.sleep(0.5) # 立即清空 for i in range(ws.led_count): ws.strip.setPixelColor(i, Color(0, 0, 0)) ws.strip.show() time.sleep(0.1) print(f"{color_name}测试完成") return True except Exception as e: print(f"{color_name}测试失败: {e}") return False def safe_color_test(ws): """安全颜色测试""" print("安全颜色测试...") success = True success &= test_single_color_with_reset(ws, Color(255, 0, 0), "红色") time.sleep(0.5) success &= test_single_color_with_reset(ws, Color(0, 255, 0), "绿色") time.sleep(0.5) success &= test_single_color_with_reset(ws, Color(0, 0, 255), "蓝色") time.sleep(0.5) success &= test_single_color_with_reset(ws, Color(255, 255, 255), "白色") if success: print("所有颜色测试完成") else: print("颜色测试过程中出现问题") reset_strip(ws) # ===== 主函数:按顺序播放所有特效 ===== def show_all_effects(): """按顺序播放所有LED特效""" ws = WS2812B_WS281X(led_count=10, brightness=100) try: print("🎆 LED特效展示开始!") print("=" * 50) # 特效列表 effects = [ ("安全颜色测试", lambda: safe_color_test(ws)), ("呼吸灯效果", lambda: breathing_effect(ws, color=(255, 0, 0), cycles=3)), ("颜色擦除效果", lambda: color_wipe(ws, color=(0, 255, 0), cycles=2)), ("剧院追逐效果", lambda: theater_chase(ws, color1=(255, 255, 0), color2=(0, 0, 0), cycles=8)), ("彩虹循环效果", lambda: rainbow_cycle(ws, delay=0.05, cycles=2)), ("简单彩虹效果", lambda: rainbow_simple(ws, wait_ms=20, iterations=1)), ("火焰效果", lambda: fire_effect(ws, delay=0.15, cycles=8)), ("闪烁效果", lambda: sparkle_effect(ws, base_color=(20, 20, 20), sparkle_color=(255, 255, 255), cycles=15)), ("脉冲效果", lambda: pulse_effect(ws, color=(255, 0, 255), cycles=3)), ("颜色混合效果", lambda: color_mixing(ws, color1=(255, 0, 0), color2=(0, 255, 0), cycles=10)), ("跑马灯效果", lambda: running_light(ws, colors=[(255, 0, 0), (0, 255, 0), (0, 0, 255)], delay=0.2, cycles=2)), ("单点追逐效果", lambda: simple_single_chase(ws, color=(0, 255, 255), delay=0.15, cycles=2)), ("彩虹效果", lambda: rainbow_effect(ws, delay=0.2, cycles=2)), ] # 按顺序播放每个特效 for i, (name, effect_func) in enumerate(effects): print(f"\n🎭 特效 {i+1}/{len(effects)}: {name}") print("-" * 30) effect_func() # 特效之间短暂停顿 time.sleep(1) print("\n🎉 所有LED特效播放完成!") print("=" * 50) except KeyboardInterrupt: print("\n⏹️ 用户中断,停止播放...") ws.show([(0, 0, 0)] * ws.led_count) except Exception as e: print(f"\n❌ 播放出错: {e}") ws.show([(0, 0, 0)] * ws.led_count) finally: ws.cleanup() print("🧹 清理完成") if __name__ == "__main__": show_all_effects()