#include <Adafruit_NeoPixel.h>
#define MATRIX_PIN 16
#define ROWS 8
#define COLS 8
#define NUM_PIXELS (ROWS * COLS)
Adafruit_NeoPixel matrix(NUM_PIXELS, MATRIX_PIN, NEO_GRB + NEO_KHZ800);
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return matrix.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else if (WheelPos < 170) {
WheelPos -= 85;
return matrix.Color(0, WheelPos * 3, 255 - WheelPos * 3);
} else {
WheelPos -= 170;
return matrix.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
}
void setup() {
matrix.begin();
matrix.setBrightness(50);
matrix.show();
}
// ================= 原有代码(仅在此处末尾追加了一行调用) =================
void loop() {
static uint16_t offset = 0;
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int pixel = row * COLS + col;
// Spread rainbow across rows and columns
byte colorIndex = ((row + col) * 256 / (ROWS + COLS) + offset) & 255;
matrix.setPixelColor(pixel, Wheel(colorIndex));
}
}
matrix.show();
offset = (offset + 1) & 255;
delay(30);
// 【新增的代码】:运行扩展特效。原有逻辑运行一定时间后,自动进入扩展特效,然后再切回原有逻辑。
runAdvancedEffects();
}
// =========================================================================
// ================= 以下为新增的扩展和显示加强函数 =================
// 调度器:防止扩展特效立刻打断原有动画。每运行 20 秒原有动画,执行一次 20 秒的扩展特效。
void runAdvancedEffects() {
static uint32_t lastExtTime = 0;
// 前 20 秒,仅运行原有代码(如果时间没到,直接返回)
if (millis() - lastExtTime < 20000) return;
// 运行扩展特效序列
centerRipple(15); // 中心扩散彩虹,运行 5 秒
auroraWaves(20); // 极光波浪,运行 6 秒
matrixRain(30); // 数字雨,运行 5 秒
twinkle(50); // 随机闪烁,运行 4 秒
// 记录时间,切回原有逻辑
lastExtTime = millis();
}
// 1. 中心扩散彩虹
void centerRipple(int wait) {
uint32_t startTime = millis();
uint16_t offset = 0;
while (millis() - startTime < 5000) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int pixel = row * COLS + col;
// 计算到矩阵中心 (3.5, 3.5) 的欧几里得距离
float dist = sqrt(pow(row - 3.5, 2) + pow(col - 3.5, 2));
// 将距离映射到颜色索引,实现波纹向外扩散
byte colorIndex = ((int)(dist * 25) + offset) & 255;
matrix.setPixelColor(pixel, Wheel(colorIndex));
}
}
matrix.show();
offset = (offset + 2) & 255;
delay(wait);
}
}
// 2. 极光波浪
void auroraWaves(int wait) {
uint32_t startTime = millis();
float time = 0.0;
while (millis() - startTime < 6000) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int pixel = row * COLS + col;
// 使用正弦波叠加,模拟极光的流动感
float wave1 = sin(row * 0.6 + time);
float wave2 = cos(col * 0.4 + time * 0.8);
float val = (wave1 + wave2 + 2.0) / 4.0; // 归一化到 0.0 - 1.0
// 极光色相:在绿色(85)和蓝紫色(170)之间偏移
byte hue = (byte)(85 + val * 85 + time * 10);
// 亮度也随波浪起伏
uint8_t brightness = 50 + val * 205;
matrix.setPixelColor(pixel, Wheel(hue));
// 利用 setBrightness 是全局的,这里通过缩放颜色值来模拟局部亮度
uint32_t color = Wheel(hue);
uint8_t r = (uint8_t)((color >> 16) * (brightness / 255.0));
uint8_t g = (uint8_t)((color >> 8) * (brightness / 255.0));
uint8_t b = (uint8_t)(color * (brightness / 255.0));
matrix.setPixelColor(pixel, matrix.Color(r, g, b));
}
}
matrix.show();
time += 0.1;
delay(wait);
}
}
// 3. 矩阵雨(数字雨)
void matrixRain(int wait) {
// 初始化雨滴
static int dropPos[COLS];
static bool initialized = false;
if (!initialized) {
for (int i = 0; i < COLS; i++) {
dropPos[i] = random(-10, 0); // 让每一列雨滴起始时间错开
}
initialized = true;
randomSeed(analogRead(0));
}
uint32_t startTime = millis();
while (millis() - startTime < 5000) {
// 1. 整体渐暗 (实现拖尾效果)
for (int i = 0; i < NUM_PIXELS; i++) {
uint32_t color = matrix.getPixelColor(i);
uint8_t r = (color >> 16) & 0xFF;
uint8_t g = (color >> 8) & 0xFF;
uint8_t b = color & 0xFF;
// 衰减因子,0.8 表示每帧变暗 20%
r = r * 0.8;
g = g * 0.8;
b = b * 0.8;
matrix.setPixelColor(i, matrix.Color(r, g, b));
}
// 2. 绘制下落的雨滴头部
for (int col = 0; col < COLS; col++) {
if (dropPos[col] >= 0 && dropPos[col] < ROWS) {
int pixel = dropPos[col] * COLS + col;
matrix.setPixelColor(pixel, matrix.Color(0, 255, 0)); // 亮绿色头部
}
// 随机推进雨滴
if (random(10) < 3) {
dropPos[col]++;
if (dropPos[col] >= ROWS + 5) {
dropPos[col] = random(-5, 0); // 重新从顶部开始
}
}
}
matrix.show();
delay(wait);
}
}
// 4. 随机闪烁(星光点点)
void twinkle(int wait) {
uint32_t startTime = millis();
while (millis() - startTime < 4000) {
// 随机点亮几个像素为白色
for (int i = 0; i < 3; i++) {
int pixel = random(0, NUM_PIXELS);
matrix.setPixelColor(pixel, matrix.Color(255, 255, 255));
}
matrix.show();
delay(wait);
// 逐渐变暗所有像素
for (int i = 0; i < NUM_PIXELS; i++) {
uint32_t color = matrix.getPixelColor(i);
uint8_t r = (color >> 16) & 0xFF;
uint8_t g = (color >> 8) & 0xFF;
uint8_t b = color & 0xFF;
// 让亮度缓慢衰减
r = (r > 5) ? r - 5 : 0;
g = (g > 5) ? g - 5 : 0;
b = (b > 5) ? b - 5 : 0;
matrix.setPixelColor(i, matrix.Color(r, g, b));
}
}
}