在ESP32上使用FastLED库实现烛光效果

[复制链接]
640|0
keer_zu 发表于 2025-11-12 10:20 | 显示全部楼层 |阅读模式

一个在ESP32上使用FastLED库实现烛光效果的代码。这个效果模拟了真实蜡烛的闪烁和颜色变化。

#include <FastLED.h>

// LED点阵配置
#define LED_PIN     2
#define NUM_LEDS    64  // 假设是8x8点阵
#define BRIGHTNESS  100
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

// 烛光参数
uint8_t flickerIntensity = 50;  // 闪烁强度
uint8_t baseBrightness = 150;   // 基础亮度
unsigned long lastFlicker = 0;
unsigned long flickerDelay = 50; // 闪烁间隔(毫秒)

// 烛光颜色调色板 - 从深黄到橙红
CRGBPalette16 flamePalette = CRGBPalette16(
  CRGB::DarkOrange,
  CRGB::Orange,
  CRGB::OrangeRed,
  CRGB::Yellow,
  CRGB::Gold,
  CRGB::Orange,
  CRGB::Red,
  CRGB::DarkOrange,
  CRGB::OrangeRed,
  CRGB::Yellow,
  CRGB::Orange,
  CRGB::Gold,
  CRGB::Red,
  CRGB::DarkOrange,
  CRGB::Orange,
  CRGB::Yellow
);

void setup() {
  Serial.begin(115200);
  delay(1000); // 给串口时间初始化
  
  // 初始化FastLED
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  
  Serial.println("烛光效果启动");
}

void loop() {
  candleEffect();
  FastLED.show();
  delay(30); // 控制刷新率
}

void candleEffect() {
  unsigned long currentTime = millis();
  
  // 定期更新闪烁参数
  if (currentTime - lastFlicker > flickerDelay) {
    flickerIntensity = random8(30, 80);
    flickerDelay = random8(30, 100);
    lastFlicker = currentTime;
  }
  
  // 为每个LED生成烛光效果
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getCandleColor(i);
  }
}

CRGB getCandleColor(int ledIndex) {
  // 使用噪声函数创建自然的烛光效果
  uint16_t noise = inoise8(ledIndex * 20, millis() / 50);
  
  // 基础颜色 - 暖黄色
  CRGB baseColor = CRGB(255, 150, 50);
  
  // 添加随机闪烁
  uint8_t flicker = random8(flickerIntensity);
  uint8_t brightness = baseBrightness - flicker;
  
  // 使用调色板获取颜色变化
  uint8_t colorIndex = scale8(noise, 128) + random8(20);
  CRGB flameColor = ColorFromPalette(flamePalette, colorIndex);
  
  // 混合基础颜色和火焰颜色
  CRGB finalColor = blend(baseColor, flameColor, noise);
  
  // 应用亮度变化
  finalColor.nscale8_video(brightness);
  
  return finalColor;
}

// 高级版本:模拟火焰形状的烛光
void advancedCandleEffect() {
  // 假设8x8点阵,索引按行排列
  const uint8_t width = 8;
  const uint8_t height = 8;
  
  for (uint8_t y = 0; y < height; y++) {
    for (uint8_t x = 0; x < width; x++) {
      int index = y * width + x;
    
      // 计算距离中心的距离来创建火焰形状
      int centerX = width / 2;
      float distance = sqrt(pow(x - centerX, 2) + pow(y, 2));
    
      // 基础亮度随高度增加而减小
      uint8_t baseBright = 200 - (y * 25);
    
      // 使用Perlin噪声创建有机的火焰运动
      uint16_t noise1 = inoise8(x * 30, y * 40 + millis() / 60);
      uint16_t noise2 = inoise8(x * 25 + 1000, millis() / 45);
    
      // 结合多个噪声源
      uint8_t combinedNoise = (noise1 + noise2) / 2;
    
      // 火焰形状遮罩 - 底部亮,顶部暗
      uint8_t flameMask = 255 - (y * 32);
      if (flameMask < 50) flameMask = 50;
    
      // 随机闪烁
      uint8_t flicker = random8(30, 70);
    
      // 最终亮度计算
      uint8_t brightness = (baseBright * combinedNoise / 255) - flicker;
      brightness = (brightness * flameMask) / 255;
    
      // 颜色选择 - 底部偏黄,顶部偏橙红
      uint8_t hue;
      if (y < 2) {
        hue = 25; // 黄色
      } else if (y < 4) {
        hue = 20; // 橙黄色
      } else {
        hue = 10; // 橙红色
      }
    
      // 添加颜色变化
      hue += random8(-3, 3);
    
      leds[index] = CHSV(hue, 255, brightness);
    }
  }
}

// 切换效果的函数
void switchEffect() {
  static bool simpleEffect = true;
  
  if (simpleEffect) {
    candleEffect();
  } else {
    advancedCandleEffect();
  }
  
  simpleEffect = !simpleEffect;
}

使用说明

  1. 基础配置

    • 修改 LED_PIN 为你的ESP32连接的数据引脚
    • 修改 NUM_LEDS 为你的点阵LED数量
    • 调整 BRIGHTNESS 控制整体亮度
  2. 两种效果

    • candleEffect(): 简单的烛光闪烁效果
    • advancedCandleEffect(): 更复杂的火焰形状模拟
  3. 自定义参数

    • flickerIntensity: 控制闪烁强度
    • baseBrightness: 基础亮度水平
    • flamePalette: 烛光颜色调色板

进阶功能

你还可以添加以下功能来增强效果:

// 添加环境光传感器控制亮度
void autoBrightness() {
  // 读取光敏电阻值
  int lightValue = analogRead(A0);
  int newBrightness = map(lightValue, 0, 4095, 50, 255);
  FastLED.setBrightness(newBrightness);
}

// 响应声音的烛光效果
void soundReactiveCandle() {
  int soundLevel = analogRead(A1);
  if (soundLevel > 500) {
    // 声音较大时增强闪烁
    flickerIntensity = 100;
  }
}

这个代码提供了自然的烛光效果,包括颜色变化、亮度闪烁和火焰形状模拟。可以根据实际硬件调整参数来获得最佳效果。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1497

主题

12971

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部