keer_zu 发表于 2025-5-26 15:16

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

代码:

#include <FastLED.h>

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

// LED总数计算
#define NUM_LOWER_ROWS9
#define NUM_UPPER_ROWS10
#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;


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

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


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


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

Wave 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;
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 = sqrt(dx*dx + dy*dy);
    }
}
maxRadius = distanceMap;

// 初始化第一个波环
waves = {
    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.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.active){
      waves = {
      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.active){
      Wave &w = waves;
      
      // 应用随机速度
      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 += 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.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_WIDTH30
#define MATRIX_HEIGHT 19
#define DATA_PIN_LOWER 15// 下部区域GPIO15
#define DATA_PIN_UPPER 4   // 上部区域GPIO2

// LED总数计算
#define NUM_LOWER_ROWS9
#define NUM_UPPER_ROWS10
#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;
//======================================

#define HAN_BITMAP_HEIGHT 16
#define HAN_START_ROW2   //只能偶数
#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 << BITMMAP_POSITION(bitmapX)) &0x80) {
          int ledIndex = XY(x, y);
          if (ledIndex != -1) leds = 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;

// 调整后的参数
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;
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 = sqrt(dx*dx + dy*dy);
    }
}
maxRadius = distanceMap;

// 初始化第一个波环
waves = {
    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.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 = 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 = CHSV(targetHue, 255, brightness);
    }
}

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

void show_rainbow() {
static uint16_t timeBase = 0;
static uint8_t xNoise;
static uint8_t yNoise;

// 亮度平滑滤波器
static uint8_t lastBrightness = {{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 = xNoise + (random8() - xNoise) * NOISE_BLEND_AMOUNT / 255;
    }
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      yNoise = yNoise + (random8() - yNoise) * NOISE_BLEND_AMOUNT / 255;
    }
}

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

      // 动态色相生成(保持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 * 7) / 10; // 70%历史值权重
      lastBrightness = brightness;

      leds = 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 = 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 = 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;
      
      // 中心点计算(蛇形坐标)
      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 = 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;
      
      // 蛇形布局修正(如需平面布局可注释)
      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 = blend(palette, palette, 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 = 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 = {
{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;
    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 = 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 = {
{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++;
}

// 有限渐变状态转移
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 = CHSV(hue, 235, val);
    }
}

   // 使用标准二维模糊 + 逐行模糊替代方案
blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, 64);

// 手动实现行模糊
for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    CRGB* rowStart = &leds;
    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 = 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.active){
      waves = {
      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.active){
      Wave &w = waves;
      
      // 应用随机速度
      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 += 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.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;

// 调整后的参数
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;
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 = sqrt(dx*dx + dy*dy);
    }
}
maxRadius = distanceMap;

// 初始化第一个波环
waves = {
    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.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 = 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 = CHSV(targetHue, 255, brightness);
    }
}

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

void show_rainbow() {
static uint16_t timeBase = 0;
static uint8_t xNoise;
static uint8_t yNoise;

// 亮度平滑滤波器
static uint8_t lastBrightness = {{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 = xNoise + (random8() - xNoise) * NOISE_BLEND_AMOUNT / 255;
    }
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
      yNoise = yNoise + (random8() - yNoise) * NOISE_BLEND_AMOUNT / 255;
    }
}

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

      // 动态色相生成(保持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 * 7) / 10; // 70%历史值权重
      lastBrightness = brightness;

      leds = 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 = 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 = 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;
      
      // 中心点计算(蛇形坐标)
      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 = 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;
      
      // 蛇形布局修正(如需平面布局可注释)
      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 = blend(palette, palette, 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 = 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 = {
{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;
    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 = 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 = {
{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++;
}

// 有限渐变状态转移
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 = CHSV(hue, 235, val);
    }
}

   // 使用标准二维模糊 + 逐行模糊替代方案
blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, 64);

// 手动实现行模糊
for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
    CRGB* rowStart = &leds;
    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 = 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.active){
      waves = {
      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.active){
      Wave &w = waves;
      
      // 应用随机速度
      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 += 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.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 = CHSV(200, 50, noise*0.2f); // 低饱和度背景噪声
    }
}

// ================= 高密度波环系统 =================
for(uint8_t i=0; i<MAX_WAVES; i++){
    if(waves.active){
      Wave &w = waves;
      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 += 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 += CHSV(210, 180, highFreqNoise*NOISE_INTENSITY); // 高频闪烁噪声
    leds.nscale8(240); // 防止过曝
}

FastLED.delay(28);
}

// ================= 辅助函数优化 =================
void spawnWave(uint8_t gen) {
for(uint8_t i=0; i<MAX_WAVES; i++){
    if(!waves.active){
      waves = {
      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

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;
CRGB 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 = CHSV(hue, 255, 255);
    } else {
      leds1 = 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 = CHSV(hue, 255, 255);
    } else {
      leds2 = CRGB::Black;
    }
}
}

keer_zu 发表于 2025-5-28 04:51

keer_zu 发表于 2025-5-27 10:13
尝试速度可控,还存在问题:

似乎淡出可以,渐入不行

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 BRIGHTNESS100

CRGB 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 = 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 = CRGB(brightness, brightness, brightness);
    } else {
      leds = 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 = CRGB(brightness, brightness, brightness);
    } else {
      leds = 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);
}
页: [1]
查看完整版本: 将两条led融合为一个显示矩阵