回到顶部 回到顶部
best-icon

用行空板制作的WS2812-24 RGB LED Ring炫彩灯环控制器 中等

头像 HonestQiao 2022.11.16 102 0

目录:

 

1. 硬件材料

2. 原理图

3. 实物连线

4. 逻辑设计

5. 代码编写

6. 使用步骤

7. 实际效果

8. 总结

步骤1 硬件材料

材料清单

材料清单

  • WS2812-24 RGB LED Ring X1 链接

材料清单

  • DC-DC自动升降压电源模块2.5~15V转3.3V600mA X1 链接

步骤2 原理图

行空板_WS2812B电路原理图.png

步骤3 实物连线

image.png

.

上图中,小黑块IoT Power,用于给WS2812-24 RGB LED Ring供电。同时,其电源输出的-,需要与行空板的GND连接共地。另外,此处应使用3.3V供电。

步骤4 逻辑设计

行空板_WS2812B电路原理图.drawio.png

步骤5 代码编写

根据设计,实际使用到的库如下:

1. pinpong库中的Board、Pin、NeoPixel

2. unihiker库中的GUI

 

处理的核心逻辑,为根据屏幕点击区域色块的颜色,去设置灯环点灯的颜色。

代码
# -*- coding: UTF-8 -*-
import sys
import time
from pinpong.board import Board,Pin,NeoPixel #导入neopixel类
from unihiker import GUI

# 颜色定义
colors_def = (
    ("海蓝色",  "Navy",     "#000080",  (0,0,128)),
    ("蓝色",  "Blue",     "#0000FF",  (0,0,255)),
    # ("湖绿色",  "Aqua",     "#7FDBFF",  (127,219,255)),
    ("蓝绿色",  "Teal",     "#008080",  (0,128,128)),
    # ("青色",    "Cyan",     "#00FFFF",  (0,255,255)),    
    ("橄榄绿",  "Olive",    "#808000",  (128,128,0)),
    ("草绿色",  "Green",    "#008000",  (0,128,0)),
    ("石灰绿",  "Lime",     "#00FF00",  (0,255,0)),
    ("黄色",    "Yellow",   "#FFFF00",  (255,255,0)),
    # ("橙红色",  "Orange",   "#FF851B",  (255, 133, 27)),
    ("红色",    "Red",      "#FF0000",  (255,0,0)),
    ("洋红色",  "Magenta",  "#FF00FF",  (255,0,255)),    
    ("褐红色",  "Maroon",   "#800000",  (128,0,0)),
    # ("紫红色",  "fuchsia",  "#F012BE",  (240,18,190)),
    ("紫色",    "Purple",   "#800080",  (128,0,128)),
    ("淡黑色",  "black",    "#111111",  (17,17,17)),
    ("纯黑色",  "Black",    "#000000",  (0,0,0)),
    ("灰色",    "Gray",     "#808080",  (128,128,128)),
    # ("灰色2",   "Gray2",    "#AAAAAA",  (170,170,170)),
    ("银色",    "Silver",   "#C0C0C0",  (192,192,192)),
    # ("银色2",   "Silver2",  "#DDDDDD",  (221,221,221)),
    ("白色",    "White",    "#FFFFFF",  (255,255,255)),
)

# 按键修改颜色回调
def mod_color(val):
    global color_curr
    color_curr = list(color_curr)
    for i in range(0,3):
        color_curr[i] = color_curr[i] + val
        if color_curr[i] < 0:
            color_curr[i] = 0
        elif color_curr[i] > 255:
            color_curr[i] = 255
    print(color_curr)

def get_index(i, j):
    return i * 4 + j

# 初始化屏幕
gui = GUI()
gui.draw_text(x=40, y=0, text="WS2812B控制器")
gui.draw_text(x=10, y=280, text="当前颜色值:")
color_obj = gui.draw_text(x=120, y=280, text="0,0,0")

# 变量定义
colors = []
color_curr = (0, 0, 0)
x0 = 25
y0 = 50
w0 = 40
h0 = 40

# 颜色区块点击回调对象
class clickHandle:
    def __init__(self, i, j):
        self.i=i
        self.j=j

    def process(self):
        global colors_def, obj_prev, color_curr
        index = get_index(self.i, self.j)
        print(index, colors_def[index])

        obj = round_rects[index]
        x = x0 + self.i * (w0+10)
        y = y0 + self.j * (h0+15)
        obj.config(x=x-4, y=y-4, w=w0+8, h=h0+8, width=3)
        color_curr = colors_def[index][3]

        if obj_prev['i']>=0:
            index_prev = get_index(obj_prev['i'], obj_prev['j'])
            if not index_prev == index:
                obj = round_rects[index_prev]
                x = x0 + obj_prev['i'] * (w0+10)
                y = y0 + obj_prev['j'] * (h0+15)
                obj.config(x=x-2, y=y-2, w=w0+4, h=h0+4, width=1)

        obj_prev['i'] = self.i
        obj_prev['j'] = self.j


obj_prev = dict()
obj_prev['i'] = -1
obj_prev['j'] = -1

round_rects = dict()

# 区块显示
for i in range(0,4):
    for j in range(0,4):
        x = x0 + i * (w0+10)
        y = y0 + j * (h0+15)
        index = get_index(i, j)
        if index >= len(colors_def):
            continue

        print("%d,%d -> %d" % (i, j, index))
        color = colors_def[index][3]
        ch = clickHandle(i, j)
        gui.fill_round_rect(x=x, y=y, w=w0, h=h0, r=2, color=color, onclick=ch.process)
        color_rr = (0,0,0) if color == (255,255,255) else color
        round_rects[index] = gui.draw_round_rect(x=x-2, y=y-2, w=w0+4, h=h0+4, r=2, width=1, color=color_rr)
        gui.draw_text(x=x-2, y=y-12, text="%s:" % colors_def[index][0], font_size=6)

# 初始化通讯
Board("UNIHIKER").begin()

# 初始化灯环对象
NEOPIXEL_PIN = Pin(Pin.D24)
PIXELS_NUM = 24 #灯数

# 清空显示
np = NeoPixel(NEOPIXEL_PIN,PIXELS_NUM)
np.clear()
time.sleep(1)
np.range_color(0,PIXELS_NUM-1, 0x000000)
time.sleep(1)

# 注册按键回调
gui.on_key_click('a', lambda: mod_color(5))
gui.on_key_click('b', lambda: mod_color(-5))


color_hex_prev = 0
run_index = 0
led_status = False
time_prev = time.time()

循环
while True:
    # 计算和显示当前颜色
    color_obj.config(text="%d,%d,%d" % (color_curr[0], color_curr[1], color_curr[2]))
    color_hex = (color_curr[0]<<16) + (color_curr[1]<<8) + color_curr[2]

    # 颜色变化后,重新开始效果
    if color_hex != color_hex_prev:
        color_hex_prev = color_hex
        run_index = 0
        time_prev = time.time()
    
    # 每5s换一次效果
    if time.time() - time_prev > 5:
        time_prev = time.time()
        run_index = run_index + 1
        if run_index>2:
            run_index = 0

    # 效果1:全部点亮,闪烁
    if run_index == 0:
        led_status = not led_status
        if led_status:
            np.range_color(0,PIXELS_NUM-1, color_hex)
        else:
            np.range_color(0,PIXELS_NUM-1, 0)
        time.sleep(1)

    # 效果2:依次点亮1颗
    if run_index == 1:
        for i in range(0, PIXELS_NUM):
            np.range_color(0,PIXELS_NUM-1, 0x00)
            np[i] = tuple(color_curr)
            time.sleep(0.1)

步骤6 使用步骤

1. 将代码保存到如下路径:

image.png

 

2. 操作屏幕菜单,使用 切换运行程序

image.png

 

3. 进入到测试程序目录,并选中运行:

image.png

 

4. 等待程序启动完成,显示操控面板:

image.png

5. 在屏上点击对应的区块,改变颜色,选中的色块会标示出来:

image.png

 

6. 按A键减少颜色值+5,按B键颜色值-5,范围为0~255:

image.png

步骤7 实际效果

image.png

 

image.png

步骤8 总结

在设计开发本作品的过程中,行空板提供的GUI调用,以及pinpong硬件控制库方便的硬件控制能力,为开发提供了很大的方便,使得开发过程中,能够专心于具体逻辑的实现,而不用操心硬件底层的处理。

 

另外,在开发的过程中,遇到过时序问题,导致灯环颜色显示错乱的问题。这个灯环,我在其他开发板上也使用过,根据说明,使用外接5V电源供电,在行空板上,也自然认为应该要用5V供电。结果,就是这个5V,导致出现问题。在李亮大佬的指点下,改为3.3V一切正常。这可能与行空板是外挂了硬件处理模块的原因,待李亮大佬进一步排查问题原因。

评论

user-avatar