打印

LED阵列的波环向外扩散显示效果

[复制链接]
321|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2025-5-23 12:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

代码如下:

#include <FastLED.h>

#define MATRIX_WIDTH   16
#define MATRIX_HEIGHT  16
#define NUM_LEDS       (MATRIX_WIDTH * MATRIX_HEIGHT)
#define LED_PIN        16
#define BRIGHTNESS     80      // 更低亮度更柔和
#define MAX_WAVES      5       // 最大同时存在的波环数

CRGB leds[NUM_LEDS];

// 波环结构体
struct Wave {
  float radius;      // 当前半径
  float intensity;   // 当前强度
  bool active;       // 是否激活
};
Wave waves[MAX_WAVES];

// 效果参数
const float WAVE_SPEED = 0.4;   // 波传播速度(更慢)
const float WAVE_WIDTH = 4.0;   // 波环宽度(更宽)
const float DECAY_RATE = 0.96;  // 衰减速率(更平缓)
const uint16_t WAVE_INTERVAL = 3000; // 新波生成间隔(ms)
const uint8_t BASE_HUE = 160;   // 基础色调(淡蓝)

// 预计算数据
float distanceMap[MATRIX_WIDTH][MATRIX_HEIGHT];
float maxRadius;

// 蛇形矩阵坐标转换
uint16_t XY(uint8_t x, uint8_t y) {
  return (y % 2 == 0) ? (y * MATRIX_WIDTH) + x
                      : (y * MATRIX_WIDTH) + (MATRIX_WIDTH - 1 - x);
}

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  
  // 预计算距离矩阵
  float centerX = (MATRIX_WIDTH-1)/2.0;
  float centerY = (MATRIX_HEIGHT-1)/2.0;
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
    for(uint8_t x=0; x<MATRIX_WIDTH; x++){
      float dx = x - centerX;
      float dy = y - centerY;
      distanceMap[x][y] = sqrt(dx*dx + dy*dy);
    }
  }
  maxRadius = distanceMap[0][0]; // 最大半径(到角落的距离)

  // 初始化波环
  for(auto &w : waves) w.active = false;
}

void spawnWave() {
  for(auto &w : waves){
    if(!w.active){
      w.radius = 0.0;
      w.intensity = 1.0;
      w.active = true;
      return;
    }
  }
}

void loop() {
  static uint32_t lastWaveTime = 0;
  
  // 生成新波环
  if(millis() - lastWaveTime > WAVE_INTERVAL){
    spawnWave();
    lastWaveTime = millis();
  }

  // 清空LED
  memset8(leds, 0, NUM_LEDS * 3);

  // 更新所有波环
  for(auto &w : waves){
    if(w.active){
      // 更新波环参数
      w.radius += WAVE_SPEED;
      w.intensity *= DECAY_RATE;

      // 波环失效条件
      if(w.radius > maxRadius*1.2 || w.intensity < 0.05){
        w.active = false;
        continue;
      }

      // 绘制波环
      for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
        for(uint8_t x=0; x<MATRIX_WIDTH; x++){
          float dist = distanceMap[x][y];
         
          // 计算波环影响
          float delta = abs(dist - w.radius);
          float effect = exp(-pow(delta/WAVE_WIDTH, 2)) * w.intensity;
         
          // 叠加颜色(加法混合)
          float hue = BASE_HUE + w.radius*0.3; // 色相渐变
          uint8_t val = constrain(effect * 255, 0, 255);
          leds[XY(x,y)] += CHSV(hue, 200, val);
        }
      }
    }
  }

  // 添加中心常亮
  leds[XY(MATRIX_WIDTH/2, MATRIX_HEIGHT/2)] = CHSV(BASE_HUE, 255, 50);

  FastLED.show();
  FastLED.delay(30); // 更流畅的动画
}

使用特权

评论回复

相关帖子

沙发
keer_zu|  楼主 | 2025-5-23 12:48 | 只看该作者
连续的波:

变量:

//===================== wave ====================================
#define MAX_WAVES      4       // 最大同时存在的波环数

struct Wave {
  float radius;
  float intensity;
  bool active;
  uint8_t generation;
  bool hasTriggered;
};
Wave waves[MAX_WAVES];

const float WAVE_SPEED = 0.4;
const float WAVE_WIDTH = 3.5;
const float DECAY_RATE = 0.96;
const float TRIGGER_DISTANCE = 2.5;

float distanceMap[MATRIX_WIDTH][MATRIX_HEIGHT];
float maxRadius;
uint8_t center_x, center_y; // 修改变量名
void spawnWave(uint8_t gen);
//===============================================================


初始化:

  //==================== wave ======================
    // 修改中心坐标变量名
  center_x = (MATRIX_WIDTH-1)/2;
  center_y = (MATRIX_HEIGHT-1)/2;
  
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
    for(uint8_t x=0; x<MATRIX_WIDTH; x++){
      float dx = x - center_x; // 修改变量名
      float dy = y - center_y; // 修改变量名
      distanceMap[x][y] = sqrt(dx*dx + dy*dy);
    }
  }
  maxRadius = distanceMap[0][0];

  waves[0] = {0.0, 1.0, true, 0, false};
  for(uint8_t i=1; i<MAX_WAVES; i++) waves[i].active = false;

  //================================================




实现:

//======================  wave ======================


// 生成新波环(参数:代数)
void spawnWave(uint8_t gen) {
  for(auto &w : waves){
    if(!w.active){
      w.radius = 0.0;
      w.intensity = 1.0 - gen*0.15; // 每代强度递减
      w.active = true;
      w.generation = gen;
      return;
    }
  }
}

void wave_vision() {
  static uint32_t lastFrame = millis();
  float deltaTime = (millis() - lastFrame)/1000.0;
  lastFrame = millis();

  fadeToBlackBy(leds, NUM_LEDS, 30);

  for(uint8_t i=0; i<MAX_WAVES; i++){
    if(waves[i].active){
      Wave &w = waves[i];
      w.radius += WAVE_SPEED * (1.0 + deltaTime);
      w.intensity *= DECAY_RATE;

      if(w.generation == 0 && !w.hasTriggered && w.radius >= TRIGGER_DISTANCE){
        spawnWave(1);
        w.hasTriggered = true;
      }

      if(w.radius > maxRadius || w.intensity < 0.1){
        if(w.generation == 0){
          w.radius = 0.0;
          w.intensity = 1.0;
          w.hasTriggered = false;
        }else{
          w.active = false;
        }
      }

      for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
        for(uint8_t x=0; x<MATRIX_WIDTH; x++){
          float dist = distanceMap[x][y];
          float delta = abs(dist - w.radius);
          float effect = exp(-pow(delta/WAVE_WIDTH, 2)) * w.intensity;
         
          // 修改中心区域判断条件变量名
          if(x >= center_x-1 && x <= center_x &&
             y >= center_y-1 && y <= center_y){ // 变量名修改
            effect *= 0.2;
          }
         
          leds[XY(x,y)] += CHSV(160 + w.generation*20, 200, effect * 200);
        }
      }
    }
  }

  // 修改中心区域强制降亮部分变量名
  for(uint8_t dx=0; dx<2; dx++){
    for(uint8_t dy=0; dy<2; dy++){
      uint16_t idx = XY(center_x-dx, center_y-dy); // 变量名修改
      leds[idx].nscale8(50);
    }
  }

  FastLED.show();
  FastLED.delay(30);
}


使用特权

评论回复
板凳
keer_zu|  楼主 | 2025-5-23 13:02 | 只看该作者
宽度调整、密度增加和随机性改进:

代码如下:

#include <FastLED.h>

#define MATRIX_WIDTH   16
#define MATRIX_HEIGHT  16
#define NUM_LEDS       (MATRIX_WIDTH * MATRIX_HEIGHT)
#define LED_PIN        16
#define BRIGHTNESS     90
#define MAX_WAVES      6  // 增加最大波环数量

CRGB leds[NUM_LEDS];

struct Wave {
  float radius;
  float intensity;
  bool active;
  uint8_t generation;
  bool hasTriggered;
  float speedVariation;   // 速度随机因子
  float widthVariation;   // 宽度随机因子
  float angleOffset;      // 角度偏移(用于形状随机)
};
Wave waves[MAX_WAVES];

// 调整后的参数
const float BASE_WAVE_SPEED = 0.45;  // 基础速度
const float BASE_WAVE_WIDTH = 2.4f;   // 基础宽度(减小)
const float DECAY_RATE = 0.955f;
const float TRIGGER_DISTANCE = 1.8f;  // 缩短触发距离增加密度

float distanceMap[MATRIX_WIDTH][MATRIX_HEIGHT];
float maxRadius;
uint8_t center_x, center_y;

uint16_t XY(uint8_t x, uint8_t y) {
  return (y % 2 == 0) ? (y * MATRIX_WIDTH) + x
                      : (y * MATRIX_WIDTH) + (MATRIX_WIDTH - 1 - x);
}

// 带随机扰动的距离计算
float perturbedDistance(uint8_t x, uint8_t y, Wave &w) {
  float dx = x - center_x;
  float dy = y - center_y;
  
  // 添加基于角度的随机扰动
  float angle = atan2(dy, dx) + w.angleOffset;
  float perturbation = 0.4f * sin(angle * 3 + w.radius * 0.5f);
  
  return sqrt(dx*dx + dy*dy) * (1.0f + perturbation * 0.08f);
}

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  
  center_x = (MATRIX_WIDTH-1)/2;
  center_y = (MATRIX_HEIGHT-1)/2;
  
  // 预计算基础距离
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
    for(uint8_t x=0; x<MATRIX_WIDTH; x++){
      float dx = x - center_x;
      float dy = y - center_y;
      distanceMap[x][y] = sqrt(dx*dx + dy*dy);
    }
  }
  maxRadius = distanceMap[0][0];

  // 初始化第一个波环
  waves[0] = {
    0.0f,
    1.0f,
    true,
    0,
    false,
    random8(95, 105)/100.0f,  // 初始速度随机
    random8(95, 105)/100.0f,  // 初始宽度随机
    random8(0, 628)/100.0f     // 初始角度偏移(0-2π)
  };
  for(uint8_t i=1; i<MAX_WAVES; i++) waves[i].active = false;
}

void spawnWave(uint8_t gen) {
  for(uint8_t i=0; i<MAX_WAVES; i++){
    if(!waves[i].active){
      waves[i] = {
        0.0f,
        1.0f - gen*0.12f,
        true,
        gen,
        false,
        random8(95, 105)/100.0f,  // 速度随机因子
        random8(90, 110)/100.0f,  // 宽度随机因子
        random8(0, 628)/100.0f    // 新随机角度
      };
      return;
    }
  }
}

void loop() {
  static uint32_t lastFrame = millis();
  float deltaTime = (millis() - lastFrame)/1000.0f;
  lastFrame = millis();

  fadeToBlackBy(leds, NUM_LEDS, 25);  // 加快淡出速度增加密度感

  for(uint8_t i=0; i<MAX_WAVES; i++){
    if(waves[i].active){
      Wave &w = waves[i];
      
      // 应用随机速度
      w.radius += BASE_WAVE_SPEED * w.speedVariation * (1.0f + deltaTime);
      w.intensity *= DECAY_RATE;

      // 触发新波环
      if(w.generation == 0 && !w.hasTriggered && w.radius >= TRIGGER_DISTANCE){
        spawnWave(1);
        w.hasTriggered = true;
      }

      // 波环生命周期管理
      if(w.radius > maxRadius || w.intensity < 0.12f){
        if(w.generation == 0){
          // 重置核心波环并重新随机参数
          w.radius = 0.0f;
          w.intensity = 1.0f;
          w.hasTriggered = false;
          w.speedVariation = random8(95, 105)/100.0f;
          w.widthVariation = random8(90, 110)/100.0f;
          w.angleOffset = random8(0, 628)/100.0f;
        }else{
          w.active = false;
        }
      }

      // 绘制波环
      for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
        for(uint8_t x=0; x<MATRIX_WIDTH; x++){
          // 使用扰动后的距离计算
          float dist = perturbedDistance(x, y, w);
          float delta = abs(dist - w.radius);
         
          // 应用随机宽度
          float effectiveWidth = BASE_WAVE_WIDTH * w.widthVariation;
          float effect = exp(-pow(delta/effectiveWidth, 2.2f)) * w.intensity;
         
          // 中心抑制
          if(x >= center_x-1 && x <= center_x && y >= center_y-1 && y <= center_y){
            effect *= 0.15f;
          }
         
          // 颜色混合(添加轻微随机色相偏移)
          uint8_t hue = 160 + w.generation*18 + w.radius*0.8f;
          leds[XY(x,y)] += CHSV(hue, 210, effect * 220);
        }
      }
    }
  }

  // 强化中心暗区
  for(uint8_t dx=0; dx<2; dx++){
    for(uint8_t dy=0; dy<2; dy++){
      uint16_t idx = XY(center_x-dx, center_y-dy);
      leds[idx].nscale8(40);  // 更暗的中心
    }
  }

  FastLED.show();
  FastLED.delay(28);  // 稍快的刷新率
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1445

主题

12781

帖子

53

粉丝