打印

将两条led融合为一个显示矩阵

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

#include <FastLED.h>

// 矩阵配置
#define MATRIX_WIDTH  30
#define MATRIX_HEIGHT 19
#define DATA_PIN_LOWER 15  // 下部区域GPIO15
#define DATA_PIN_UPPER 4   // 上部区域GPIO2

// LED总数计算
#define NUM_LOWER_ROWS  9
#define NUM_UPPER_ROWS  10
#define NUM_LEDS_LOWER (MATRIX_WIDTH*NUM_LOWER_ROWS)   // 下部30x9
#define NUM_LEDS_UPPER (MATRIX_WIDTH*NUM_UPPER_ROWS) // 上部30x10
#define NUM_LEDS (NUM_LEDS_LOWER + NUM_LEDS_UPPER)
CRGB leds[NUM_LEDS];


// 颜色定义
const CRGB BACKGROUND = CRGB(0, 0, 0);  // 浅白色背景
const CRGB CIRCLE_COLOR = CRGB(0, 100, 255);  // 蓝色圆环

#define MAX_WAVES      6  // 增加最大波环数量


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


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;

//===============================================================
// 安全版XY映射
uint16_t XY(uint8_t x, uint8_t y) {
  x = constrain(x, 0, MATRIX_WIDTH-1);
  y = constrain(y, 0, MATRIX_HEIGHT-1);
  
  uint16_t index;
  if(y < NUM_LOWER_ROWS) {
    if(y % 2 == 0) {
      index = y * MATRIX_WIDTH + x;
    } else {
      index = (y + 1) * MATRIX_WIDTH - 1 - x;
    }
  } else {
    if(y % 2 == 0) {
      index = (y-NUM_LOWER_ROWS) * MATRIX_WIDTH + x + NUM_LEDS_LOWER;
    } else {
      index = (y-NUM_LOWER_ROWS + 1) * MATRIX_WIDTH - 1 - x + NUM_LEDS_LOWER;
    }
  }

  return constrain(index, 0, NUM_LEDS-1);
}


void setup() {
  FastLED.addLeds<WS2815, DATA_PIN_LOWER, GRB>(leds, NUM_LEDS_LOWER);
  FastLED.addLeds<WS2815, DATA_PIN_UPPER, GRB>(leds+NUM_LEDS_LOWER, NUM_LEDS_UPPER);
  FastLED.setBrightness(100);
  FastLED.clear();
   //==================== 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.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;

  //================================================
}

// 带随机扰动的距离计算
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 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);  // 稍快的刷新率
}

使用特权

评论回复

相关帖子

沙发
keer_zu|  楼主 | 2025-5-26 17:20 | 只看该作者
显示16*16汉字:

#include <FastLED.h>
#include <ArduinoJson.h>

#define COLOR_ORDER GRB
#define CHIPSET     WS2815



//======================================
// 矩阵配置
#define MATRIX_WIDTH  30
#define MATRIX_HEIGHT 19
#define DATA_PIN_LOWER 15  // 下部区域GPIO15
#define DATA_PIN_UPPER 4   // 上部区域GPIO2

// LED总数计算
#define NUM_LOWER_ROWS  9
#define NUM_UPPER_ROWS  10
#define NUM_LEDS_LOWER (MATRIX_WIDTH*NUM_LOWER_ROWS)   // 下部30x9
#define NUM_LEDS_UPPER (MATRIX_WIDTH*NUM_UPPER_ROWS) // 上部30x10
#define NUM_LEDS (NUM_LEDS_LOWER + NUM_LEDS_UPPER)
CRGB leds[NUM_LEDS];
//======================================

#define HAN_BITMAP_HEIGHT 16
#define HAN_START_ROW  2   //只能偶数
#define BITMAP_WIDTH 720
#define BITMAP_WIDTH_BYTE_NUM  (BITMAP_WIDTH/8)




#define BITMAP_INDEX(x,y) ((HAN_BITMAP_HEIGHT - 1 - y)*BITMAP_WIDTH_BYTE_NUM + (x/8) - 1)
#define BITMMAP_POSITION(x) (x%8)


// 颜色定义
const CRGB BACKGROUND_COLOR = CRGB(0x0, 0x0, 0x100); //
const CRGB TEXT_COLOR = CRGB(30,250, 30);       //

// 点阵数据(已转换格式)
/*96 x 15*/
static const unsigned char textBitmap[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x04, 0x40, 0x10, 0x00, 0x10, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00, 0x40, 0x10, 0x40, 0x04, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x20, 0x04, 0x40, 0x10, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x04, 0x40, 0x00, 0x80, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0x00, 0x80, 0x01, 0x10, 0x00, 0x80, 0x00, 0x80, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x3f, 0xf8, 0x3f, 0xf8, 0x20, 0x40, 0x20, 0x40, 0x0e, 0x50, 0x10, 0xfc, 0x10, 0x20, 0x10, 0x20, 0x00, 0x00, 0x7c, 0x20, 0x10, 0x40, 0x0e, 0x50, 0x23, 0xfe, 0x04, 0x00, 0x10, 0x20, 0x20, 0x40, 0x20, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x3f, 0xf8, 0x08, 0x20, 0x0e, 0x50, 0x10, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x41, 0x08, 0x3f, 0xf8, 0x00, 0x40, 0x01, 0x00, 0x0e, 0x50, 0x00, 0x80, 0x01, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0x10, 0x00, 0x40, 0x01, 0x10, 0x20, 0x40, 0x20, 0x40, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x17, 0xfc, 0x17, 0xfc, 0x78, 0x48, 0x10, 0x04, 0x10, 0x40, 0x10, 0x40, 0x00, 0x00, 0x45, 0xfc, 0x20, 0x40, 0x78, 0x48, 0x12, 0x02, 0x1f, 0xf0, 0x10, 0x3e, 0x17, 0xfc, 0x17, 0xfc, 0x00, 0x00, 0x7f, 0xfe, 0xfc, 0x10, 0x01, 0x00, 0x08, 0x20, 0x78, 0x48, 0x3f, 0x7e, 0x78, 0xa0, 0x78, 0xa0, 0x00, 0x00, 0x21, 0x10, 0x01, 0x00, 0xfc, 0x80, 0x02, 0x80, 0x78, 0x48, 0x78, 0x80, 0x77, 0xc4, 0x79, 0x20, 0x00, 0x00, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0x17, 0xfc, 0x17, 0xfc, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x7f, 0xfe, 0x11, 0x10, 0x11, 0x10, 0x08, 0x48, 0x10, 0x08, 0x11, 0xfc, 0x11, 0xfc, 0x00, 0x00, 0x44, 0x88, 0x7e, 0x7c, 0x08, 0x48, 0x14, 0x44, 0x10, 0x10, 0x10, 0x20, 0x10, 0xe0, 0x10, 0xe0, 0x00, 0x00, 0x40, 0x02, 0x11, 0xfe, 0x01, 0x00, 0x7e, 0x20, 0x08, 0x48, 0x28, 0x90, 0x49, 0x10, 0x49, 0x10, 0x00, 0x00, 0x2f, 0xfe, 0x01, 0x00, 0x04, 0xfe, 0x04, 0x40, 0x08, 0x48, 0x48, 0xfc, 0x51, 0x04, 0x49, 0x20, 0x00, 0x00, 0x91, 0x10, 0x91, 0x10, 0x91, 0x10, 0x91, 0x10, 0x11, 0x10, 0x11, 0x10, 0x91, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x41, 0x02, 0x82, 0x48, 0x82, 0x48, 0x08, 0x40, 0xfc, 0x10, 0x19, 0x04, 0x19, 0x04, 0x00, 0x00, 0x7c, 0x50, 0x42, 0x84, 0x08, 0x40, 0x80, 0x40, 0x1f, 0xf0, 0xfd, 0xfc, 0x81, 0x50, 0x81, 0x50, 0x00, 0x00, 0x88, 0x24, 0x11, 0x12, 0x01, 0x00, 0x08, 0xfc, 0x08, 0x40, 0x45, 0x08, 0x4a, 0x08, 0x4a, 0x08, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x05, 0x08, 0x08, 0x20, 0x08, 0x40, 0x49, 0x04, 0x51, 0x14, 0x49, 0x20, 0x00, 0x00, 0x90, 0xa0, 0x90, 0x40, 0x90, 0xa0, 0x90, 0x40, 0x80, 0xa0, 0x80, 0xa0, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x9d, 0x74, 0x44, 0x84, 0x44, 0x84, 0xff, 0xfe, 0x24, 0x20, 0x55, 0x04, 0x55, 0x04, 0x00, 0x00, 0x43, 0xfe, 0x42, 0x84, 0xff, 0xfe, 0x43, 0xfc, 0x10, 0x10, 0x11, 0x04, 0x42, 0x48, 0x42, 0x48, 0x00, 0x00, 0x11, 0x10, 0x21, 0x14, 0x01, 0x00, 0x08, 0x24, 0xff, 0xfe, 0x80, 0xf0, 0x4c, 0x06, 0x4c, 0x06, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x05, 0x08, 0x37, 0xd8, 0xff, 0xfe, 0x49, 0x08, 0x57, 0xd4, 0x49, 0x20, 0x00, 0x00, 0x97, 0xfc, 0x90, 0xa0, 0x97, 0xfc, 0x90, 0xa0, 0x47, 0xfc, 0x47, 0xfc, 0x90, 0xa0, 0x00, 0x00, 0x00, 0x00,
    0xff, 0xfe, 0x01, 0x00, 0x41, 0x20, 0x41, 0x20, 0x08, 0x40, 0x24, 0x20, 0x51, 0x04, 0x51, 0x04, 0x00, 0x00, 0x7c, 0x20, 0x43, 0x04, 0x08, 0x40, 0x48, 0x80, 0x1f, 0xf2, 0x15, 0xfc, 0x44, 0x46, 0x44, 0x46, 0x00, 0x00, 0x21, 0x48, 0x3d, 0x10, 0xff, 0xfe, 0x08, 0x24, 0x08, 0x40, 0x3f, 0x00, 0x4b, 0xf8, 0x4b, 0xf8, 0x00, 0x00, 0xe4, 0x44, 0xff, 0xfe, 0x06, 0x88, 0xc0, 0x06, 0x08, 0x40, 0x4a, 0x40, 0x55, 0x54, 0x49, 0x20, 0x00, 0x00, 0x94, 0x44, 0x91, 0x10, 0x94, 0x44, 0x91, 0x10, 0x44, 0x44, 0x44, 0x44, 0x91, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x1d, 0x70, 0x13, 0xf0, 0x13, 0xf0, 0x08, 0x44, 0x25, 0xfe, 0x51, 0x04, 0x51, 0x04, 0x00, 0x00, 0xa5, 0xfc, 0x42, 0x44, 0x08, 0x44, 0x08, 0xa0, 0x10, 0x14, 0x19, 0x04, 0x13, 0xf8, 0x13, 0xf8, 0x00, 0x00, 0x01, 0x20, 0x65, 0xfc, 0x01, 0x00, 0xff, 0x24, 0x08, 0x44, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0x00, 0x24, 0x44, 0x01, 0x00, 0x7c, 0x88, 0x00, 0x00, 0x08, 0x44, 0x4c, 0x40, 0x55, 0x54, 0x49, 0x20, 0x00, 0x00, 0x95, 0xf4, 0x92, 0x08, 0x95, 0xf4, 0x92, 0x08, 0x15, 0xf4, 0x15, 0xf4, 0x92, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x80, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x0a, 0x44, 0x24, 0x20, 0x91, 0xfc, 0x91, 0xfc, 0x00, 0x00, 0x24, 0x20, 0x7e, 0x24, 0x0a, 0x44, 0x11, 0x20, 0x10, 0x18, 0x31, 0xfc, 0x12, 0x08, 0x12, 0x08, 0x00, 0x00, 0x01, 0x00, 0x65, 0x44, 0x02, 0x80, 0x10, 0x24, 0x0a, 0x44, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0x00, 0x24, 0x44, 0x02, 0x80, 0x40, 0x88, 0x3e, 0xf8, 0x0a, 0x44, 0x48, 0x40, 0x57, 0xd4, 0x49, 0x20, 0x00, 0x00, 0x94, 0x44, 0x95, 0xf6, 0x94, 0x44, 0x95, 0xf6, 0x14, 0x44, 0x14, 0x44, 0x95, 0xf6, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x80, 0x3f, 0xf8, 0x20, 0x88, 0x20, 0x88, 0x0c, 0x48, 0x48, 0x20, 0x11, 0x04, 0x11, 0x04, 0x00, 0x00, 0x3c, 0x20, 0x42, 0x24, 0x0c, 0x48, 0x11, 0xfc, 0x7f, 0xf0, 0xd1, 0x24, 0x23, 0xf8, 0x23, 0xf8, 0x00, 0x00, 0x7f, 0xfc, 0xa5, 0x44, 0x02, 0x80, 0x10, 0x24, 0x0c, 0x48, 0xff, 0xfe, 0x4b, 0xf8, 0x4b, 0xf8, 0x00, 0x00, 0x27, 0xfc, 0x02, 0x80, 0x40, 0x50, 0x22, 0x88, 0x0c, 0x48, 0x48, 0xa0, 0x51, 0x14, 0x49, 0x10, 0x00, 0x00, 0x95, 0xf4, 0x90, 0x00, 0x95, 0xf4, 0x90, 0x00, 0x25, 0xf4, 0x25, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x04, 0x40, 0x21, 0x08, 0xe1, 0x50, 0xe1, 0x50, 0x18, 0x30, 0x28, 0x20, 0x11, 0x04, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x42, 0x04, 0x18, 0x30, 0xe0, 0x20, 0x00, 0x50, 0x10, 0x20, 0xe2, 0x08, 0xe2, 0x08, 0x18, 0x00, 0x01, 0x00, 0x25, 0x28, 0x04, 0x40, 0x20, 0x24, 0x18, 0x30, 0x01, 0x00, 0x7a, 0x08, 0x7a, 0x08, 0x00, 0x00, 0x20, 0x84, 0x04, 0x40, 0x40, 0x50, 0x22, 0x88, 0x18, 0x30, 0x78, 0xa0, 0x73, 0x94, 0x79, 0x10, 0x00, 0x00, 0xf5, 0x14, 0xf0, 0x00, 0xf5, 0x14, 0xf0, 0x00, 0xe5, 0x14, 0xe5, 0x14, 0xf0, 0x00, 0x18, 0x00, 0x00, 0x00,
    0x04, 0x40, 0x21, 0x08, 0x23, 0x20, 0x23, 0x20, 0x68, 0x22, 0x10, 0x20, 0x11, 0x04, 0x11, 0x04, 0x30, 0x00, 0x7f, 0xf8, 0x42, 0x04, 0x68, 0x22, 0x20, 0x20, 0x00, 0x90, 0x13, 0xfe, 0x23, 0xf8, 0x23, 0xf8, 0x24, 0x00, 0x02, 0x80, 0x25, 0x28, 0x04, 0x40, 0x44, 0x44, 0x68, 0x22, 0x02, 0x80, 0x4a, 0x08, 0x4a, 0x08, 0x30, 0x00, 0x21, 0x00, 0x04, 0x40, 0x44, 0x20, 0x22, 0x88, 0x68, 0x22, 0x49, 0x10, 0x55, 0x54, 0x4a, 0x10, 0x30, 0x00, 0x95, 0x14, 0x93, 0xf8, 0x95, 0x14, 0x93, 0xf8, 0x25, 0x14, 0x25, 0x14, 0x93, 0xf8, 0x24, 0x00, 0x00, 0x00,
    0x08, 0x20, 0x3f, 0xf8, 0x25, 0x10, 0x25, 0x10, 0x08, 0x52, 0x28, 0x20, 0x11, 0x04, 0x11, 0x04, 0x30, 0x00, 0x04, 0x08, 0x42, 0x04, 0x08, 0x52, 0x27, 0xfe, 0x03, 0x10, 0x10, 0x20, 0x22, 0x08, 0x22, 0x08, 0x24, 0x00, 0x04, 0x40, 0x3d, 0x10, 0x08, 0x20, 0xfe, 0x44, 0x08, 0x52, 0x04, 0x40, 0x02, 0x08, 0x02, 0x08, 0x30, 0x00, 0x22, 0x00, 0x08, 0x20, 0x58, 0x50, 0x3e, 0xa8, 0x08, 0x52, 0x01, 0x10, 0x09, 0x44, 0x02, 0x08, 0x30, 0x00, 0x05, 0xf4, 0x02, 0x08, 0x05, 0xf4, 0x02, 0x08, 0x25, 0xf4, 0x25, 0xf4, 0x02, 0x08, 0x24, 0x00, 0x00, 0x00,
    0x10, 0x10, 0x21, 0x08, 0x29, 0x48, 0x29, 0x48, 0x08, 0x8a, 0x44, 0x20, 0x11, 0x04, 0x11, 0x04, 0x10, 0x00, 0x08, 0x08, 0x7e, 0x04, 0x08, 0x8a, 0x20, 0x20, 0x1c, 0x10, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x18, 0x00, 0x08, 0x20, 0x26, 0x28, 0x10, 0x10, 0x42, 0x84, 0x08, 0x8a, 0x08, 0x20, 0x02, 0x08, 0x02, 0x08, 0x10, 0x00, 0x54, 0x00, 0x10, 0x10, 0x60, 0x88, 0x22, 0x90, 0x08, 0x8a, 0x02, 0x08, 0x01, 0x04, 0x04, 0x08, 0x10, 0x00, 0x04, 0x04, 0x02, 0x08, 0x04, 0x04, 0x02, 0x08, 0x24, 0x04, 0x24, 0x04, 0x02, 0x08, 0x18, 0x00, 0x00, 0x00,
    0x20, 0x08, 0x21, 0x08, 0x21, 0x86, 0x21, 0x86, 0x2b, 0x06, 0x84, 0xa0, 0x11, 0xfc, 0x11, 0xfc, 0x20, 0x00, 0x10, 0x50, 0x42, 0x28, 0x2b, 0x06, 0x20, 0x20, 0xe0, 0x50, 0x50, 0x20, 0x2f, 0xfe, 0x2f, 0xfe, 0x00, 0x00, 0x30, 0x18, 0x22, 0x44, 0x20, 0x08, 0x01, 0x28, 0x2b, 0x06, 0x30, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x20, 0x00, 0x8f, 0xfe, 0x20, 0x08, 0x41, 0x04, 0x00, 0x80, 0x2b, 0x06, 0x04, 0x04, 0x01, 0x14, 0x08, 0x04, 0x20, 0x00, 0x04, 0x14, 0x03, 0xf8, 0x04, 0x14, 0x03, 0xf8, 0x24, 0x14, 0x24, 0x14, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00,
    0xc0, 0x06, 0x3f, 0xf8, 0x01, 0x00, 0x01, 0x00, 0x10, 0x02, 0x00, 0x40, 0x11, 0x04, 0x11, 0x04, 0x00, 0x00, 0x60, 0x20, 0x00, 0x10, 0x10, 0x02, 0x00, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x04, 0x82, 0xc0, 0x06, 0x02, 0x10, 0x10, 0x02, 0xc0, 0x06, 0x02, 0x08, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x02, 0x02, 0x00, 0x80, 0x10, 0x02, 0x08, 0x02, 0x01, 0x08, 0x10, 0x02, 0x00, 0x00, 0x04, 0x08, 0x02, 0x08, 0x04, 0x08, 0x02, 0x08, 0x04, 0x08, 0x04, 0x08, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00
};

static const unsigned char bitmap_alph_nums[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3E, 0xF8, 0xFC,
    0xFC, 0x3C, 0xE7, 0x7C, 0x3E, 0xEE, 0xE0, 0xEE, 0xC7, 0x38, 0xFC, 0x38, 0xFC, 0x3E, 0xFE,
    0xE7, 0xE7, 0xD6, 0xE7, 0xEE, 0x7E, 0x18, 0x08, 0x3C, 0x3C, 0x04, 0x7E, 0x18, 0x7E, 0x3C,
    0xC0, 0x06, 0x00, 0x0C, 0xC0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xC0, 0x06, 0x00, 0x1E, 0xC0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7E, 0xFC, 0xFE,
    0xFE, 0x7C, 0xE7, 0x7C, 0x3E, 0xEE, 0xE0, 0xEE, 0xE7, 0x7C, 0xFE, 0x7C, 0xFE, 0x7E, 0xFE,
    0xE7, 0xE7, 0xD6, 0xE7, 0xEE, 0xFE, 0x3C, 0x38, 0x7E, 0x7E, 0x0C, 0x7E, 0x3C, 0x7E, 0x7E,
    0x40, 0x02, 0x00, 0x12, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x40, 0x02, 0x00, 0x12, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x42, 0x46, 0x4A,
    0x4A, 0x44, 0x42, 0x10, 0x08, 0x4C, 0x40, 0x6C, 0x62, 0xC6, 0x42, 0xC6, 0x42, 0x42, 0x92,
    0x42, 0x42, 0x54, 0x66, 0x44, 0x84, 0x66, 0x38, 0x42, 0x42, 0x0C, 0x40, 0x64, 0x46, 0x42,
    0x58, 0x3E, 0x7C, 0x7C, 0x3E, 0x5C, 0x70, 0x1C, 0x4E, 0x10, 0xFE, 0xDC, 0x3C, 0xD8, 0x1A,
    0xEE, 0x3E, 0x7C, 0xC6, 0xEE, 0xDB, 0x76, 0xE7, 0x7E, 0x28, 0x7C, 0x80, 0x42, 0x78, 0x78,
    0x80, 0x42, 0x10, 0x08, 0x70, 0x40, 0x6C, 0x52, 0x82, 0x42, 0x82, 0x7E, 0x60, 0x10, 0x42,
    0x64, 0x54, 0x3C, 0x28, 0x08, 0x42, 0x08, 0x06, 0x34, 0x78, 0x5C, 0x0C, 0x66, 0x42, 0x42,
    0x7C, 0x7E, 0x7C, 0x7E, 0x7C, 0x7E, 0x70, 0x1C, 0x4E, 0x10, 0xFF, 0xFE, 0x7E, 0xFC, 0x3E,
    0xFE, 0x7E, 0x7C, 0xC6, 0xEE, 0xDB, 0x76, 0xE7, 0x7E, 0x2C, 0x7C, 0x80, 0x42, 0x78, 0x78,
    0x80, 0x7E, 0x10, 0x08, 0x70, 0x40, 0x6C, 0x5A, 0x82, 0x7E, 0x82, 0x7C, 0x38, 0x10, 0x42,
    0x24, 0x54, 0x18, 0x38, 0x18, 0x42, 0x08, 0x06, 0x1C, 0x24, 0x7C, 0x08, 0x3C, 0x46, 0x7E,
    0x6C, 0x66, 0x62, 0x42, 0x42, 0x10, 0x44, 0x62, 0x10, 0x04, 0x58, 0x10, 0x49, 0x62, 0x42,
    0x66, 0x66, 0x32, 0x42, 0x10, 0x42, 0x6C, 0xCB, 0x76, 0x66, 0x4C, 0x3C, 0x46, 0x42, 0x80,
    0x42, 0x48, 0x48, 0x8E, 0x7E, 0x10, 0x08, 0x58, 0x40, 0x54, 0x4A, 0x82, 0x7C, 0x82, 0x48,
    0x1C, 0x10, 0x42, 0x2C, 0x54, 0x18, 0x10, 0x30, 0x42, 0x08, 0x0C, 0x1C, 0x64, 0x46, 0x18,
    0x3C, 0x42, 0x40, 0x42, 0x7E, 0x10, 0x78, 0x42, 0x10, 0x04, 0x70, 0x10, 0x49, 0x42, 0x42,
    0x42, 0x42, 0x20, 0x7C, 0x10, 0x42, 0x28, 0x5E, 0x18, 0x3C, 0x10, 0x46, 0x42, 0x80, 0x42,
    0x48, 0x48, 0x8E, 0x42, 0x10, 0x08, 0x48, 0x40, 0x54, 0x4E, 0x82, 0x40, 0xB2, 0x44, 0x42,
    0x10, 0x42, 0x38, 0x28, 0x24, 0x10, 0x62, 0x42, 0x08, 0x30, 0x42, 0x7F, 0x42, 0x42, 0x10,
    0x6C, 0x66, 0x62, 0x46, 0x42, 0x10, 0x7C, 0x42, 0x10, 0x04, 0x4C, 0x10, 0x49, 0x42, 0x42,
    0x42, 0x42, 0x20, 0x3E, 0x10, 0x46, 0x38, 0x74, 0x3C, 0x18, 0x32, 0x42, 0x46, 0x46, 0x46,
    0x42, 0x40, 0x44, 0x42, 0x10, 0x08, 0x44, 0x42, 0x54, 0x46, 0xC6, 0x40, 0xFE, 0x46, 0x42,
    0x10, 0x42, 0x18, 0x28, 0x66, 0x10, 0x42, 0x66, 0x08, 0x62, 0x42, 0x04, 0x46, 0x62, 0x10,
    0x7E, 0x7C, 0x3E, 0x7F, 0x7E, 0x7C, 0x7E, 0xE7, 0x7C, 0x04, 0xEE, 0x7C, 0xED, 0xE7, 0x7E,
    0x7C, 0x3E, 0xF8, 0x7E, 0x1E, 0x7F, 0x10, 0x24, 0x6E, 0x18, 0x7E, 0xE7, 0xFC, 0x7C, 0xFC,
    0xFE, 0xE0, 0x7C, 0xE7, 0x7C, 0x08, 0xEE, 0xFE, 0xD6, 0xE6, 0x7C, 0xE0, 0x7C, 0xE3, 0x7E,
    0x38, 0x7E, 0x10, 0x28, 0xE7, 0x38, 0xFE, 0x3C, 0x3E, 0x7E, 0x7E, 0x1F, 0x7C, 0x3E, 0x10,
    0x36, 0x58, 0x1C, 0x3B, 0x3C, 0x7C, 0x42, 0xE7, 0x7C, 0x44, 0xEE, 0x7C, 0xED, 0xE7, 0x3C,
    0x58, 0x1A, 0xF8, 0x7C, 0x0C, 0x3B, 0x10, 0x24, 0x6E, 0x10, 0x7E, 0xE7, 0xF8, 0x38, 0xF8,
    0xFC, 0xE0, 0x38, 0xE7, 0x7C, 0x88, 0xEE, 0xFE, 0xD6, 0xE2, 0x38, 0xE0, 0x3E, 0xE3, 0x7C,
    0x38, 0x3C, 0x10, 0x28, 0xE7, 0x38, 0xFC, 0x18, 0x3E, 0x7E, 0x3C, 0x1F, 0x38, 0x1C, 0x10,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00
};

int scrollOffset = 0;


// 安全版XY映射
uint16_t XY(uint8_t x, uint8_t y) {
  x = constrain(x, 0, MATRIX_WIDTH-1);
  y = constrain(y, 0, MATRIX_HEIGHT-1);
  
  uint16_t index;
  if(y < NUM_LOWER_ROWS) {
    if(y % 2 == 0) {
      index = y * MATRIX_WIDTH + x;
    } else {
      index = (y + 1) * MATRIX_WIDTH - 1 - x;
    }
  } else {
    if(y % 2 == 0) {
      index = (y-NUM_LOWER_ROWS) * MATRIX_WIDTH + x + NUM_LEDS_LOWER;
    } else {
      index = (y-NUM_LOWER_ROWS + 1) * MATRIX_WIDTH - 1 - x + NUM_LEDS_LOWER;
    }
  }

  return constrain(index, 0, NUM_LEDS-1);
}

void setup() {
  FastLED.addLeds<WS2815, DATA_PIN_LOWER, GRB>(leds, NUM_LEDS_LOWER);
  FastLED.addLeds<WS2815, DATA_PIN_UPPER, GRB>(leds+NUM_LEDS_LOWER, NUM_LEDS_UPPER);
  FastLED.setBrightness(50);
}

void loop() {
  static unsigned long lastUpdate = 0;
  if (millis() - lastUpdate > 60) {
    lastUpdate = millis();
   
    fill_solid(leds, NUM_LEDS, BACKGROUND_COLOR);

    for (int x = 0; x < MATRIX_WIDTH; x++) {
      int bitmapX = (scrollOffset + x) % BITMAP_WIDTH;
      for (int y = 0; y < HAN_BITMAP_HEIGHT; y++) {
        if ((textBitmap[BITMAP_INDEX(bitmapX,y)] << BITMMAP_POSITION(bitmapX)) &0x80) {
          int ledIndex = XY(x, y);
          if (ledIndex != -1) leds[ledIndex + MATRIX_WIDTH*HAN_START_ROW] = TEXT_COLOR;
        }
      }
    }

    FastLED.show();
    scrollOffset = (scrollOffset + 1) % BITMAP_WIDTH;
  }
}

使用特权

评论回复
板凳
keer_zu|  楼主 | 2025-5-27 08:27 | 只看该作者
更多显示效果:

#include <stdint.h>
//#include <math.h>
#include "led_functions.h"

#define ROTATION_SPEED 0.5  // 旋转速度(弧度/秒)


// 定义主色和辅助色的HSV范围(H:0-255对应0-360度)
const uint8_t MAIN_HUE = 0;     // 主色Hue(例如红色)
const uint8_t ACCENT_HUE = 32;  // 辅助色Hue(例如橙色)
const uint8_t HUE_RANGE = 16;   // 主辅色之间的过渡范围

// 动态参数
uint8_t baseBrightness = 128;   // 基础亮度
uint8_t brightnessJitter = 50;  // 亮度波动范围
uint8_t saturation = 200;       // 饱和度(0-255)
uint8_t spreadRatio = 50;       // 主色占比(%)

//===================== wave ====================================
#define MAX_WAVES      6  // 增加最大波环数量


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;

void spawnWave(uint8_t gen);
//===============================================================

// 颜色定义
const CRGB coreColor1 = CRGB(0x66, 0x99, 0xFF);  // #6699FF
const CRGB coreColor2 = CRGB(0xAE, 0xEE, 0xEE);  // #AEEEEE
const CRGB bgColor = CRGB(0x00, 0x33, 0x66);     // #003366
CRGB mainColor = CRGB(0x00, 0x88, 0xFF);         // 主过渡色

float distanceFromCenter(uint8_t x, uint8_t y);
// 随机种子初始化
unsigned long seed = 0;
uint8_t randomness = 0;   // 随机种子

void random_init()
{
  //randomSeed(analogRead(0)); // 使用模拟输入初始化随机种子
  //seed = random(10000); // 创建基础随机种子
  //randomness = random(64);   // 创建基础随机层
  //random16_set_seed(esp_random()); // 使用ESP32硬件随机数
  
  //==================== 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.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;

  //================================================
}

//example
#if 1
void show_rainbow()
{
  static uint8_t hue = 0;
  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 根据坐标生成色相和明度波浪
      uint8_t ledHue = hue + x * 10 + y * 5;
       uint8_t targetHue = map(ledHue, -32768, 32767, 96, 225);
      uint8_t brightness = sin8(x * 20 + y * 20 + hue);
      leds[XY(x, y)] = CHSV(targetHue, 255, brightness);
    }
  }
  FastLED.show();
  hue += 2;
  delay(20);
}
#else
void show_rainbow() {
  static uint8_t wavePhase = 0;  // 波形相位控制

  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 生成动态波形色相(核心逻辑)
      uint8_t waveHue = sin8(wavePhase + x * 15 + y * 8);  // 空间波形叠加
      uint8_t targetHue = map(waveHue, 0, 255, 150, 255);  // 映射到目标范围

      // 亮度波浪(与色相不同步增强立体感)
      uint8_t brightness = sin8(x * 30 + y * 20 + wavePhase * 2);

      leds[XY(x, y)] = CHSV(targetHue, 255, brightness);
    }
  }

  FastLED.show();
  wavePhase += 1;  // 控制波形运动速度
  delay(20);
}

void show_rainbow() {
  static uint16_t timeBase = 0;
  static uint8_t xNoise[MATRIX_WIDTH];
  static uint8_t yNoise[MATRIX_HEIGHT];
  
  // 亮度平滑滤波器
  static uint8_t lastBrightness[MATRIX_WIDTH][MATRIX_HEIGHT] = {{0}};

  // 噪声混合参数(20%更新强度)
  #define NOISE_BLEND_AMOUNT 51  // 近似20% (51/255 ≈ 0.2)

  EVERY_N_MILLISECONDS(50) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      xNoise[x] = xNoise[x] + (random8() - xNoise[x]) * NOISE_BLEND_AMOUNT / 255;
    }
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      yNoise[y] = yNoise[y] + (random8() - yNoise[y]) * NOISE_BLEND_AMOUNT / 255;
    }
  }

  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 获取当前噪声值
      uint8_t currentXNoise = xNoise[x];
      uint8_t currentYNoise = yNoise[y];

      // 动态色相生成(保持120-255范围)
      uint8_t baseHue = map(sin8(timeBase/3 + x*8), 0, 255, 120, 200);
      uint8_t finalHue = (baseHue +
                         map(currentXNoise, 0, 255, -15, 15) +
                         map(currentYNoise, 0, 255, -10, 10)) % 136 + 120;

      // 亮度处理(核心修改部分)
      uint8_t rawBrightness = inoise8(x*30, y*30, timeBase);  // 降低噪声频率
      
      // 映射到40-200范围并添加平滑滤波
      uint8_t targetBrightness = map(rawBrightness, 0, 255, 40, 200);
      uint8_t brightness = (targetBrightness * 3 + lastBrightness[x][y] * 7) / 10; // 70%历史值权重
      lastBrightness[x][y] = brightness;

      leds[XY(x, y)] = CHSV(finalHue, 240, brightness);
    }
  }

  FastLED.show();
  timeBase += 2;  // 降低整体变化速度
  delay(20);
}
#endif

void random_vision()
{
  // 随机生成动态参数
  uint8_t currentHue = random(MAIN_HUE - HUE_RANGE, MAIN_HUE + HUE_RANGE);
  uint8_t currentBrightness = baseBrightness + random(-brightnessJitter, brightnessJitter);
  uint8_t currentSpread = random(0, 100); // 用于范围控制

  // 更新所有LED颜色
  for (int i = 0; i < NUM_LEDS; i++) {
    // 根据spreadRatio决定使用主色还是辅助色
    uint8_t hue = (currentSpread < spreadRatio) ?
                  random(currentHue - 5, currentHue + 5) :  // 主色微抖动
                  random(ACCENT_HUE - 5, ACCENT_HUE + 5);    // 辅助色微抖动

    // 生成最终颜色
    leds[i] = CHSV(
      hue,
      saturation,
      constrain(currentBrightness + random(-20, 20), 0, 255) // 亮度叠加噪声
    );
  }

  FastLED.show();
  delay(50 + random(0, 100)); // 随机刷新间隔
}

void smooth_vision()
{
    uint8_t currentBrightness = baseBrightness + random(-brightnessJitter, brightnessJitter);
    static CRGBPalette16 currentPalette;
  if (random(0, 100) > 90) { // 10%概率切换色板
    currentPalette = CRGBPalette16(
      CHSV(random(MAIN_HUE - HUE_RANGE, MAIN_HUE + HUE_RANGE), 255, 255),
      CHSV(random(ACCENT_HUE - HUE_RANGE, ACCENT_HUE + HUE_RANGE), 255, 255)
    );
  }
  
  // 使用色板插值
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = ColorFromPalette(
      currentPalette,
      random8(), // 随机位置采样色板
      currentBrightness,
      LINEARBLEND
    );
  }
  FastLED.show();
  delay(30);
}

#if 1
void optim_vision()
{
  static uint8_t breathPhase = 0;
  static uint8_t rotationPhase = 0;
  static uint8_t globalRandom = 0;
  
  breathPhase += 1;
  rotationPhase += 2;
  globalRandom = (globalRandom + 1) % 256; // 缓慢变化的随机种子
  
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      int index = getLEDIndex(x, y);
      CRGB& pixel = leds[index];
      
      // 中心点计算(蛇形坐标)
      int centerX = MATRIX_WIDTH / 2;
      int centerY = MATRIX_HEIGHT / 2;
      float dx = abs(x - centerX);
      float dy = abs(y - centerY);
      float distance = sqrt(dx*dx + dy*dy);
      
      // 带随机性的呼吸效果
      float breathVal = (sin(breathPhase * 0.1 + (random(3)-1)*0.5) + 1) * 64;
      breathVal += (random(5) - 2) * 0.5; // 微小随机波动
      
      uint8_t baseHue = 240; // 主色调深蓝
      uint8_t hueVariance = 10; // 色调随机范围
      
      // 主色调背景(带柔和渐变)
      if (distance > 10) {
        pixel = CHSV(baseHue + random(-hueVariance, hueVariance),
                    80 + random(10),
                    breathVal / 2);
      } else {
        // 紫色光晕(等级1限制,柔和混合)
        float ratio = constrain(distance / 10, 0, 1);
        uint8_t h1 = baseHue;
        uint8_t s1 = 100;
        uint8_t v1 = breathVal;
        
        uint8_t h2 = 255;
        uint8_t s2 = 20 + random(5);
        uint8_t v2 = breathVal * 2 + random(3);
        
        CRGB color1 = CHSV(h1, s1, v1);
        CRGB color2 = CHSV(h2, s2, v2);
        
        // 使用立方贝塞尔曲线实现平滑过渡
        float t = pow(ratio, 0.5);
        CRGB blended = blend(color1, color2, t*t*(3-2*t));
        
        // 添加随机噪声纹理
        float noiseVal = (inoise8(x * 3 + seed, y * 3 + seed + rotationPhase) - 128) / 256.0;
        blended.g += noiseVal * 15;
        blended.b += noiseVal * 10;
        
        pixel = blended;
        
        // 动态波纹(带随机相位)
        float time = (millis() / 1000.0) + rotationPhase * 0.05 + (random(5)-2)*0.1;
        float wave = sin((distance + time) * 0.5 + (random(10)-5)*0.05) * 2;
        pixel.blue += wave;
        pixel.green += wave / 2;
        
        // 结构纹理(模拟波纹)
        float detail = sin((x + y + time) * 3 + (random(3)-1)*0.2) * 5;
        pixel.red += detail;
      }
    }
  }
  
  FastLED.show();
  delay(random(20, 40)); // 随机延时增加自然感
}
#endif

void random_rainbow()
{
    static uint8_t hue = 180; // 初始色相设定在青色区间
  static uint8_t randomness = 0; // 随机种子控制变量
  
  // 动态调整随机种子
  randomness = (randomness + 1) % 64;
  
  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 计算基础色相
      uint8_t baseHue = hue + x * 10 + y * 5;
      
      // 添加可控随机偏移(±3范围内)
      uint8_t hueOffset = random(61) - 30; // 生成-30到+29的随机数
      uint8_t ledHue = baseHue + hueOffset;
      
      // 强制限制在青蓝紫区间(180-300度)
      ledHue = ledHue % 360;
      if (ledHue < 180) ledHue += 180;
      else if (ledHue > 300) ledHue -= 120;
      
      // 生成动态亮度(带波浪噪声)
      uint8_t brightness = sin8(x * 20 + y * 20 + hue + randomness);
      brightness = qadd8(brightness, random(32)); // 最多叠加31的随机亮度
      
      // 创建柔和过渡的色彩
      CRGB color = CHSV(ledHue, 255, brightness);
      color.fadeToBlackBy(255 - (random(64) + 192)); // 随机透明度
      
      leds[XY(x, y)] = color;
    }
  }
  
  FastLED.show();
  
  // 随机呼吸式延迟
  uint8_t delayTime = random(15, 45);
  delay(delayTime);
  
  // 更新主色相(缓慢变化)
  hue += 1;
  if (hue >= 360) hue -= 360;
}
// 中心点坐标(蛇形布局需调整)
int centerX = MATRIX_WIDTH / 2;
int centerY = MATRIX_HEIGHT / 2;

// 动态参数
uint8_t hueBase = 180;    // 初始色相(青色)
uint8_t flowSpeed = 1;    // 流动速度(1-5)

void centor_rainbow()
{
  static uint8_t time = 0;
  
  // 时间推进与随机扰动
  time++;
  randomness = (randomness + 1) % 64;
  
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      int index = y * MATRIX_WIDTH + x;
      CRGB& pixel = leds[index];
      
      // 蛇形布局修正(如需平面布局可注释)
      if (y % 2 != 0) x = MATRIX_WIDTH - 1 - x;
      
      // 计算到中心点的距离
      float dx = x - centerX;
      float dy = y - centerY;
      float distance = sqrt(dx*dx + dy*dy);
      
      // 生成基础半径和随机涨落
      float baseRadius = (time * flowSpeed) / 2.0;
      float radiusFluctuation = (random(21) - 10) * 0.5; // ±5范围随机
      float currentRadius = baseRadius + radiusFluctuation;
      
      // 判断是否在扩散范围内
      if (distance <= currentRadius) {
        // 计算色相(强制青蓝紫范围)
        float hueRange = 120; // 180-300度
        float hueOffset = (distance / currentRadius) * hueRange;
        uint8_t hue = hueBase + hueOffset;
        hue = constrain(hue, 180, 300);
        
        // 添加噪声纹理
        uint8_t noiseVal = inoise8(x * 4 + randomness, y * 4 + time + randomness);
        hue += (noiseVal - 128) / 64; // ±0.5色相偏移
        
        // 生成颜色(柔和渐变)
        uint8_t saturation = 255;
        uint8_t value = 255 - (distance / currentRadius * 255);
        
        CRGB color = CHSV(hue, saturation, value);
        pixel = color;
      } else {
        pixel = CRGB::Black;
      }
    }
  }
  
  FastLED.show();
  
  // 动态延迟控制
  uint8_t delayTime = random(10, 30) + (randomness % 5);
  delay(delayTime);
}


const CRGB palette[] = {
  CRGB(0x2A, 0x5B, 0x8C), // 深蓝
  CRGB(0x3E, 0xB7, 0xA0), // 青绿
  CRGB(0x80, 0x00, 0x80), // 紫
  CRGB(0xFF, 0xC0, 0xCB)  // 粉
};

void renderGradient(int style) {
  switch (style) {
    case 0: // 对角线线性渐变(第1张图)
      for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++) {
          float ratio = (x + y) / (float)(MATRIX_WIDTH + MATRIX_HEIGHT - 2);
          leds[y * MATRIX_WIDTH + x] = blend(palette[0], palette[2], ratio * 255);
        }
      }
      break;
    case 1: // 流体渐变(第5张图)
      static uint16_t z;
      for (int i = 0; i < NUM_LEDS; i++) {
        uint8_t noise = inoise8(i % MATRIX_WIDTH * 30, i / MATRIX_WIDTH * 30, z);
        leds[i] = ColorFromPalette(CRGBPalette16(palette), noise);
      }
      z += 10;
      break;
  }
  FastLED.show();
}

void test_vision()
{
   for (int i = 0; i < 4; i++) { // 循环切换4种渐变
    renderGradient(i % 2);
    delay(20);
  }
}

#if 1
// 马尔科夫链状态结构体(修正字段类型)
struct MarkovState {
  uint8_t baseHue;     // 改为8位存储
  uint8_t speed;       // 速度范围1-5
  int8_t direction;    // 风向
  uint8_t intensity;   // 强度范围
};

// 初始化状态(调整参数)
MarkovState currentState = {200, 3, 1, 150}; // 提高初始baseHue

// 简化转移概率矩阵
const uint8_t transitionProb[4][4] = {
  {80, 10, 5, 5},   
  {15, 70, 10, 5},  
  {10, 5, 80, 5},  
  {5, 5, 5, 85}   
};

// 噪声参数
uint16_t z = 0;
const uint8_t scale = 30;
const uint8_t blurAmount = 64;


// 马尔科夫状态转移实现
void applyMarkovTransition() {
  uint8_t randVal = random8();
  uint8_t probSum = 0;
  
  // 选择要改变的状态维度
  uint8_t targetDim = 0;
  for(; targetDim<4; targetDim++) {
    probSum += transitionProb[targetDim][targetDim];
    if(randVal < probSum) break;
  }
  
  // 执行状态转移(有限差分法)
  switch(targetDim) {
    case 0: // 基础色调变化
      currentState.baseHue += random8(3) - 1; // ±1微调
      currentState.baseHue = constrain(currentState.baseHue, 180, 255);
      break;
      
    case 1: // 速度变化
      currentState.speed = constrain(
        currentState.speed + random8(3) - 1, 1, 5);
      break;
      
    case 2: // 方向变化
      if(random8() < 30) currentState.direction *= -1;
      break;
      
    case 3: // 强度变化
      currentState.intensity = constrain(
        currentState.intensity + random8(21) - 10, 100, 200);
      break;
  }
}

// 基于状态的图案生成
void generateWindPattern() {
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
      uint8_t noise = inoise8(
        (x * scale) / 2 + (currentState.direction * z),
        y * scale + z/2,
        currentState.intensity * 10
      );
      
      // 修正色调计算(添加循环处理)
      uint8_t hue = currentState.baseHue + map(noise, 0,255, -20,20);
      hue = (hue < 180) ? hue + 75 : hue; // 确保在180-255范围
      
      // 修正亮度计算(移除错误处理)
      uint8_t val = map(noise, 50, 205, 30, 230);
      val = constrain(val, 30, 230); // 硬约束
      
      leds[XY(x,y)] = CHSV(hue, 230, val);
    }
  }
  
  blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, blurAmount);
  z += 2;//currentState.speed;   //速度均匀
}



void wind_vision() {
  static uint32_t lastUpdate = 0;
  static uint8_t hueShift = 0;

  if(millis() - lastUpdate > 50) { // 降低更新频率
    lastUpdate = millis();
   
    // 马尔科夫状态转移
    applyMarkovTransition();
   
    // 生成动态风场
    generateWindPattern();
   
    FastLED.show();
    delay(10);
  }
}
#else



// 马尔科夫链增强平滑版本
struct MarkovState {
  uint8_t baseHue;     // 当前色相
  uint8_t targetHue;   // 目标色相(新增)
  uint8_t speed;
  uint8_t targetSpeed; // 新增目标速度
  int8_t direction;
  float directionF;    // 新增浮点方向(用于平滑过渡)
  uint8_t intensity;
};

MarkovState currentState = {200, 200, 3, 3, 1, 1.0f, 150};
const uint8_t transitionProb[4][4] = {
  {90, 5, 3, 2},     // 提高保持色相的概率
  {10, 85, 3, 2},    // 降低速度变化频率
  {5, 5, 88, 2},     // 增强方向稳定性
  {3, 2, 2, 93}      // 提高强度保持率
};

uint32_t z = 0;       // 改为32位防溢出
const float DIRECTION_TRANSITION = 0.1f; // 方向过渡系数

void applyMarkovTransition() {
  static uint32_t lastChange = 0;
  const uint32_t CHANGE_INTERVAL = 3000; // 延长状态变化间隔
  
  if(millis() - lastChange < CHANGE_INTERVAL) return;
  lastChange = millis();

  uint8_t randVal = random8();
  uint8_t probSum = 0;
  uint8_t targetDim = 0;
  
  // 概率累计方式优化
  while(targetDim < 4 && randVal > (probSum += transitionProb[targetDim][targetDim])) {
    targetDim++;
  }

  // 有限渐变状态转移
  switch(targetDim) {
    case 0: // 色相渐变
      currentState.targetHue = constrain(currentState.baseHue + random8(-8, 9), 180, 255);
      break;
      
    case 1: // 速度渐变
      currentState.targetSpeed = constrain(currentState.speed + random8(-1, 2), 1, 5);
      break;
      
    case 2: // 方向平滑过渡
      currentState.directionF = -currentState.directionF; // 缓慢反转
      break;
      
    case 3: // 强度渐变
      currentState.intensity = constrain(currentState.intensity + random8(-8, 9), 100, 200);
      break;
  }
}

void smoothUpdateStates() {
  // 色相线性插值
  currentState.baseHue = lerp8by8(currentState.baseHue, currentState.targetHue, 10);
  
  // 速度指数平滑
  currentState.speed = (currentState.speed * 7 + currentState.targetSpeed * 1) / 8;
  
  // 方向浮点过渡
  currentState.directionF += (currentState.direction - currentState.directionF) * DIRECTION_TRANSITION;
}

void generateWindPattern() {
  const float dirFactor = currentState.directionF; // 使用浮点方向因子


  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
      // 改进的噪声参数(增加Z轴细分)
      uint8_t noise = inoise8(
        (x * 25) + (z * dirFactor * 0.7f),
        y * 35 + z * 0.3f,
        currentState.intensity * 8 + (z >> 6)
      );
      
      // 循环色相映射(替代硬约束)
      uint8_t hue = currentState.baseHue + map(noise, 0,255, -15,15);
      hue = 180 + ((hue - 180) % 76); // 180-255循环
      
      // 亮度S曲线处理
      uint8_t val = cubicwave8(noise);
      val = map(val, 30, 225, 50, 220);  // 压缩两端
      
      leds[XY(x,y)] = CHSV(hue, 235, val);
    }
  }
  
   // 使用标准二维模糊 + 逐行模糊替代方案
  blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, 64);
  
  // 手动实现行模糊
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    CRGB* rowStart = &leds[XY(0, y)];
    blur1d(rowStart, MATRIX_WIDTH, 32);
  }
  
  z += currentState.speed;
}

void wind_vision() {
  static uint32_t lastUpdate = 0;
  
  if(millis() - lastUpdate > 33) { // 30FPS
    lastUpdate = millis();
   
    smoothUpdateStates();  // 先更新状态
    applyMarkovTransition();
    generateWindPattern();
   
    // 添加残影效果
    fadeToBlackBy(leds, NUM_LEDS, 220);
    FastLED.show();
  }
}
#endif



// 动画参数
uint8_t noiseScale = 20;
uint8_t noiseSpeed = 12;
uint16_t zOffset = 0;

#define COLS       30
#define ROWS       15

// 坐标转换函数
void getXY(uint16_t i, uint8_t &x, uint8_t &y) {
  x = i % COLS;
  y = i / COLS;
  if (y % 2) x = (COLS - 1) - x;
}
#define FRAME_RATE 10
void fluidAnimation() {
  for (int i = 0; i < NUM_LEDS; i++) {
    uint8_t x, y;
    getXY(i, x, y);
   
    // 生成三维噪声
    uint16_t noise = inoise16(x * noiseScale * 10,
                             y * noiseScale * 10,
                             zOffset);
   
    // 动态色相映射
    uint8_t hue = (noise >> 8) + millis() / 100; // 叠加整体色相漂移
    hue = 180 + ((hue - 160) % 76); // 160-255循环
    // 亮度波动
    uint8_t val = 100 + (noise % 55);
   
    leds[i] = CHSV(hue, 240, val);
  }
  zOffset += noiseSpeed * 256;
}

void fluor_vision() {
  fluidAnimation();
  FastLED.show();
  FastLED.delay(1000 / FRAME_RATE);
}

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

// 带随机扰动的距离计算
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 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 wave_vision() {
  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);  // 更暗的中心
    }
  }


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

使用特权

评论回复
地板
keer_zu|  楼主 | 2025-5-27 10:13 | 只看该作者
尝试速度可控,还存在问题:

#include <stdint.h>
//#include <math.h>
#include "led_functions.h"

#define ROTATION_SPEED 0.5  // 旋转速度(弧度/秒)


// 定义主色和辅助色的HSV范围(H:0-255对应0-360度)
const uint8_t MAIN_HUE = 0;     // 主色Hue(例如红色)
const uint8_t ACCENT_HUE = 32;  // 辅助色Hue(例如橙色)
const uint8_t HUE_RANGE = 16;   // 主辅色之间的过渡范围

// 动态参数
uint8_t baseBrightness = 128;   // 基础亮度
uint8_t brightnessJitter = 50;  // 亮度波动范围
uint8_t saturation = 200;       // 饱和度(0-255)
uint8_t spreadRatio = 50;       // 主色占比(%)

//===================== wave ====================================
#define MAX_WAVES      24  // 增加最大波环数量
const float NOISE_INTENSITY = 0.6f;   // 空白区域噪声强度

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 = 0.8f;  // 缩短触发距离增加密度

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

void spawnWave(uint8_t gen);
//===============================================================

// 颜色定义
const CRGB coreColor1 = CRGB(0x66, 0x99, 0xFF);  // #6699FF
const CRGB coreColor2 = CRGB(0xAE, 0xEE, 0xEE);  // #AEEEEE
const CRGB bgColor = CRGB(0x00, 0x33, 0x66);     // #003366
CRGB mainColor = CRGB(0x00, 0x88, 0xFF);         // 主过渡色

float distanceFromCenter(uint8_t x, uint8_t y);
// 随机种子初始化
unsigned long seed = 0;
uint8_t randomness = 0;   // 随机种子

//================= globalSpeedFactor ======================
float globalSpeedFactor=1.0f;

void SetGlobalSpeedFactor(float speed)
{
  globalSpeedFactor = constrain(speed, 0.1f, 5.0f);
}
//==========================================================

void random_init()
{
  //randomSeed(analogRead(0)); // 使用模拟输入初始化随机种子
  //seed = random(10000); // 创建基础随机种子
  //randomness = random(64);   // 创建基础随机层
  //random16_set_seed(esp_random()); // 使用ESP32硬件随机数
  
  //==================== 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.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;

  //================================================
}

//example
#if 1
void show_rainbow()
{
  static uint8_t hue = 0;
  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 根据坐标生成色相和明度波浪
      uint8_t ledHue = hue + x * 10 + y * 5;
       uint8_t targetHue = map(ledHue, -32768, 32767, 96, 225);
      uint8_t brightness = sin8(x * 20 + y * 20 + hue);
      leds[XY(x, y)] = CHSV(targetHue, 255, brightness);
    }
  }
  FastLED.show();
  hue += 2;
  delay(20);
}
#else
void show_rainbow() {
  static uint8_t wavePhase = 0;  // 波形相位控制

  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 生成动态波形色相(核心逻辑)
      uint8_t waveHue = sin8(wavePhase + x * 15 + y * 8);  // 空间波形叠加
      uint8_t targetHue = map(waveHue, 0, 255, 150, 255);  // 映射到目标范围

      // 亮度波浪(与色相不同步增强立体感)
      uint8_t brightness = sin8(x * 30 + y * 20 + wavePhase * 2);

      leds[XY(x, y)] = CHSV(targetHue, 255, brightness);
    }
  }

  FastLED.show();
  wavePhase += 1;  // 控制波形运动速度
  delay(20);
}

void show_rainbow() {
  static uint16_t timeBase = 0;
  static uint8_t xNoise[MATRIX_WIDTH];
  static uint8_t yNoise[MATRIX_HEIGHT];
  
  // 亮度平滑滤波器
  static uint8_t lastBrightness[MATRIX_WIDTH][MATRIX_HEIGHT] = {{0}};

  // 噪声混合参数(20%更新强度)
  #define NOISE_BLEND_AMOUNT 51  // 近似20% (51/255 ≈ 0.2)

  EVERY_N_MILLISECONDS(50) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      xNoise[x] = xNoise[x] + (random8() - xNoise[x]) * NOISE_BLEND_AMOUNT / 255;
    }
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      yNoise[y] = yNoise[y] + (random8() - yNoise[y]) * NOISE_BLEND_AMOUNT / 255;
    }
  }

  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 获取当前噪声值
      uint8_t currentXNoise = xNoise[x];
      uint8_t currentYNoise = yNoise[y];

      // 动态色相生成(保持120-255范围)
      uint8_t baseHue = map(sin8(timeBase/3 + x*8), 0, 255, 120, 200);
      uint8_t finalHue = (baseHue +
                         map(currentXNoise, 0, 255, -15, 15) +
                         map(currentYNoise, 0, 255, -10, 10)) % 136 + 120;

      // 亮度处理(核心修改部分)
      uint8_t rawBrightness = inoise8(x*30, y*30, timeBase);  // 降低噪声频率
      
      // 映射到40-200范围并添加平滑滤波
      uint8_t targetBrightness = map(rawBrightness, 0, 255, 40, 200);
      uint8_t brightness = (targetBrightness * 3 + lastBrightness[x][y] * 7) / 10; // 70%历史值权重
      lastBrightness[x][y] = brightness;

      leds[XY(x, y)] = CHSV(finalHue, 240, brightness);
    }
  }

  FastLED.show();
  timeBase += 2;  // 降低整体变化速度
  delay(20);
}
#endif

void random_vision()
{
  // 随机生成动态参数
  uint8_t currentHue = random(MAIN_HUE - HUE_RANGE, MAIN_HUE + HUE_RANGE);
  uint8_t currentBrightness = baseBrightness + random(-brightnessJitter, brightnessJitter);
  uint8_t currentSpread = random(0, 100); // 用于范围控制

  // 更新所有LED颜色
  for (int i = 0; i < NUM_LEDS; i++) {
    // 根据spreadRatio决定使用主色还是辅助色
    uint8_t hue = (currentSpread < spreadRatio) ?
                  random(currentHue - 5, currentHue + 5) :  // 主色微抖动
                  random(ACCENT_HUE - 5, ACCENT_HUE + 5);    // 辅助色微抖动

    // 生成最终颜色
    leds[i] = CHSV(
      hue,
      saturation,
      constrain(currentBrightness + random(-20, 20), 0, 255) // 亮度叠加噪声
    );
  }

  FastLED.show();
  delay(50 + random(0, 100)); // 随机刷新间隔
}

void smooth_vision()
{
    uint8_t currentBrightness = baseBrightness + random(-brightnessJitter, brightnessJitter);
    static CRGBPalette16 currentPalette;
  if (random(0, 100) > 90) { // 10%概率切换色板
    currentPalette = CRGBPalette16(
      CHSV(random(MAIN_HUE - HUE_RANGE, MAIN_HUE + HUE_RANGE), 255, 255),
      CHSV(random(ACCENT_HUE - HUE_RANGE, ACCENT_HUE + HUE_RANGE), 255, 255)
    );
  }
  
  // 使用色板插值
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = ColorFromPalette(
      currentPalette,
      random8(), // 随机位置采样色板
      currentBrightness,
      LINEARBLEND
    );
  }
  FastLED.show();
  delay(30);
}

#if 1
void optim_vision()
{
  static uint8_t breathPhase = 0;
  static uint8_t rotationPhase = 0;
  static uint8_t globalRandom = 0;
  
  breathPhase += 1;
  rotationPhase += 2;
  globalRandom = (globalRandom + 1) % 256; // 缓慢变化的随机种子
  
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      int index = getLEDIndex(x, y);
      CRGB& pixel = leds[index];
      
      // 中心点计算(蛇形坐标)
      int centerX = MATRIX_WIDTH / 2;
      int centerY = MATRIX_HEIGHT / 2;
      float dx = abs(x - centerX);
      float dy = abs(y - centerY);
      float distance = sqrt(dx*dx + dy*dy);
      
      // 带随机性的呼吸效果
      float breathVal = (sin(breathPhase * 0.1 + (random(3)-1)*0.5) + 1) * 64;
      breathVal += (random(5) - 2) * 0.5; // 微小随机波动
      
      uint8_t baseHue = 240; // 主色调深蓝
      uint8_t hueVariance = 10; // 色调随机范围
      
      // 主色调背景(带柔和渐变)
      if (distance > 10) {
        pixel = CHSV(baseHue + random(-hueVariance, hueVariance),
                    80 + random(10),
                    breathVal / 2);
      } else {
        // 紫色光晕(等级1限制,柔和混合)
        float ratio = constrain(distance / 10, 0, 1);
        uint8_t h1 = baseHue;
        uint8_t s1 = 100;
        uint8_t v1 = breathVal;
        
        uint8_t h2 = 255;
        uint8_t s2 = 20 + random(5);
        uint8_t v2 = breathVal * 2 + random(3);
        
        CRGB color1 = CHSV(h1, s1, v1);
        CRGB color2 = CHSV(h2, s2, v2);
        
        // 使用立方贝塞尔曲线实现平滑过渡
        float t = pow(ratio, 0.5);
        CRGB blended = blend(color1, color2, t*t*(3-2*t));
        
        // 添加随机噪声纹理
        float noiseVal = (inoise8(x * 3 + seed, y * 3 + seed + rotationPhase) - 128) / 256.0;
        blended.g += noiseVal * 15;
        blended.b += noiseVal * 10;
        
        pixel = blended;
        
        // 动态波纹(带随机相位)
        float time = (millis() / 1000.0) + rotationPhase * 0.05 + (random(5)-2)*0.1;
        float wave = sin((distance + time) * 0.5 + (random(10)-5)*0.05) * 2;
        pixel.blue += wave;
        pixel.green += wave / 2;
        
        // 结构纹理(模拟波纹)
        float detail = sin((x + y + time) * 3 + (random(3)-1)*0.2) * 5;
        pixel.red += detail;
      }
    }
  }
  
  FastLED.show();
  delay(random(20, 40)); // 随机延时增加自然感
}
#endif

void random_rainbow()
{
    static uint8_t hue = 180; // 初始色相设定在青色区间
  static uint8_t randomness = 0; // 随机种子控制变量
  
  // 动态调整随机种子
  randomness = (randomness + 1) % 64;
  
  for (int x = 0; x < MATRIX_WIDTH; x++) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      // 计算基础色相
      uint8_t baseHue = hue + x * 10 + y * 5;
      
      // 添加可控随机偏移(±3范围内)
      uint8_t hueOffset = random(61) - 30; // 生成-30到+29的随机数
      uint8_t ledHue = baseHue + hueOffset;
      
      // 强制限制在青蓝紫区间(180-300度)
      ledHue = ledHue % 360;
      if (ledHue < 180) ledHue += 180;
      else if (ledHue > 300) ledHue -= 120;
      
      // 生成动态亮度(带波浪噪声)
      uint8_t brightness = sin8(x * 20 + y * 20 + hue + randomness);
      brightness = qadd8(brightness, random(32)); // 最多叠加31的随机亮度
      
      // 创建柔和过渡的色彩
      CRGB color = CHSV(ledHue, 255, brightness);
      color.fadeToBlackBy(255 - (random(64) + 192)); // 随机透明度
      
      leds[XY(x, y)] = color;
    }
  }
  
  FastLED.show();
  
  // 随机呼吸式延迟
  uint8_t delayTime = random(15, 45);
  delay(delayTime);
  
  // 更新主色相(缓慢变化)
  hue += 1;
  if (hue >= 360) hue -= 360;
}
// 中心点坐标(蛇形布局需调整)
int centerX = MATRIX_WIDTH / 2;
int centerY = MATRIX_HEIGHT / 2;

// 动态参数
uint8_t hueBase = 180;    // 初始色相(青色)
uint8_t flowSpeed = 1;    // 流动速度(1-5)

void centor_rainbow()
{
  static uint8_t time = 0;
  
  // 时间推进与随机扰动
  time++;
  randomness = (randomness + 1) % 64;
  
  for (int y = 0; y < MATRIX_HEIGHT; y++) {
    for (int x = 0; x < MATRIX_WIDTH; x++) {
      int index = y * MATRIX_WIDTH + x;
      CRGB& pixel = leds[index];
      
      // 蛇形布局修正(如需平面布局可注释)
      if (y % 2 != 0) x = MATRIX_WIDTH - 1 - x;
      
      // 计算到中心点的距离
      float dx = x - centerX;
      float dy = y - centerY;
      float distance = sqrt(dx*dx + dy*dy);
      
      // 生成基础半径和随机涨落
      float baseRadius = (time * flowSpeed) / 2.0;
      float radiusFluctuation = (random(21) - 10) * 0.5; // ±5范围随机
      float currentRadius = baseRadius + radiusFluctuation;
      
      // 判断是否在扩散范围内
      if (distance <= currentRadius) {
        // 计算色相(强制青蓝紫范围)
        float hueRange = 120; // 180-300度
        float hueOffset = (distance / currentRadius) * hueRange;
        uint8_t hue = hueBase + hueOffset;
        hue = constrain(hue, 180, 300);
        
        // 添加噪声纹理
        uint8_t noiseVal = inoise8(x * 4 + randomness, y * 4 + time + randomness);
        hue += (noiseVal - 128) / 64; // ±0.5色相偏移
        
        // 生成颜色(柔和渐变)
        uint8_t saturation = 255;
        uint8_t value = 255 - (distance / currentRadius * 255);
        
        CRGB color = CHSV(hue, saturation, value);
        pixel = color;
      } else {
        pixel = CRGB::Black;
      }
    }
  }
  
  FastLED.show();
  
  // 动态延迟控制
  uint8_t delayTime = random(10, 30) + (randomness % 5);
  delay(delayTime);
}


const CRGB palette[] = {
  CRGB(0x2A, 0x5B, 0x8C), // 深蓝
  CRGB(0x3E, 0xB7, 0xA0), // 青绿
  CRGB(0x80, 0x00, 0x80), // 紫
  CRGB(0xFF, 0xC0, 0xCB)  // 粉
};

void renderGradient(int style) {
  switch (style) {
    case 0: // 对角线线性渐变(第1张图)
      for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++) {
          float ratio = (x + y) / (float)(MATRIX_WIDTH + MATRIX_HEIGHT - 2);
          leds[y * MATRIX_WIDTH + x] = blend(palette[0], palette[2], ratio * 255);
        }
      }
      break;
    case 1: // 流体渐变(第5张图)
      static uint16_t z;
      for (int i = 0; i < NUM_LEDS; i++) {
        uint8_t noise = inoise8(i % MATRIX_WIDTH * 30, i / MATRIX_WIDTH * 30, z);
        leds[i] = ColorFromPalette(CRGBPalette16(palette), noise);
      }
      z += 10;
      break;
  }
  FastLED.show();
}

void test_vision()
{
   for (int i = 0; i < 4; i++) { // 循环切换4种渐变
    renderGradient(i % 2);
    delay(20);
  }
}

#if 1
// 马尔科夫链状态结构体(修正字段类型)
struct MarkovState {
  uint8_t baseHue;     // 改为8位存储
  uint8_t speed;       // 速度范围1-5
  int8_t direction;    // 风向
  uint8_t intensity;   // 强度范围
};

// 初始化状态(调整参数)
MarkovState currentState = {200, 3, 1, 150}; // 提高初始baseHue

// 简化转移概率矩阵
const uint8_t transitionProb[4][4] = {
  {80, 10, 5, 5},   
  {15, 70, 10, 5},  
  {10, 5, 80, 5},  
  {5, 5, 5, 85}   
};

// 噪声参数
uint16_t z = 0;
const uint8_t scale = 30;
const uint8_t blurAmount = 64;


// 马尔科夫状态转移实现
void applyMarkovTransition() {
  uint8_t randVal = random8();
  uint8_t probSum = 0;
  
  // 选择要改变的状态维度
  uint8_t targetDim = 0;
  for(; targetDim<4; targetDim++) {
    probSum += transitionProb[targetDim][targetDim];
    if(randVal < probSum) break;
  }
  
  // 执行状态转移(有限差分法)
  switch(targetDim) {
    case 0: // 基础色调变化
      currentState.baseHue += random8(3) - 1; // ±1微调
      currentState.baseHue = constrain(currentState.baseHue, 180, 255);
      break;
      
    case 1: // 速度变化
      currentState.speed = constrain(
        currentState.speed + random8(3) - 1, 1, 5);
      break;
      
    case 2: // 方向变化
      if(random8() < 30) currentState.direction *= -1;
      break;
      
    case 3: // 强度变化
      currentState.intensity = constrain(
        currentState.intensity + random8(21) - 10, 100, 200);
      break;
  }
}

// 基于状态的图案生成
void generateWindPattern() {
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
      uint8_t noise = inoise8(
        (x * scale) / 2 + (currentState.direction * z),
        y * scale + z/2,
        currentState.intensity * 10
      );
      
      // 修正色调计算(添加循环处理)
      uint8_t hue = currentState.baseHue + map(noise, 0,255, -20,20);
      hue = (hue < 180) ? hue + 75 : hue; // 确保在180-255范围
      
      // 修正亮度计算(移除错误处理)
      uint8_t val = map(noise, 50, 205, 30, 230);
      val = constrain(val, 30, 230); // 硬约束
      
      leds[XY(x,y)] = CHSV(hue, 230, val);
    }
  }
  
  blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, blurAmount);
  z += 2;//currentState.speed;   //速度均匀
}



void wind_vision() {
  static uint32_t lastUpdate = 0;
  static uint8_t hueShift = 0;

  if(millis() - lastUpdate > 50) { // 降低更新频率
    lastUpdate = millis();
   
    // 马尔科夫状态转移
    applyMarkovTransition();
   
    // 生成动态风场
    generateWindPattern();
   
    FastLED.show();
    delay(10);
  }
}
#else



// 马尔科夫链增强平滑版本
struct MarkovState {
  uint8_t baseHue;     // 当前色相
  uint8_t targetHue;   // 目标色相(新增)
  uint8_t speed;
  uint8_t targetSpeed; // 新增目标速度
  int8_t direction;
  float directionF;    // 新增浮点方向(用于平滑过渡)
  uint8_t intensity;
};

MarkovState currentState = {200, 200, 3, 3, 1, 1.0f, 150};
const uint8_t transitionProb[4][4] = {
  {90, 5, 3, 2},     // 提高保持色相的概率
  {10, 85, 3, 2},    // 降低速度变化频率
  {5, 5, 88, 2},     // 增强方向稳定性
  {3, 2, 2, 93}      // 提高强度保持率
};

uint32_t z = 0;       // 改为32位防溢出
const float DIRECTION_TRANSITION = 0.1f; // 方向过渡系数

void applyMarkovTransition() {
  static uint32_t lastChange = 0;
  const uint32_t CHANGE_INTERVAL = 3000; // 延长状态变化间隔
  
  if(millis() - lastChange < CHANGE_INTERVAL) return;
  lastChange = millis();

  uint8_t randVal = random8();
  uint8_t probSum = 0;
  uint8_t targetDim = 0;
  
  // 概率累计方式优化
  while(targetDim < 4 && randVal > (probSum += transitionProb[targetDim][targetDim])) {
    targetDim++;
  }

  // 有限渐变状态转移
  switch(targetDim) {
    case 0: // 色相渐变
      currentState.targetHue = constrain(currentState.baseHue + random8(-8, 9), 180, 255);
      break;
      
    case 1: // 速度渐变
      currentState.targetSpeed = constrain(currentState.speed + random8(-1, 2), 1, 5);
      break;
      
    case 2: // 方向平滑过渡
      currentState.directionF = -currentState.directionF; // 缓慢反转
      break;
      
    case 3: // 强度渐变
      currentState.intensity = constrain(currentState.intensity + random8(-8, 9), 100, 200);
      break;
  }
}

void smoothUpdateStates() {
  // 色相线性插值
  currentState.baseHue = lerp8by8(currentState.baseHue, currentState.targetHue, 10);
  
  // 速度指数平滑
  currentState.speed = (currentState.speed * 7 + currentState.targetSpeed * 1) / 8;
  
  // 方向浮点过渡
  currentState.directionF += (currentState.direction - currentState.directionF) * DIRECTION_TRANSITION;
}

void generateWindPattern() {
  const float dirFactor = currentState.directionF; // 使用浮点方向因子


  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
      // 改进的噪声参数(增加Z轴细分)
      uint8_t noise = inoise8(
        (x * 25) + (z * dirFactor * 0.7f),
        y * 35 + z * 0.3f,
        currentState.intensity * 8 + (z >> 6)
      );
      
      // 循环色相映射(替代硬约束)
      uint8_t hue = currentState.baseHue + map(noise, 0,255, -15,15);
      hue = 180 + ((hue - 180) % 76); // 180-255循环
      
      // 亮度S曲线处理
      uint8_t val = cubicwave8(noise);
      val = map(val, 30, 225, 50, 220);  // 压缩两端
      
      leds[XY(x,y)] = CHSV(hue, 235, val);
    }
  }
  
   // 使用标准二维模糊 + 逐行模糊替代方案
  blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, 64);
  
  // 手动实现行模糊
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    CRGB* rowStart = &leds[XY(0, y)];
    blur1d(rowStart, MATRIX_WIDTH, 32);
  }
  
  z += currentState.speed;
}

void wind_vision() {
  static uint32_t lastUpdate = 0;
  
  if(millis() - lastUpdate > 33) { // 30FPS
    lastUpdate = millis();
   
    smoothUpdateStates();  // 先更新状态
    applyMarkovTransition();
    generateWindPattern();
   
    // 添加残影效果
    fadeToBlackBy(leds, NUM_LEDS, 220);
    FastLED.show();
  }
}
#endif



// 动画参数
uint8_t noiseScale = 20;
uint8_t noiseSpeed = 12;
uint16_t zOffset = 0;

#define COLS       30
#define ROWS       15

// 坐标转换函数
void getXY(uint16_t i, uint8_t &x, uint8_t &y) {
  x = i % COLS;
  y = i / COLS;
  if (y % 2) x = (COLS - 1) - x;
}
#define FRAME_RATE 10
void fluidAnimation() {
  for (int i = 0; i < NUM_LEDS; i++) {
    uint8_t x, y;
    getXY(i, x, y);
   
    // 生成三维噪声
    uint16_t noise = inoise16(x * noiseScale * 10,
                             y * noiseScale * 10,
                             zOffset);
   
    // 动态色相映射
    uint8_t hue = (noise >> 8) + millis() / 100; // 叠加整体色相漂移
    hue = 180 + ((hue - 160) % 76); // 160-255循环
    // 亮度波动
    uint8_t val = 100 + (noise % 55);
   
    leds[i] = CHSV(hue, 240, val);
  }
  zOffset += noiseSpeed * 256;
}

void fluor_vision() {
  fluidAnimation();
  FastLED.show();
  FastLED.delay(1000 / FRAME_RATE);
}

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

// 带随机扰动的距离计算
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);
}

#if 0
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 wave_vision() {
  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);//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);  // 更暗的中心
    }
  }


  //LedDelay(200);
  FastLED.delay(28);  // 稍快的刷新率
}
#else


const uint8_t WAVE_OVERLAP = 3;      // 波环叠加层数

// 全局控制变量

uint32_t noiseZ = 0;

// ================= 波环视觉核心 =================
void wave_vision() {
  static uint32_t lastFrame = millis();
  uint32_t currentFrame = millis();
  float deltaTime = (currentFrame - lastFrame) / 1000.0f;
  lastFrame = currentFrame;

  // 全屏基础噪声填充(先于波环绘制)
  for(uint8_t y=0; y<MATRIX_HEIGHT; y++){
    for(uint8_t x=0; x<MATRIX_WIDTH; x++){
      uint8_t noise = inoise8(x*20, y*20, noiseZ);
      leds[XY(x,y)] = CHSV(200, 50, noise*0.2f); // 低饱和度背景噪声
    }
  }

  // ================= 高密度波环系统 =================
  for(uint8_t i=0; i<MAX_WAVES; i++){
    if(waves[i].active){
      Wave &w = waves[i];
      w.radius += BASE_WAVE_SPEED * w.speedVariation * globalSpeedFactor * deltaTime;

      // 动态波环生成(三重触发机制)
      float effectiveTriggerDist = TRIGGER_DISTANCE / globalSpeedFactor;
      if(w.generation < WAVE_OVERLAP && w.radius >= effectiveTriggerDist*(w.generation+1)){
        spawnWave(w.generation+1);
        w.hasTriggered = true;
      }

      // 持续能量补充机制
      if(w.intensity < 0.8f && random8() < 30){
        w.intensity += 0.15f; // 随机能量增强
      }

      // 波环绘制(三重叠加)
      for(uint8_t n=0; n<WAVE_OVERLAP; n++){
        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;
            float angle = atan2(dy, dx) + w.angleOffset + n*1.047f; // 120度相位差
            float perturbation = 0.6f * sin(angle*5 + w.radius*0.7f);
            float dist = sqrt(dx*dx + dy*dy) * (1.0f + perturbation*0.12f);
            
            float delta = abs(dist - (w.radius + n*0.8f)); // 叠加偏移
            float effectiveWidth = BASE_WAVE_WIDTH * (w.widthVariation - n*0.1f);
            float effect = exp(-pow(delta/effectiveWidth, 1.8f)) * w.intensity;

            // 颜色混合(多世代渐变)
            uint8_t hue = 160 + w.generation*12 + (w.radius + n*2.0f)*0.9f;
            uint8_t sat = 220 - w.generation*15;
            leds[XY(x,y)] += CHSV(hue, sat, effect*255 * (0.7f - n*0.15f));
          }
        }
      }
      
      // 生命周期管理(延长存在时间)
      if(w.radius > maxRadius*1.5f || w.intensity < 0.08f){
        if(w.generation == 0){
          w.radius = 0.0f;
          w.intensity = 1.0f;
          w.speedVariation = random8(85, 115)/100.0f;
          w.widthVariation = random8(80, 120)/100.0f;
        }else{
          w.active = false;
        }
      }
    }
  }

  // ================= 动态高频噪声 =================
  noiseZ += 4 * globalSpeedFactor;
  for(uint8_t i=0; i<NUM_LEDS; i++){
    uint8_t highFreqNoise = inoise8(i*10, noiseZ);
    leds[i] += CHSV(210, 180, highFreqNoise*NOISE_INTENSITY); // 高频闪烁噪声
    leds[i].nscale8(240); // 防止过曝
  }

  FastLED.delay(28);
}

// ================= 辅助函数优化 =================
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.08f,  // 更缓慢的强度衰减
        true,
        gen,
        false,
        random8(80, 120)/100.0f,  // 更大速度变化范围
        random8(75, 125)/100.0f,  // 更大宽度变化
        random8(0, 628)/100.0f
      };
      return;
    }
  }
}

#endif

使用特权

评论回复
5
keer_zu|  楼主 | 2025-5-28 04:50 | 只看该作者
想做一个渐入淡出的效果:
#include <FastLED.h>

#define LED_PIN1 15
#define LED_PIN2 4
#define NUM_LEDS1 270  // 30x9
#define NUM_LEDS2 300  // 30x10
#define MATRIX_WIDTH 30
#define MATRIX_HEIGHT 19
#define MAX_BRIGHTNESS 180
#define EFFECT_DURATION 20000  // 20秒
#define FADE_TIME 3000         // 3秒

CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];

enum Effect { RAINBOW, CIRCLE };
Effect currentEffect = RAINBOW;
unsigned long effectStartTime = 0;

void setup() {
  FastLED.addLeds<WS2815, LED_PIN1>(leds1, NUM_LEDS1);
  FastLED.addLeds<WS2815, LED_PIN2>(leds2, NUM_LEDS2);
  FastLED.setBrightness(MAX_BRIGHTNESS);
  effectStartTime = millis();
}

void loop() {
  unsigned long currentTime = millis();
  unsigned long elapsed = currentTime - effectStartTime;
  
  // 效果切换判断
  if (elapsed >= EFFECT_DURATION) {
    currentEffect = (currentEffect == RAINBOW) ? CIRCLE : RAINBOW;
    effectStartTime = currentTime;
    elapsed = 0;
  }

  // 亮度计算
  float brightness = 1.0;
  if (elapsed < FADE_TIME) {  // 淡入
    brightness = (float)elapsed / FADE_TIME;
  } else if (elapsed < (EFFECT_DURATION - FADE_TIME)) {  // 正常
    brightness = 1.0;
  } else {  // 淡出
    brightness = 1.0 - (float)(elapsed - (EFFECT_DURATION - FADE_TIME)) / FADE_TIME;
  }

  // 设置全局亮度
  FastLED.setBrightness(MAX_BRIGHTNESS * brightness);

  // 执行当前效果
  if (currentEffect == RAINBOW) {
    rainbow_vision();
  } else {
    circle_vision();
  }

  FastLED.show();
}

// 滚动彩虹效果
void rainbow_vision() {
  static uint8_t hue = 0;
  fill_rainbow(leds1, NUM_LEDS1, hue);
  fill_rainbow(leds2, NUM_LEDS2, hue + NUM_LEDS1);
  hue += 2;
}

// 中心扩散圆环效果
void circle_vision() {
  static uint8_t hue = 0;
  static unsigned long startTime = millis();
  
  float radius = (millis() - startTime) / 50.0f;  // 控制扩散速度
  float maxRadius = sqrt(pow(14.5, 2) + pow(9.0, 2));

  if (radius > maxRadius) {
    startTime = millis();
    hue += 50;
  }

  // 处理上半部分(leds1)
  for (int i = 0; i < NUM_LEDS1; i++) {
    int row = i / MATRIX_WIDTH;
    int col = (row % 2 == 0) ? (i % MATRIX_WIDTH) : (MATRIX_WIDTH - 1 - (i % MATRIX_WIDTH));
    float dx = col - 14.5;
    float dy = row - 9.0;
    float distance = sqrt(dx*dx + dy*dy);
   
    if (distance >= radius-1 && distance <= radius+1) {
      leds1[i] = CHSV(hue, 255, 255);
    } else {
      leds1[i] = CRGB::Black;
    }
  }

  // 处理下半部分(leds2)
  for (int i = 0; i < NUM_LEDS2; i++) {
    int row = 9 + (i / MATRIX_WIDTH);
    int col = (row % 2 == 0) ? (i % MATRIX_WIDTH) : (MATRIX_WIDTH - 1 - (i % MATRIX_WIDTH));
    float dx = col - 14.5;
    float dy = row - 9.0;
    float distance = sqrt(dx*dx + dy*dy);
   
    if (distance >= radius-1 && distance <= radius+1) {
      leds2[i] = CHSV(hue, 255, 255);
    } else {
      leds2[i] = CRGB::Black;
    }
  }
}

使用特权

评论回复
6
keer_zu|  楼主 | 2025-5-28 04:51 | 只看该作者
keer_zu 发表于 2025-5-27 10:13
尝试速度可控,还存在问题:

似乎淡出可以,渐入不行

使用特权

评论回复
7
keer_zu|  楼主 | 2025-5-28 17:12 | 只看该作者
非阻塞的跑马灯和呼吸灯:

#include <FastLED.h>

#define LED_PIN     2
#define NUM_LEDS    165
#define LED_TYPE    WS2815
#define COLOR_ORDER GRB
#define BRIGHTNESS  100

CRGB leds[NUM_LEDS];

// 效果状态结构体
struct EffectState {
  unsigned long startTime;
  bool isRunning;
  uint8_t currentPos;
  float brightness;
  bool breathingUp;
};

EffectState fastChaseState = {0, false, 0, 0, true};
EffectState clockwiseState = {0, false, 0, 0, true};
EffectState anticlockwiseState = {0, false, 0, 0, true};
EffectState fastBreathState = {0, false, 0, 0, true};
EffectState slowBreathState = {0, false, 0, 0, true};

void setup() {
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
}

// 1. 快速跑马效果 (3秒一圈)
void startFastChase() {
  fastChaseState.startTime = millis();
  fastChaseState.isRunning = true;
  fastChaseState.currentPos = 0;
}

void updateFastChase() {
  if (!fastChaseState.isRunning) return;
  
  unsigned long elapsed = millis() - fastChaseState.startTime;
  float progress = fmod((float)elapsed / 3000.0, 1.0); // 3秒周期
  fastChaseState.currentPos = (uint8_t)(progress * NUM_LEDS);
  
  // 清除所有LED
  fill_solid(leds, NUM_LEDS, CRGB::Black);
  
  // 设置当前LED为白光
  leds[fastChaseState.currentPos] = CRGB(255, 255, 255);
  
  FastLED.show();
}

// 2. 顺时针拖尾跑马 (8秒一圈)
void startClockwiseChase() {
  clockwiseState.startTime = millis();
  clockwiseState.isRunning = true;
  clockwiseState.currentPos = 0;
}

void updateClockwiseChase() {
  if (!clockwiseState.isRunning) return;
  
  unsigned long elapsed = millis() - clockwiseState.startTime;
  float progress = fmod((float)elapsed / 8000.0, 1.0); // 8秒周期
  uint16_t headPos = (uint16_t)(progress * NUM_LEDS);
  
  // 拖尾参数
  const uint8_t trailLength = 30;
  
  for (int i = 0; i < NUM_LEDS; i++) {
    // 计算与头灯的距离(顺时针方向)
    int distance = (i + NUM_LEDS - headPos) % NUM_LEDS;
   
    if (distance < trailLength) {
      // 指数衰减拖尾
      float decay = pow(0.7, distance);
      uint8_t brightness = (uint8_t)(255 * decay);
      leds[i] = CRGB(brightness, brightness, brightness);
    } else {
      leds[i] = CRGB::Black;
    }
  }
  
  FastLED.show();
}

// 3. 快速呼吸效果 (4秒一轮)
void startFastBreathing() {
  fastBreathState.startTime = millis();
  fastBreathState.isRunning = true;
  fastBreathState.brightness = 0;
  fastBreathState.breathingUp = true;
}

void updateFastBreathing() {
  if (!fastBreathState.isRunning) return;
  
  unsigned long elapsed = millis() - fastBreathState.startTime;
  float cycleProgress = fmod((float)elapsed / 4000.0, 1.0); // 4秒周期
  
  // 使用正弦波实现平滑呼吸
  float brightness = 128 + 127 * sin(cycleProgress * 2 * PI);
  
  fill_solid(leds, NUM_LEDS, CRGB(brightness, brightness, brightness));
  FastLED.show();
}

// 4. 逆时针拖尾跑马 (8秒一圈)
void startAnticlockwiseChase() {
  anticlockwiseState.startTime = millis();
  anticlockwiseState.isRunning = true;
  anticlockwiseState.currentPos = 0;
}

void updateAnticlockwiseChase() {
  if (!anticlockwiseState.isRunning) return;
  
  unsigned long elapsed = millis() - anticlockwiseState.startTime;
  float progress = fmod((float)elapsed / 8000.0, 1.0); // 8秒周期
  uint16_t headPos = NUM_LEDS - (uint16_t)(progress * NUM_LEDS);
  
  // 拖尾参数
  const uint8_t trailLength = 30;
  
  for (int i = 0; i < NUM_LEDS; i++) {
    // 计算与头灯的距离(逆时针方向)
    int distance = (headPos + NUM_LEDS - i) % NUM_LEDS;
   
    if (distance < trailLength) {
      // 指数衰减拖尾
      float decay = pow(0.7, distance);
      uint8_t brightness = (uint8_t)(255 * decay);
      leds[i] = CRGB(brightness, brightness, brightness);
    } else {
      leds[i] = CRGB::Black;
    }
  }
  
  FastLED.show();
}

// 5. 缓慢呼吸效果 (8秒一轮)
void startSlowBreathing() {
  slowBreathState.startTime = millis();
  slowBreathState.isRunning = true;
  slowBreathState.brightness = 0;
  slowBreathState.breathingUp = true;
}

void updateSlowBreathing() {
  if (!slowBreathState.isRunning) return;
  
  unsigned long elapsed = millis() - slowBreathState.startTime;
  float cycleProgress = fmod((float)elapsed / 8000.0, 1.0); // 8秒周期
  
  // 使用正弦波实现平滑呼吸
  float brightness = 128 + 127 * sin(cycleProgress * 2 * PI);
  
  fill_solid(leds, NUM_LEDS, CRGB(brightness, brightness, brightness));
  FastLED.show();
}

// 停止所有效果
void stopAllEffects() {
  fastChaseState.isRunning = false;
  clockwiseState.isRunning = false;
  anticlockwiseState.isRunning = false;
  fastBreathState.isRunning = false;
  slowBreathState.isRunning = false;
  FastLED.clear();
  FastLED.show();
}

void loop() {
  // 非阻塞式更新所有活动效果
  updateFastChase();
  updateClockwiseChase();
  updateFastBreathing();
  updateAnticlockwiseChase();
  updateSlowBreathing();
  
  // 简单的效果切换逻辑(每10秒切换一个效果)
  static unsigned long lastChange = 0;
  if (millis() - lastChange > 10000) {
    lastChange = millis();
    static uint8_t currentEffect = 0;
   
    stopAllEffects();
   
    switch (currentEffect) {
      case 0: startFastChase(); break;
      case 1: startClockwiseChase(); break;
      case 2: startFastBreathing(); break;
      case 3: startAnticlockwiseChase(); break;
      case 4: startSlowBreathing(); break;
    }
   
    currentEffect = (currentEffect + 1) % 5;
  }
  
  // 保持低延迟
  delay(20);
}

使用特权

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

本版积分规则

1443

主题

12779

帖子

53

粉丝