打印
[STM32U5]

【NUCLEO-U5A5ZJ-Q测评】驱动DFRobot 24灯珠炫彩灯环带你穿越时空之门

[复制链接]
837|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 HonestQiao 于 2023-12-12 13:29 编辑

#申请原创#

本篇文章,分享了在 NUCLEO-U5A5ZJ-Q 开发板上,使用WS2812B 炫彩灯环的经验,展示的效果,包括按照顺序亮灭灯环上的灯珠,已经根据简谱点亮对应数量的灯珠。

一、硬件了解
炫彩灯带是一种非常常见的LED灯带,一般有5050灯带、WS28系列灯带(WS2801、WS2812、WS2813、WS2815和WS2818),在日常要使用灯光效果的场合,应用非常的多。


其中WS2812是最常见的一种,可以编程控制每一颗灯珠的亮灭,以及不同的颜色。

我手头有WS2812的灯板(1、2、4、8*8)、灯带(60、92)、灯环(24),其中24灯珠的灯环最常用:

我给这个灯环配了一个时空之门的底座,科幻感十足,当灯环上的灯珠亮起来的时候,仿佛开启了时空之门。


这是一款DFRobot出品的灯环,其参数如下:
工作电压:3.3~5V
最大工作电流:<100mA
接口类型:PH2.0-3P
灯珠型号:WS2812
灯珠数量:24
颜色:1600万色

要控制WS2812,除了供电以外,只需要1根数据信号线,即可控制所有的灯珠,非常的方便。
关于WS2812的具体控制原理,可以参考我的文章:【GD32F427开发板试用】点亮WS2812B炫彩灯环,里面详细讲述了灯环的电路原理和灯珠和颜色控制的原理。

在咱们 NUCLEO-U5A5ZJ-Q 开发板 开发板上,可与使用SPI的方式进行控制,将其信号线,连接到开发板的Arduino兼容接口的MOSI即可:


具体连接如下:


如果有多个这样的灯环,那灯环直接,还可以串联起来使用:



不过,需要注意的是,如果控制的灯珠较多,那么务必需要使用外部供电。
通常情况下,1颗灯珠,1种颜色,需要20mA电流,白色需要60mA电流,控制100颗,就需要最大6A电流。

二、驱动适配
在Zephyr中,提供了ws2812B的处理,但是没有提供咱们NUCLEO-U5A5ZJ-Q 开发板对应的处理定义,需要自己处理适配一下。
文件1:samples/drivers/led_ws2812/boards/nucleo_u5a5zj_q.conf
CONFIG_WS2812_STRIP_SPI=y
CONFIG_SPI=y
这个文件定义了使用SPI,以及使用SPI控制WS2812。

文件2:samples/drivers/led_ws2812/boards/nucleo_u5a5zj_q.overlay:
/*
* Copyright (c) 2022, STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/dt-bindings/led/led.h>

&arduino_spi {
        led_strip: ws2812[url=home.php?mod=space&uid=2514928]@0[/url] {
                compatible = "worldsemi,ws2812-spi";

                /* SPI */
                reg = <0>; /* ignored, but necessary for SPI bindings */
                spi-max-frequency = <DT_FREQ_M(4)>;
                frame-format = <32768>; /* SPI_FRAME_FORMAT_TI */

                /* WS2812 */
                chain-length = <24>; /* arbitrary; change at will */
                spi-one-frame = <0x70>;
                spi-zero-frame = <0x40>;
                color-mapping = <LED_COLOR_ID_GREEN
                                 LED_COLOR_ID_RED
                                 LED_COLOR_ID_BLUE>;
        };
};

/ {
        aliases {
                led-strip = &led_strip;
        };
};

这个文件定义了基于arduio_spi的led-strip设备,使用4MHz通信速率,灯珠数量24颗,颜色对应关系为GRB。
对,就是GRB,WS2812就是这样定义颜色的:


三、基础测试
在Zephyr中,提供了ws2812的基础实例:samples/drivers/led_ws2812
其中main.c内容如下:
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <errno.h>
#include <string.h>

#define LOG_LEVEL 4
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main);

#include <zephyr/kernel.h>
#include <zephyr/drivers/led_strip.h>
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/sys/util.h>

#define STRIP_NODE                DT_ALIAS(led_strip)
#define STRIP_NUM_PIXELS        DT_PROP(DT_ALIAS(led_strip), chain_length)

#define DELAY_TIME K_MSEC(CONFIG_SAMPLE_LED_UPDATE_DELAY)

#define RGB(_r, _g, _b) { .r = (_r), .g = (_g), .b = (_b) }

static const struct led_rgb colors[] = {
        RGB(0x0f, 0x00, 0x00), /* red */
        RGB(0x00, 0x0f, 0x00), /* green */
        RGB(0x00, 0x00, 0x0f), /* blue */
};

struct led_rgb pixels[STRIP_NUM_PIXELS];

static const struct device *const strip = DEVICE_DT_GET(STRIP_NODE);

int main(void)
{
        size_t cursor = 0, color = 0;
        int rc;

        if (device_is_ready(strip)) {
                LOG_INF("Found LED strip device %s", strip->name);
        } else {
                LOG_ERR("LED strip device %s is not ready", strip->name);
                return 0;
        }

        LOG_INF("Displaying pattern on strip");
        while (1) {
                memset(&pixels, 0x00, sizeof(pixels));
                memcpy(&pixels[cursor], &colors[color], sizeof(struct led_rgb));
                rc = led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS);

                if (rc) {
                        LOG_ERR("couldn't update strip: %d", rc);
                }

                cursor++;
                if (cursor >= STRIP_NUM_PIXELS) {
                        cursor = 0;
                        color++;
                        if (color == ARRAY_SIZE(colors)) {
                                color = 0;
                        }
                }

                k_sleep(DELAY_TIME);
        }

        return 0;
}


这个代码的逻辑如下:
1. 定义了一个 colors ,用于灯珠显示的颜色定义
2. 定义了一个 pixels ,用于存放每颗灯珠的颜色数据
3. while循环过程中,cursor用于指向下一颗要点亮的灯珠,如果打倒了最大值,则从第一颗重新点亮
4. while循环过程中,没循环一遍灯珠,就指向下一个定义的颜色,如果颜色循环完了,则从头开始。
5. 使用 led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS) 来更新灯珠的颜色,也就是通过SPI发送数据到WS2812。

编译下载后,具体的运行效果如下:


四、根据简谱控制灯珠点亮
在上面的基础测试中,是依次点亮灯珠。
下面,就根据《小星星》的简谱,来实现根据简谱点亮对应的灯珠。
首先,在代码中,添加一个颜色定义:
static const struct led_rgb num_colors[] = {
        RGB(0x00, 0x00, 0x00), /* black */
        RGB(0x0f, 0x00, 0x00), /* red */
        RGB(0x00, 0x0f, 0x00), /* green */
        RGB(0x00, 0x00, 0x0f), /* blue */

        RGB(0x0f, 0x0f, 0x00), /* ?? */
        RGB(0x00, 0x0f, 0x0f), /* ?? */
        RGB(0x0f, 0x00, 0x0f), /* ?? */
        RGB(0x0f, 0x0f, 0x0f), /* white */
};
实际的颜色,大家可以对照RGB颜色表来取值。

再添加一个曲谱的定义:

uint8_t nums[] = {1,1,5,5,6,6,5,0,4,4,3,3,2,2,1,0,5,5,4,4,3,3,2,0,5,5,4,4,3,3,2,0,1,1,5,5,6,6,5,0,4,4,3,3,2,2,1};


然后,把while循环替换为:
        while(1) {
                memset(&pixels, 0x00, sizeof(pixels));
                for(int i=0;i<nums[cursor];i++) {
                        memcpy(&pixels[i], &num_colors[nums[cursor]], sizeof(struct led_rgb));
                }
                rc = led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS);

                if (rc) {
                        LOG_ERR("couldn't update strip: %d", rc);
                }

                cursor++;
                if (cursor >= sizeof(nums)/sizeof(nums[0])) {
                        cursor = 0;
                }

                k_sleep(K_MSEC(500));
        }


上述代码,就是通过循环简谱的每一位,来确定要点亮的灯珠数量,控制pixels 中灯珠的颜色。具体的颜色,再根据要控制的数量,从 num_colors 中取值。

编译下载后,运行效果如下:


五、总结
WS2812的控制,是一件非常有意思的事情,了解其原理也是一件非常值得学习的事情。
在 NUCLEO-U5A5ZJ-Q 开发板 上使用WS2812,也是一件非常简单方便的事情。
如果感兴趣的话,还可以和音乐播放等结合起来,达到更好的效果。

使用特权

评论回复
沙发
OliviaSH| | 2023-12-13 10:50 | 只看该作者
颜色对应谱子,这想法不错

使用特权

评论回复
板凳
SophiaOP| | 2023-12-13 11:30 | 只看该作者
WS2812最多可以串联多少啊?

使用特权

评论回复
地板
jobszheng| | 2023-12-14 06:35 | 只看该作者

居然使用了Zephyr操作系统!
看楼主的展示代码,在Zephyr下操作灯珠几行代码就生成了如此酪炫的效果!

使用特权

评论回复
5
HonestQiao|  楼主 | 2023-12-15 17:16 | 只看该作者
Zephyr系统相当的好用啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

99

帖子

2

粉丝