// 定义LED引脚(5个LED分别接数字引脚13,12,11,10,9)
const int ledPins[] = {13, 12, 11, 10, 9};
// 定义按钮引脚(接数字引脚2,使用内部上拉电阻)
const int buttonPin = 2;
// 模式变量:0=同步闪烁,1=流水灯,2=混合闪烁
int mode = 0;
// 按钮消抖相关变量
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const int debounceDelay = 50;
// 非阻塞定时器变量
unsigned long previousMillis = 0;
// 闪烁状态(同步/混合闪烁共用)
int blinkState = LOW;
// 流水灯当前LED位置和方向
int currentLed = 0;
int flowDirection = 1;
void setup() {
// 初始化所有LED引脚为输出模式,并默认熄灭
for (int i = 0; i < 5; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
// 初始化按钮引脚(启用内部上拉电阻)
pinMode(buttonPin, INPUT_PULLUP);
// 串口调试(用于查看模式切换,可选)
Serial.begin(9600);
}
void loop() {
// 1. 检测按钮状态并切换模式(带消抖处理)
checkButton();
// 2. 根据当前模式执行对应灯光效果(非阻塞方式)
executeCurrentEffect();
}
// 按钮检测与模式切换(含消抖逻辑)
void checkButton() {
int buttonState = digitalRead(buttonPin);
// 检测到按钮状态变化时重置消抖时间
if (buttonState != lastButtonState) {
lastDebounceTime = millis();
}
// 消抖时间结束后处理按钮按下事件
if ((millis() - lastDebounceTime) > debounceDelay) {
if (buttonState == LOW) { // 按钮按下(低电平触发)
mode = (mode + 1) % 3; // 循环切换模式(0→1→2→0)
resetEffect(); // 重置效果状态
Serial.print("当前模式:");
Serial.println(mode); // 串口输出当前模式(调试用)
}
}
lastButtonState = buttonState; // 更新按钮状态
}
// 重置效果状态(切换模式时调用)
void resetEffect() {
// 关闭所有LED
for (int i = 0; i < 5; i++) {
digitalWrite(ledPins[i], LOW);
}
// 重置各效果控制变量
blinkState = LOW;
currentLed = 0;
flowDirection = 1;
previousMillis = millis();
}
// 执行当前模式的灯光效果(核心逻辑)
void executeCurrentEffect() {
unsigned long currentMillis = millis();
switch (mode) {
case 0: // 同步闪烁模式:所有LED同时亮灭
if (currentMillis - previousMillis >= 500) { // 500ms切换一次状态
previousMillis = currentMillis;
blinkState = !blinkState; // 翻转闪烁状态
for (int i = 0; i < 5; i++) {
digitalWrite(ledPins[i], blinkState); // 所有LED同步亮灭
}
}
break;
case 1: // 流水灯模式:LED依次点亮,到达边界后反向流动
if (currentMillis - previousMillis >= 200) { // 200ms移动一个LED
previousMillis = currentMillis;
// 先关闭所有LED
for (int i = 0; i < 5; i++) {
digitalWrite(ledPins[i], LOW);
}
// 点亮当前LED
digitalWrite(ledPins[currentLed], HIGH);
// 更新下一个LED位置
currentLed += flowDirection;
// 到达边界时反向(0→4或4→0时切换方向)
if (currentLed >= 5 || currentLed < 0) {
flowDirection *= -1; // 反转流动方向
currentLed += flowDirection * 2; // 修正位置(避免越界)
}
}
break;
case 2: // 混合闪烁模式:部分LED常亮,部分同步闪烁
if (currentMillis - previousMillis >= 500) { // 500ms切换一次状态
previousMillis = currentMillis;
blinkState = !blinkState;
// 绿、黄、红(引脚12,10,9)同步闪烁
digitalWrite(ledPins[1], blinkState);
digitalWrite(ledPins[3], blinkState);
digitalWrite(ledPins[4], blinkState);
}
// 橙、蓝(引脚13,11)保持常亮
digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[2], HIGH);
break;
}
}