本文最后更新于25 天前,如有错误请在评论区中留言。
FasLED库使用
日志
2025-11-12
新增灯效,修改调用逻辑
2025-10-31
记录自用fastled库
前言
前段时间做了一些小项目,有使用到WS2812灯带,ST7789驱动的LCD彩屏,DF家的mini mp3 player,还有servo motor。这里主要记录一下灯带库的使用,以及封装好的原程序,便于后期快速使用。其中有一些重复功能,忽略即可。
使用说明
- 新建
led.cpp,led.h文件,粘贴下面代码即可 - 自行安装FastLED库
- 相关功能见注释
代码文件
非阻塞实现
led.cpp文件
主要包含各种灯效的实现,这里全部使用非阻塞的方式实现
#include <FastLED.h>
#include "led.h"
int LED_State = LED_ON; // 灯效变量,默认工作灯效
int num_leds = NUM_LEDS; // 校时灯效中间变量
bool EffectAllowed = true; // 允许重新执行一些一次性特效
CRGB leds[NUM_LEDS];
/**
@brief 初始化led
*/
void Led_Init() {
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); //初始化led
FastLED.setBrightness(150);
}
/**
@brief led灯控制函数
*/
void Led_Control(int LED_KEYS) {
switch (LED_KEYS) {
case 0: //灯效关闭
{
clearAllLEDs();
break;
}
case 1: // 非阻塞:全彩色流动RGB
{
rainbowFlowEffect();
break;
}
case 2: // 非阻塞:校时充能灯效,只有在使用case0重置num_leds后才能多次使用
{
chargingEffect(0x00FF00);
break;
}
case 3: // 非阻塞:银蓝色流水灯效
{
runningWaterEffect(0x52CFE0);
break;
}
case 4: //固定渐变灯效
{
gradientEffectRGB(0xFF0000, 0x00FF00);
break;
}
case 5: // 非阻塞:白色流水灯效
{
runningWaterEffect(0xFFFFFF);
break;
}
case 6: // 非阻塞:绿色呼吸灯效果
{
breathingLightEffect(0x00FF00);
break;
}
case 7: // 非阻塞:红色呼吸灯效果
{
breathingLightEffect(0xFF0000);
break;
}
case 8: // 非阻塞:红绿交替闪烁
{
alternatingBlinkEffect(0xFF0000, 0x00FF00, 500);
break;
}
case 9: // 非阻塞:白色呼吸灯效果
{
breathingLightEffect(0xFFFFFF);
break;
}
case 10: // 非阻塞:白色流水灯旋转5圈后停止
{
fixedRoundsWaterEffect(5, 0xFFFFFF);
break;
}
case 11: // 非阻塞:白色流水灯旋转5圈后停止
{
fixedRoundsWaterEffect(2, 0xFFFFFF);
break;
}
case 12:
{
turnOnLEDSingle(5, 0xFFFFFF);
break;
}
case 13:
{
turnOnLEDRange(5, 10, 0xFFFFFF);
break;
}
default:
{
clearAllLEDs();
break;
}
}
}
/**
* @brief 非阻塞全彩色流动RGB效果
*/
void rainbowFlowEffect() {
static unsigned long lastUpdate = 0; // 上次更新时间
static uint8_t hue = 0; // 色调值
const unsigned long interval = 30; // 流动速度(毫秒)
// 检查是否到达更新时间
if (millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 填充彩虹色
fill_rainbow(leds, NUM_LEDS, hue, 7);
FastLED.show();
// 更新色调值,循环0-255
hue++;
// 不需要检查边界,uint8_t会自动溢出回0
}
}
/**
* @brief 非阻塞校时充能灯效
* @param color 充能颜色(十六进制)
*/
void chargingEffect(uint32_t color) {
static int currentLED = 0; // 当前要点亮的LED
static unsigned long lastUpdate = 0; // 上次更新时间
static bool isActive = false; // 是否正在执行充能
static bool isShowing = false; // 是否正在显示当前LED
const unsigned long interval = 5; // 充能速度(毫秒)
// 如果不是正在执行充能,则开始新的充能
if (!isActive) {
isActive = true;
currentLED = 0;
isShowing = false;
}
// 检查是否到达更新时间
if (isActive && millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 如果还没到达最后一个LED
if (currentLED < num_leds) {
if (!isShowing) {
// 点亮当前LED
if (currentLED < NUM_LEDS) {
leds[currentLED] = color;
FastLED.show();
}
isShowing = true;
} else {
// 熄灭当前LED并移动到下一个
if (currentLED < NUM_LEDS) {
leds[currentLED] = CRGB::Black;
}
currentLED++;
isShowing = false;
}
}
// 如果已经到达最后一个LED
else {
// 保留最后一个点亮的LED
if (num_leds > 0 && (num_leds - 1) < NUM_LEDS) {
leds[num_leds - 1] = color;
FastLED.show();
}
// 减少LED数量
if (num_leds > 0) {
num_leds--;
}
// 重置状态,准备下一次充能
isActive = false;
}
}
}
/**
* @brief 固定RGB渐变灯效
* @param startColor 起始颜色(十六进制)
* @param endColor 结束颜色(十六进制)
*/
void gradientEffectRGB(uint32_t startColor, uint32_t endColor) {
fill_gradient_RGB(leds, NUM_LEDS, startColor, endColor);
FastLED.show();
}
/**
* @brief 非阻塞双色交替闪烁效果
* @param color1 第一种颜色(十六进制)
* @param color2 第二种颜色(十六进制)
* @param interval 闪烁间隔(毫秒),默认500ms
*/
void alternatingBlinkEffect(uint32_t color1, uint32_t color2, unsigned long interval) {
static bool toggle = false; // 状态切换标志
static unsigned long lastUpdate = 0; // 上次更新时间
// 检查是否到达更新时间
if (millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 切换状态并更新LED
toggle = !toggle;
if (toggle) {
fill_solid(leds, NUM_LEDS, color1); // 第一种颜色
} else {
fill_solid(leds, NUM_LEDS, color2); // 第二种颜色
}
FastLED.show();
}
}
/**
* @brief 非阻塞循环流水灯效果
* @param color 流水灯颜色(十六进制)
*/
void runningWaterEffect(uint32_t color) {
static int currentLED = 0; // 当前点亮的LED
static unsigned long lastUpdate = 0; // 上次更新时间
const unsigned long interval = 20; // 流水速度(毫秒)
// 检查是否到达更新时间
if (millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 熄灭上一个LED(使用取模运算实现循环)
leds[(currentLED - 1 + NUM_LEDS) % NUM_LEDS] = CRGB::Black;
// 点亮当前LED
leds[currentLED] = color;
FastLED.show();
// 移动到下一个LED,循环到开头
currentLED = (currentLED + 1) % NUM_LEDS;
}
}
/**
* @brief 非阻塞呼吸灯效果,全部灯珠点亮
* @param color 呼吸灯颜色(十六进制)
*/
void breathingLightEffect(uint32_t color) {
// 呼吸灯控制变量,static 保持状态
static int brightness = 0; // 当前亮度
static int step = 5; // 亮度变化步长
static int breathDirection = 1; // 呼吸方向:1增亮,-1减暗
static int minBri = 50; // 最小亮度
static int maxBri = 255; // 最大亮度
static unsigned long lastUpdate = 0; // 上次更新时间
const unsigned long interval = 15; // 更新间隔(毫秒)
// 检查是否到达更新时间
if (millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 更新亮度
brightness += step * breathDirection;
// 检查边界并反转方向
if (brightness <= minBri) {
brightness = minBri;
breathDirection = 1; // 开始增亮
} else if (brightness >= maxBri) {
brightness = maxBri;
breathDirection = -1; // 开始减暗
}
// 生成当前亮度下的颜色
CRGB baseColor = color;
CRGB currentColor = baseColor;
currentColor.nscale8_video(brightness);
// 整条灯带同步显示
fill_solid(leds, NUM_LEDS, currentColor);
FastLED.show();
}
}
/**
* @brief 非阻塞固定圈数流水灯旋转效果,需要配合全局变量EffectAllowed来重置
* @param rounds 旋转圈数
* @param color 流水灯颜色(十六进制)
*/
void fixedRoundsWaterEffect(int rounds, uint32_t color) {
static unsigned long lastUpdate = 0;
static int currentLED = 0;
static int roundCount = 0;
static bool running = false;
const unsigned long interval = 30;
// 检查是否允许执行
if (!EffectAllowed) {
// 如果不允许执行,重置所有状态
if (running) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
running = false;
currentLED = 0;
roundCount = 0;
}
return;
}
// 当第一次调用时启动动画
if (!running) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
currentLED = 0;
roundCount = 0;
running = true;
lastUpdate = millis();
}
// 非阻塞更新LED动画
if (running && millis() - lastUpdate >= interval) {
lastUpdate = millis();
// 先检查是否已经完成所有圈数
if (roundCount >= rounds) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
running = false;
EffectAllowed = false; // 标记为不允许再次执行
return;
}
// 熄灭前一个LED
leds[currentLED] = CRGB::Black;
// 移动到下一个LED
currentLED++;
// 完成一圈
if (currentLED >= NUM_LEDS) {
currentLED = 0;
roundCount++;
// 检查完成圈数后立即返回,避免点亮LED0
if (roundCount >= rounds) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
running = false;
EffectAllowed = false;
return;
}
}
// 点亮当前LED
leds[currentLED] = color;
FastLED.show();
}
}
/**
* @brief 点亮指定位置的LED(可自定义颜色),其他LED熄灭
* @param position LED位置(从0开始)
* @param color 十六进制颜色值(0xRRGGBB格式)
*/
void turnOnLEDSingle(int position, uint32_t color) {
if (position >= 0 && position < NUM_LEDS) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
leds[position] = color;
FastLED.show();
}
}
/**
* @brief 点亮指定范围的LED(可自定义颜色),其他LED熄灭
* @param startPos 起始位置(从0开始)
* @param endPos 结束位置
* @param color 十六进制颜色值(0xRRGGBB格式)
*/
void turnOnLEDRange(int startPos, int endPos, uint32_t color) {
if (startPos >= 0 && endPos < NUM_LEDS && startPos <= endPos) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = startPos; i <= endPos; i++) {
leds[i] = color;
}
FastLED.show();
}
}
/**
* @brief 熄灭所有LED
*/
void clearAllLEDs() {
EffectAllowed = true; //重置一些一次性执行特效
num_leds = NUM_LEDS; //重置校时灯效变量
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
}
led.h头文件
主要修改引脚定义以及灯珠数量
#ifndef _LED_H_
#define _LED_H_
#define NUM_LEDS 13 //led 灯珠数
#define LED_PIN 4 //led 控制IO
#define LED_GRADIENT 4 //渐变流水灯效
#define LED_BLUE 3 //银蓝流水灯效
#define LED_TIME_CORRECTION 2 //校时灯效
#define LED_ON 1 //工作灯效(rgb流水)
#define LED_OFF 0 //关闭灯效
void Led_Init(); // LED初始化函数
void Led_Control(int LED_KEYS); // LED主控制函数
void turnOnLEDSingle(int position, uint32_t color); // 点亮单个LED函数
void turnOnLEDRange(int startPos, int endPos, uint32_t color); // 点亮LED范围函数
void fixedRoundsWaterEffect(int rounds, uint32_t color); // 固定圈数流水灯函数
void runningWaterEffect(uint32_t color); // 循环流水灯函数
void breathingLightEffect(uint32_t color); // 呼吸灯效果函数
void alternatingBlinkEffect(uint32_t color1, uint32_t color2, unsigned long interval); // 双色交替闪烁函数
void gradientEffectRGB(uint32_t startColor, uint32_t endColor); // RGB渐变效果函数
void chargingEffect(uint32_t color); // 校时充能灯效函数
void rainbowFlowEffect(); // 全彩色流动RGB函数
void clearAllLEDs(); // 熄灭所有LED函数
#endif
阻塞实现
这个是本人远古时期写的代码了,几乎全使用了delay(),是阻塞的,单独控制灯效时还是有一点作用的,不适合多设备并行使用。
led.cpp文件
#include <FastLED.h>
#include "led.h"
int LED_State = LED_ON; //灯效变量,默认工作灯效
int hue = 0; //色差
int num_leds = NUM_LEDS;
int num_keys = 0;
CRGB leds[NUM_LEDS];
/**
@brief 初始化led
*/
void Led_Init() {
FastLED.addLeds<WS2812, LED_PIN, RGB>(leds, NUM_LEDS); //初始化led
FastLED.setBrightness(150);
}
/*
@brief 模式切换前准备
*/
void Led_Ready() {
}
/**
@brief led灯控制函数
*/
void Led_Control(int LED_KEYS) {
switch (LED_KEYS) {
case 0: //灯效关闭
{
num_leds = NUM_LEDS;
num_keys = 0;
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
break;
}
case 1: //工作灯效 彩色RGB
{
fill_rainbow(leds, NUM_LEDS, hue, 7);
FastLED.show();
delay(30);
hue <= 255 ? hue++ : hue = 0; //ledrainbow
break;
}
case 2: //校时充能灯效/green
{
for (num_keys = 0; num_keys < num_leds; num_keys++) {
FastLED.show();
// leds[num_keys] = CRGB(255, 0, 0); //g r b
leds[num_keys] = CRGB(37, 103, 206); //g r b
FastLED.show();
delay(5);
leds[num_keys] = CRGB::Black;
}
// leds[num_keys - 1] = CRGB(255, 0, 0);
leds[num_keys] = CRGB(37, 103, 206); //g r b
num_leds--;
break;
}
case 3: //流水灯效
{
// FastLED.show();//ticker库使用三目运算符
// num_keys < NUM_LEDS ? num_keys++ : num_keys = 0;
// leds[num_keys] = CRGB(207, 82, 224); //g r b 银蓝色
// FastLED.show();
// leds[num_keys] = CRGB::Black;
// break;
for (num_keys = 0; num_keys < NUM_LEDS; num_keys++) {
FastLED.show();
leds[num_keys] = CRGB(207, 82, 224); //g r b 银蓝色
FastLED.show();
delay(20);
leds[num_keys] = CRGB::Black;
}
break;
}
case 4: //渐变灯效
{
fill_gradient(leds, 0, CHSV(50, 255, 255), 20, CHSV(150, 255, 255), LONGEST_HUES);
FastLED.show();
break;
}
case 5: //流水灯效
{
for (num_keys = 0; num_keys < NUM_LEDS; num_keys++) {
FastLED.show();
leds[num_keys] = CRGB(255, 255, 255); //g r b 白色
FastLED.show();
delay(20);
leds[num_keys] = CRGB::Black;
}
break;
}
case 6: //绿色单色渐变(亮度呼吸)
{
// 固定颜色
CRGB baseColor = CRGB::Green;
// 定义呼吸灯控制变量,static 保持状态
static int brightness = 0; // 当前亮度
static int step = 5; // 亮度变化步长
static int breathDirection = 1; // 呼吸方向:1增亮,-1减暗
static int minBri = 50; // 最小亮度
static int maxBri = 255; // 最大亮度
// 更新亮度
brightness += step * breathDirection;
if (brightness <= minBri || brightness >= maxBri) {
breathDirection = -breathDirection; // 反转方向
brightness = constrain(brightness, minBri, maxBri); // 防止越界
}
// 生成当前亮度下的颜色
CRGB currentColor = baseColor;
currentColor.nscale8_video(brightness);
// 整条灯带同步显示
fill_solid(leds, NUM_LEDS, currentColor);
FastLED.show();
delay(15); // 控制呼吸速度
break;
}
case 7: //绿色渐变到红色(亮度呼吸)
{
// 固定颜色
CRGB baseColor = CRGB::Red;
// 定义呼吸灯控制变量,static 保持状态
static int brightness = 0; // 当前亮度
static int step = 5; // 亮度变化步长
static int breathDirection = 1; // 呼吸方向:1增亮,-1减暗
static int minBri = 50; // 最小亮度
static int maxBri = 255; // 最大亮度
// 更新亮度
brightness += step * breathDirection;
if (brightness <= minBri || brightness >= maxBri) {
breathDirection = -breathDirection; // 反转方向
brightness = constrain(brightness, minBri, maxBri); // 防止越界
}
// 生成当前亮度下的颜色
CRGB currentColor = baseColor;
currentColor.nscale8_video(brightness);
// 整条灯带同步显示
fill_solid(leds, NUM_LEDS, currentColor);
FastLED.show();
delay(15); // 控制呼吸速度
break;
}
case 8: // 红绿交替闪烁
{
static bool toggle = false; // 状态切换标志
if (toggle) {
fill_solid(leds, NUM_LEDS, CRGB::Red); // 全部红色
} else {
fill_solid(leds, NUM_LEDS, CRGB::Green); // 全部绿色
}
FastLED.show();
toggle = !toggle; // 翻转状态
delay(500); // 闪烁速度,可调整
break;
}
case 9: //绿色单色渐变(亮度呼吸)
{
// 固定颜色
CRGB baseColor = CRGB::White;
// 定义呼吸灯控制变量,static 保持状态
static int brightness = 0; // 当前亮度
static int step = 5; // 亮度变化步长
static int breathDirection = 1; // 呼吸方向:1增亮,-1减暗
static int minBri = 50; // 最小亮度
static int maxBri = 255; // 最大亮度
// 更新亮度
brightness += step * breathDirection;
if (brightness <= minBri || brightness >= maxBri) {
breathDirection = -breathDirection; // 反转方向
brightness = constrain(brightness, minBri, maxBri); // 防止越界
}
// 生成当前亮度下的颜色
CRGB currentColor = baseColor;
currentColor.nscale8_video(brightness);
// 整条灯带同步显示
fill_solid(leds, NUM_LEDS, currentColor);
FastLED.show();
delay(15); // 控制呼吸速度
break;
}
case 10: //流水灯效,旋转5圈
{
int rounds = 5; // 设置旋转圈数
for (int r = 0; r < rounds; r++) {
for (num_keys = 0; num_keys < NUM_LEDS; num_keys++) {
leds[num_keys] = CRGB(255, 255, 255); // 白色
FastLED.show();
delay(20);
leds[num_keys] = CRGB::Black; // 熄灭当前LED
}
}
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
break;
}
case 11: //流水灯效,旋转2圈
{
int rounds = 2; // 设置旋转圈数
for (int r = 0; r < rounds; r++) {
for (num_keys = 0; num_keys < NUM_LEDS; num_keys++) {
leds[num_keys] = CRGB(255, 255, 255); // 白色
FastLED.show();
delay(20);
leds[num_keys] = CRGB::Black; // 熄灭当前LED
}
}
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
break;
}
}
}
led.h头文件
#ifndef _LED_H_
#define _LED_H_
#define NUM_LEDS 20 //led 灯珠数
#define LED_PIN 4 //led 控制IO
#define LED_GRADIENT 4 //固定渐变灯效
#define LED_BLUE 3 //银蓝流水灯效
#define LED_TIME_CORRECTION 2 //校时灯效
#define LED_ON 1 //工作灯效(rgb流水)
#define LED_OFF 0 //关闭灯效
void Led_Init();
void Led_Control(int LED_KEYS);
void Led_Ready();
#endif

