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

[复制链接]
 楼主| keer_zu 发表于 2025-5-23 12:19 | 显示全部楼层 |阅读模式

代码如下:

  1. #include <FastLED.h>

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

  8. CRGB leds[NUM_LEDS];

  9. // 波环结构体
  10. struct Wave {
  11.   float radius;      // 当前半径
  12.   float intensity;   // 当前强度
  13.   bool active;       // 是否激活
  14. };
  15. Wave waves[MAX_WAVES];

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

  22. // 预计算数据
  23. float distanceMap[MATRIX_WIDTH][MATRIX_HEIGHT];
  24. float maxRadius;

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

  30. void setup() {
  31.   FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  32.   FastLED.setBrightness(BRIGHTNESS);
  33.   
  34.   // 预计算距离矩阵
  35.   float centerX = (MATRIX_WIDTH-1)/2.0;
  36.   float centerY = (MATRIX_HEIGHT-1)/2.0;
  37.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  38.     for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  39.       float dx = x - centerX;
  40.       float dy = y - centerY;
  41.       distanceMap[x][y] = sqrt(dx*dx + dy*dy);
  42.     }
  43.   }
  44.   maxRadius = distanceMap[0][0]; // 最大半径(到角落的距离)

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

  48. void spawnWave() {
  49.   for(auto &w : waves){
  50.     if(!w.active){
  51.       w.radius = 0.0;
  52.       w.intensity = 1.0;
  53.       w.active = true;
  54.       return;
  55.     }
  56.   }
  57. }

  58. void loop() {
  59.   static uint32_t lastWaveTime = 0;
  60.   
  61.   // 生成新波环
  62.   if(millis() - lastWaveTime > WAVE_INTERVAL){
  63.     spawnWave();
  64.     lastWaveTime = millis();
  65.   }

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

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

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

  79.       // 绘制波环
  80.       for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  81.         for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  82.           float dist = distanceMap[x][y];
  83.          
  84.           // 计算波环影响
  85.           float delta = abs(dist - w.radius);
  86.           float effect = exp(-pow(delta/WAVE_WIDTH, 2)) * w.intensity;
  87.          
  88.           // 叠加颜色(加法混合)
  89.           float hue = BASE_HUE + w.radius*0.3; // 色相渐变
  90.           uint8_t val = constrain(effect * 255, 0, 255);
  91.           leds[XY(x,y)] += CHSV(hue, 200, val);
  92.         }
  93.       }
  94.     }
  95.   }

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

  98.   FastLED.show();
  99.   FastLED.delay(30); // 更流畅的动画
  100. }
 楼主| keer_zu 发表于 2025-5-23 12:48 | 显示全部楼层
连续的波:

变量:

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

  3. struct Wave {
  4.   float radius;
  5.   float intensity;
  6.   bool active;
  7.   uint8_t generation;
  8.   bool hasTriggered;
  9. };
  10. Wave waves[MAX_WAVES];

  11. const float WAVE_SPEED = 0.4;
  12. const float WAVE_WIDTH = 3.5;
  13. const float DECAY_RATE = 0.96;
  14. const float TRIGGER_DISTANCE = 2.5;

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


初始化:

  1.   //==================== wave ======================
  2.     // 修改中心坐标变量名
  3.   center_x = (MATRIX_WIDTH-1)/2;
  4.   center_y = (MATRIX_HEIGHT-1)/2;
  5.   
  6.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  7.     for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  8.       float dx = x - center_x; // 修改变量名
  9.       float dy = y - center_y; // 修改变量名
  10.       distanceMap[x][y] = sqrt(dx*dx + dy*dy);
  11.     }
  12.   }
  13.   maxRadius = distanceMap[0][0];

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

  16.   //================================================




实现:

  1. //======================  wave ======================


  2. // 生成新波环(参数:代数)
  3. void spawnWave(uint8_t gen) {
  4.   for(auto &w : waves){
  5.     if(!w.active){
  6.       w.radius = 0.0;
  7.       w.intensity = 1.0 - gen*0.15; // 每代强度递减
  8.       w.active = true;
  9.       w.generation = gen;
  10.       return;
  11.     }
  12.   }
  13. }

  14. void wave_vision() {
  15.   static uint32_t lastFrame = millis();
  16.   float deltaTime = (millis() - lastFrame)/1000.0;
  17.   lastFrame = millis();

  18.   fadeToBlackBy(leds, NUM_LEDS, 30);

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

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

  28.       if(w.radius > maxRadius || w.intensity < 0.1){
  29.         if(w.generation == 0){
  30.           w.radius = 0.0;
  31.           w.intensity = 1.0;
  32.           w.hasTriggered = false;
  33.         }else{
  34.           w.active = false;
  35.         }
  36.       }

  37.       for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  38.         for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  39.           float dist = distanceMap[x][y];
  40.           float delta = abs(dist - w.radius);
  41.           float effect = exp(-pow(delta/WAVE_WIDTH, 2)) * w.intensity;
  42.          
  43.           // 修改中心区域判断条件变量名
  44.           if(x >= center_x-1 && x <= center_x &&
  45.              y >= center_y-1 && y <= center_y){ // 变量名修改
  46.             effect *= 0.2;
  47.           }
  48.          
  49.           leds[XY(x,y)] += CHSV(160 + w.generation*20, 200, effect * 200);
  50.         }
  51.       }
  52.     }
  53.   }

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

  61.   FastLED.show();
  62.   FastLED.delay(30);
  63. }


 楼主| keer_zu 发表于 2025-5-23 13:02 | 显示全部楼层
宽度调整、密度增加和随机性改进:

代码如下:

  1. #include <FastLED.h>

  2. #define MATRIX_WIDTH   16
  3. #define MATRIX_HEIGHT  16
  4. #define NUM_LEDS       (MATRIX_WIDTH * MATRIX_HEIGHT)
  5. #define LED_PIN        16
  6. #define BRIGHTNESS     90
  7. #define MAX_WAVES      6  // 增加最大波环数量

  8. CRGB leds[NUM_LEDS];

  9. struct Wave {
  10.   float radius;
  11.   float intensity;
  12.   bool active;
  13.   uint8_t generation;
  14.   bool hasTriggered;
  15.   float speedVariation;   // 速度随机因子
  16.   float widthVariation;   // 宽度随机因子
  17.   float angleOffset;      // 角度偏移(用于形状随机)
  18. };
  19. Wave waves[MAX_WAVES];

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

  25. float distanceMap[MATRIX_WIDTH][MATRIX_HEIGHT];
  26. float maxRadius;
  27. uint8_t center_x, center_y;

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

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

  43. void setup() {
  44.   FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  45.   FastLED.setBrightness(BRIGHTNESS);
  46.   
  47.   center_x = (MATRIX_WIDTH-1)/2;
  48.   center_y = (MATRIX_HEIGHT-1)/2;
  49.   
  50.   // 预计算基础距离
  51.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  52.     for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  53.       float dx = x - center_x;
  54.       float dy = y - center_y;
  55.       distanceMap[x][y] = sqrt(dx*dx + dy*dy);
  56.     }
  57.   }
  58.   maxRadius = distanceMap[0][0];

  59.   // 初始化第一个波环
  60.   waves[0] = {
  61.     0.0f,
  62.     1.0f,
  63.     true,
  64.     0,
  65.     false,
  66.     random8(95, 105)/100.0f,  // 初始速度随机
  67.     random8(95, 105)/100.0f,  // 初始宽度随机
  68.     random8(0, 628)/100.0f     // 初始角度偏移(0-2π)
  69.   };
  70.   for(uint8_t i=1; i<MAX_WAVES; i++) waves[i].active = false;
  71. }

  72. void spawnWave(uint8_t gen) {
  73.   for(uint8_t i=0; i<MAX_WAVES; i++){
  74.     if(!waves[i].active){
  75.       waves[i] = {
  76.         0.0f,
  77.         1.0f - gen*0.12f,
  78.         true,
  79.         gen,
  80.         false,
  81.         random8(95, 105)/100.0f,  // 速度随机因子
  82.         random8(90, 110)/100.0f,  // 宽度随机因子
  83.         random8(0, 628)/100.0f    // 新随机角度
  84.       };
  85.       return;
  86.     }
  87.   }
  88. }

  89. void loop() {
  90.   static uint32_t lastFrame = millis();
  91.   float deltaTime = (millis() - lastFrame)/1000.0f;
  92.   lastFrame = millis();

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

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

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

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

  120.       // 绘制波环
  121.       for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
  122.         for(uint8_t x=0; x<MATRIX_WIDTH; x++){
  123.           // 使用扰动后的距离计算
  124.           float dist = perturbedDistance(x, y, w);
  125.           float delta = abs(dist - w.radius);
  126.          
  127.           // 应用随机宽度
  128.           float effectiveWidth = BASE_WAVE_WIDTH * w.widthVariation;
  129.           float effect = exp(-pow(delta/effectiveWidth, 2.2f)) * w.intensity;
  130.          
  131.           // 中心抑制
  132.           if(x >= center_x-1 && x <= center_x && y >= center_y-1 && y <= center_y){
  133.             effect *= 0.15f;
  134.           }
  135.          
  136.           // 颜色混合(添加轻微随机色相偏移)
  137.           uint8_t hue = 160 + w.generation*18 + w.radius*0.8f;
  138.           leds[XY(x,y)] += CHSV(hue, 210, effect * 220);
  139.         }
  140.       }
  141.     }
  142.   }

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

  150.   FastLED.show();
  151.   FastLED.delay(28);  // 稍快的刷新率
  152. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1477

主题

12909

帖子

55

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