FastLED库快速使用手册
本文最后更新于25 天前,如有错误请在评论区中留言。

FasLED库使用

日志

2025-11-12
新增灯效,修改调用逻辑
2025-10-31
记录自用fastled库

前言

前段时间做了一些小项目,有使用到WS2812灯带,ST7789驱动的LCD彩屏,DF家的mini mp3 player,还有servo motor。这里主要记录一下灯带库的使用,以及封装好的原程序,便于后期快速使用。其中有一些重复功能,忽略即可。

使用说明

  • 新建led.cppled.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
如果您觉得本博客内容有所帮助,可以打赏一下吗~,此打赏将会用于博客维护运营,十分感谢!
作者:Clif
版权声明: 本博客所有文章除未特别声明外,均采用CC BY-NC-SA 4.0协议。转载请注明文章地址及作者!
暂无评论

发送评论(请正确填写邮箱地址,否则将会当成垃圾评论处理) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇