使用Arduino和FastLED库对数字RGB LED灯条进行编程

使用Arduino简化编程并不是什么新鲜事。几乎所有内容都有Arduino库,并且即使您是一个很笨的初学者,也可以使用其中的一个或多个库来制作很棒的小项目。对LED进行编程也不例外,FastLED库当然简化了这一过程。

在本文中,我们将大致讨论数字LED,并提供一些有关如何使用FastLED库的示例。

什么是数字RGB LED?

对此的一个答案是,您可以使用少量电线(与LED数量无关)单独控制LED。这些LED通常以LED灯带或LED矩阵的形式出现,但也可以是单独的LED,它们之间通过电线连续连接在一起。在文章中,我们将重点介绍LED灯条。

LED条只是一排LED,通常在一侧像胶带一样带有粘合剂。沿着带状结构,可以有三根或四根电导体,具体取决于类型。这些导体中的三个是电源电压,接地和数据信号。在某些类型的LED灯条上,您还有一个时钟信号作为第四根导线。这些带有专用时钟信号的同步LED灯带被认为比只有三根导线的异步LED灯带更坚固。

LED灯带的类型很多。WS2811 / WS2812及其相关版本是一些常见的版本。这些是异步LED,有些地方更名为NeoPixel。其他常见的是WS2801和APA102,它们都是同步的。后者是某些地方更名为SuperLED的地方。

这些类型的LED灯带的一个非常方便的特性是,您可以将其切割成任意长度。只需订购一个大卷的LED灯条,并切断小工具所需的电量即可。

所有LED均可单独控制,并且条带可以切割成所需的长度

RGB与HSV

RGB是Red Green Blue的首字母缩写。使用这三个通道,您可以重新创建任何颜色。这些通道通常由8位(值0-255)表示,但不一定。

HSV是表示相同颜色的另一种方法,但另一方面,它是Hue Saturation Value的首字母缩写。这可能是首选方法,因为它有时会使颜色更清晰地参数化:Hue决定颜色是红色,蓝色等,Saturation控制与纯白光相比存在多少颜色,而Value控制光强度。如果Value通道为零,则无论其他两个通道是什么,LED都将关闭。HSV在每个通道的分辨率方面类似于RGB。

LED功耗和USB电流限制

当将Arduino连接到USB端口以供电时,绝对不要超过500mA。

您应该始终检查LED灯带,看看它可能消耗多少功率,通常将其指定为每米瓦特数或整个灯带长度仅瓦特数。此数字表示全强度的白色。您还应该知道带材每米有多少个LED。这里常见的数字是每米30、60和144个LED。

让我们用两个不同的例子来计算每个LED消耗多少mA:

例子1

APA102

  • 5伏
  • 60 LED /米
  • 18瓦/米
    我们将功率(18)除以LED密度(60),得到0.3 W / LED。我们将其除以电压(5),得到60 mA / LED。

例子2
WS2812b

  • 5伏
  • 30个LED /米
  • 45 W /条
  • 条带长度5 m
    我们将功率(45)除以长度5得到9 W / m。然后,将这个数字除以LED密度(30),得到0.3 W / LED。这与示例1中的相同,并且由于电压也相同,因此得到60 mA / LED。

这些数字告诉我们什么?

要保持低于500mA(这在使用USB作为电源时非常重要),您不应该在这些LED灯带上打开超过500/60≈8个全白强度的LED。

如果仅使用RGB通道之一,则LED只会消耗大约先前计算值(20 mA)的三分之一。在这种情况下,我们可以将500/20 = 25个LED设置为全红,绿或蓝强度,而不会超过最大USB电流限制。在这种情况下,更容易设置RGB值而不是HSV值。

伽玛校正

您应该记住,人类不会线性感知LED的强度。我们发现1-10之间的差异比246-255之间的差异大得多。本文解释了这种现象。

FastLED库

这是一个Arduino库,可为您完成所有低级操作,因此您只需设置需要将哪些LED更新为哪种颜色值即可。

芯片组和平台支持

该库的主要优点在于,它可以与一长串LED类型(也称为芯片组)一起使用:

  • LPD8806
  • WS2801
  • SM16716
  • P9813 –又名。全面控制照明
  • APA102 –又名。超级LED
  • WS2811 / WS2812 / WS2812b –又名。NeoPixel
  • TM1809 / TM1804
  • TM1803
  • UCS1903 / UCS1903B / UCS1904 / UCS2903
  • GW6205
  • LPD1886
    除了Arduino外,该库还可以在同一类别的其他多个平台上使用。

例子

在以下示例中,我们使用带有22个LED的WS2812b LED灯条。

例子1

#include "FastLED.h"
 
// How many leds in your strip?
#define NUM_LEDS 22
 
#define DATA_PIN 5
//#define CLOCK_PIN 13
 
CRGB leds[NUM_LEDS];
 
void setup() { 
    // Uncomment/edit one of the following lines for your leds arrangement.
    // FastLED.addLeds<TM1803, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<TM1804, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<TM1809, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
    FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    // FastLED.addLeds<APA104, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<UCS1903, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<UCS1903B, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<GW6205, DATA_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<GW6205_400, DATA_PIN, RGB>(leds, NUM_LEDS);
 
    // FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<SM16716, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<LPD8806, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<P9813, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<APA102, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<DOTSTAR, RGB>(leds, NUM_LEDS);
 
    // FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<SM16716, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<LPD8806, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<P9813, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
    // FastLED.addLeds<DOTSTAR, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}
 
void loop() {
    for(int i=0; i<NUM_LEDS; i++){
        leds[i] = CHSV(160, 255, 128);
        FastLED.show();
        delay(50);
        leds[i] = CHSV(0,0,0);
        FastLED.show();
    }
}

这些行中的大多数都被注释掉,只是为了显示您需要包括的内容,具体取决于您的LED类型。如您所见,由于我们正在使用WS2812b,因此我们未对其进行注释。我们还注释掉了CLOCK_PIN定义,因为我们不在此LED灯条上使用时钟引脚。

此代码将LED设置为强度为50%的蓝色,并在关闭之前将其保持打开状态50毫秒,然后继续执行测试条上的下一个LED,直到所有LED都轮到为止,然后重新开始。

注意该FastLED.show()功能。这有点像刷新功能,它将所需的状态发送到每个LED。自上次调用该功能以来未更改其状态的LED将保持其最后状态。您不必为要更改的每个LED都调用此功能,只需在要刷新所有LED时调用它即可。

例子2

#include "FastLED.h"
 
#define NUM_LEDS 22
#define DATA_PIN 5
#define TWO_HUNDRED_PI 628
 
CRGB leds[NUM_LEDS];
 
int element = 0;
int last_element = 0;
 
void setup() { 
    FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
}
 
void loop() {
    for(int i=0; i<TWO_HUNDRED_PI; i++){
        element = round((NUM_LEDS-1)/2*(sin(i/100.0)+1));
        leds[element].g = 64;
        FastLED.show();
         
        delay(1);
         
        if(element < last_element){
            leds[element].g = 0;
            FastLED.show();
        }
         
        last_element = element;
    }
}

此代码以25%的绿色强度逐一点亮所有LED,然后以正弦波模式逐一关闭所有LED。

例子3

在最后一个示例中,我们将进行一些LED衰减。

#include "FastLED.h"
 
#define NUM_LEDS 22
#define DATA_PIN 5
#define TWO_HUNDRED_PI 628
#define TWO_THIRDS_PI 2.094
 
CRGB leds[NUM_LEDS];
 
int val1 = 0;
int val2 = 0;
int val3 = 0;
 
void setup() { 
    FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
}
 
void loop() {
    for(int i=0; i<TWO_HUNDRED_PI; i++){
        val1 = round(255/2.0*(sin(i/100.0)+1));
        val2 = round(255/2.0*(sin(i/100.0+TWO_THIRDS_PI)+1));
        val3 = round(255/2.0*(sin(i/100.0-TWO_THIRDS_PI)+1));
     
        leds[7] = CHSV(0, 255, val1);
        leds[8] = CHSV(96, 255, val2);
        leds[9] = CHSV(160, 255, val3);
     
        FastLED.show();
     
        delay(1);
    }
}

在这里,我们以正弦波模式上下衰减具有三种不同颜色的三个独立的LED。每个LED之间的淡入周期相移60度。

总结

LED是嵌入式系统中最酷的东西,使用Arduino和FastLED库使LED的工作变得非常容易。该库具有比我们在这些示例中使用的功能更多的功能。

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论