模块略览——LED 灯带 与 FastLED 库

JiaoKan 发布于 2024-05-15 75 次阅读


💬 前言

从广告灯箱上面的彩灯到增添风情的氛围灯带,究其本质不过是一串 LED 灯珠,常见的如 WS2812B 等 RGB 灯珠,常常被发烧友拿来捣鼓。本文也会以 WS2812B 为例来做个简单的介绍。

WS2812B 的通讯协议实现起来其实非常简单,有兴趣的可以自信查阅数据手册,但是真正运用的时候,若都写在项目代码里,还是略复杂了些。况且,市面上不同的 LED 灯带有很多种,想要让一份代码支持多种灯带,还是得请 FastLED 这个库出场。

💡 FastLED

这是一个有这十年多历史的库了,支持很多常见的 LED 灯带。他还提供了很多在调用灯带时非常方便的方法,诸如对 HSV 的支持,快速设置灯带为渐变彩虹色,方便的色彩校正,色温调整,伽马矫正等等,详细的内容可以参见 Wiki 以及自带的 Example。

接下来简单描述一下这个库的工作原理。

首先需要指定一些基本的信息,比如灯珠数量,数据引脚,芯片型号等等。

然后我们需要定义一个数组,充当“帧缓冲区”,用来存放要显示的东西,数据类型为CRGB,这是由 FastLED 提供的一个数据类型,提供了不少有用的关于色彩的功能。

然后把前面的基本信息和缓冲区交给 FastLED,通过调用LEDS.addLeds方法来初始化灯带。

loop里,我们只需要修改数组,然后调用FastLED.show()即可刷新灯带。如果你觉得这么做不优雅,或者你希望程序逮着空就刷新,很推荐使用FastLED.delay()代替delay(),在程序等待的间隙执行刷新。

对于 3-Wire 的灯珠,比如 WS2812B,由于通信协议的限制,必须保证在传输信号的时候连续(间隙不得超过50 μs,否则会被判定为传输完毕,从而新来的数据不会给后继 LED),所以在时钟频率较低的处理器上 FastLED 会暂时禁用中断,从而导致潜在的串口数据丢失,舵机失灵等问题。即使在时钟频率较高的处理器上,如若中断耗时过长,也会导致显示出问题,比如“怎么就前 xxx 个灯珠亮了?”之类的问题。

为了解决这个问题,一个办法是去使用那些 4-Wire 乃至更多的灯带(IIC,SPI 等协议的),或者在你确保不会产生问题的情况下,手动保持中断启用/禁用。当然最好的办法,还是提前进行思考,可以参考官方文档的这部分

🧑‍💻 程序设计

这里简单写几个小功能,以供参考。

#include <FastLED.h>
#define NUM_LEDS 64
#define DATA_PIN 16
#define LED_TYPE WS2812
#define COLOR_ORDER GRB

CRGB leds[NUM_LEDS];

void setup()
{
    LEDS.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);

    FastLED.setBrightness(64);
}

void loop()
{
    for (int i = 0; i < 64; ++i)
    {
        leds[i % NUM_LEDS] = CRGB::Green;
        FastLED.delay(200);
        leds[i % NUM_LEDS].setRGB(0, 0, 0);
    }

    fill_solid(leds, NUM_LEDS, CHSV(325 / 360 * 255, 100 / 360 * 255, 100 / 360 * 255)); // Everything is 0-255 here
    FastLED.delay(1000);

    for (int i = 0; i < 64; ++i)
    {
        fadeToBlackBy(leds, NUM_LEDS, 1);
        FastLED.delay(100);
    }

    fill_rainbow(leds, NUM_LEDS, 0, 256 / 64);
    // 3rd argument for beginning hue, 4th for delta hue between previous and next

    FastLED.delay(1000);
}
此作者没有提供个人介绍。
最后更新于 2024-05-25