将两条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);// 稍快的刷新率
} 显示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;
}
} 更多显示效果:
#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);// 稍快的刷新率
} 尝试速度可控,还存在问题:
#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 想做一个渐入淡出的效果:
#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-27 10:13
尝试速度可控,还存在问题:
似乎淡出可以,渐入不行 非阻塞的跑马灯和呼吸灯:
#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]