#include <Keypad.h>
// 定义按键模块的行和列数
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
// 按键映射
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
// 按键模块引脚
uint8_t colPins[COLS] = { 5, 4, 3, 2 }; // C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 9, 8, 7, 6 }; // R1, R2, R3, R4
// 创建 Keypad 对象
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// 定义灯引脚
const int redPin = A0; // 红灯
const int yellowPin = A1; // 黄灯
const int greenPin = A2; // 绿灯
// 模式和灯状态
bool isManualMode = false; // 是否为手动模式
int currentLight = 0; // 当前灯状态:0=红灯,1=黄灯,2=绿灯
unsigned long lastChangeTime = 0; // 上一次灯切换的时间
// 手动模式的长亮时长(默认值)
unsigned long manualRedDelay = 10000; // 红灯 10 秒
unsigned long manualYellowDelay = 10000; // 黄灯 10 秒
unsigned long manualGreenDelay = 10000; // 绿灯 10 秒
// 自动模式的时间间隔
const unsigned long autoRedDelay = 10000; // 自动模式红灯时间
const unsigned long autoYellowDelay = 3000; // 自动模式黄灯时间
const unsigned long autoGreenDelay = 10000; // 自动模式绿灯时间
// 设置模式
bool isSetting = false; // 是否处于设置模式
int settingLight = -1; // 当前正在设置的灯
String inputBuffer = ""; // 用于存储用户输入的时间
void setup() {
// 设置灯引脚为输出
pinMode(redPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(greenPin, OUTPUT);
// 初始化灯状态
updateLights();
}
void loop() {
// 检测按键输入
char key = keypad.getKey();
// 处理按键输入
if (key != NO_KEY) {
handleKeyPress(key);
}
// 如果不在设置模式,根据当前模式运行灯逻辑
if (!isSetting) {
if (isManualMode) {
handleManualMode();
} else {
handleAutoMode();
}
}
}
// 按键输入处理
void handleKeyPress(char key) {
if (isSetting) {
// 设置模式下处理输入
if (key >= '0' && key <= '9') {
inputBuffer += key; // 收集数字输入
} else if (key == '#') {
// 用户按下 # 确认输入
unsigned long newDelay = inputBuffer.toInt() * 1000; // 转换为毫秒
if (settingLight == 0) {
manualRedDelay = newDelay;
} else if (settingLight == 1) {
manualYellowDelay = newDelay;
} else if (settingLight == 2) {
manualGreenDelay = newDelay;
}
// 完成设置,退出设置模式
isSetting = false;
settingLight = -1;
inputBuffer = "";
Serial.println("设置完成!");
}
} else {
// 普通模式下处理按键
if (key == 'A') {
// 切换手动/自动模式
isManualMode = !isManualMode;
currentLight = 0; // 切换模式时从红灯开始
lastChangeTime = millis(); // 重置计时
updateLights();
} else if (key == 'B') {
// 设置红灯时间
isSetting = true;
settingLight = 0;
inputBuffer = "";
Serial.println("set redLed...");
} else if (key == 'C') {
// 设置黄灯时间
isSetting = true;
settingLight = 1;
inputBuffer = "";
Serial.println("set yeLed...");
} else if (key == 'D') {
// 设置绿灯时间
isSetting = true;
settingLight = 2;
inputBuffer = "";
Serial.println("set grrenLed");
}
}
}
// 手动模式处理
void handleManualMode() {
unsigned long currentDelay = 0;
// 根据当前灯状态选择时间间隔
if (currentLight == 0) {
currentDelay = manualRedDelay;
} else if (currentLight == 1) {
currentDelay = manualYellowDelay;
} else if (currentLight == 2) {
currentDelay = manualGreenDelay;
}
// 如果时间到了,切换到下一盏灯
if (millis() - lastChangeTime >= currentDelay) {
currentLight = (currentLight + 1) % 3; // 红->黄->绿 循环
updateLights();
lastChangeTime = millis(); // 更新切换时间
}
}
// 自动模式处理
void handleAutoMode() {
unsigned long currentTime = millis();
// 根据当前灯状态设置不同的时间间隔
switch (currentLight) {
case 0: // 红灯
if (currentTime - lastChangeTime >= autoRedDelay) {
currentLight = 1; // 切换到黄灯
updateLights();
lastChangeTime = currentTime;
}
break;
case 1: // 黄灯
if (currentTime - lastChangeTime >= autoYellowDelay) {
currentLight = 2; // 切换到绿灯
updateLights();
lastChangeTime = currentTime;
}
break;
case 2: // 绿灯
if (currentTime - lastChangeTime >= autoGreenDelay) {
currentLight = 0; // 切换到红灯
updateLights();
lastChangeTime = currentTime;
}
break;
}
}
// 更新灯的状态
void updateLights() {
digitalWrite(redPin, currentLight == 0 ? HIGH : LOW);
digitalWrite(yellowPin, currentLight == 1 ? HIGH : LOW);
digitalWrite(greenPin, currentLight == 2 ? HIGH : LOW);
}