const int SW_pin = 2; // Joystick按钮引脚
const int X_pin = A0; // X轴模拟引脚
const int Y_pin = A1; // Y轴模拟引脚
// 摇杆状态阈值
const int THRESHOLD_LOW = 400; // 低阈值
const int THRESHOLD_HIGH = 600; // 高阈值
const int CENTER_THRESHOLD = 50; // 中心位置阈值(512±50)
// 方向信号延时触发相关变量
unsigned long directionStartTime = 0; // 方向信号开始时间
const unsigned long DIRECTION_DELAY = 100; // 方向信号延时(0.1秒)
String lastDirection = ""; // 上次检测到的方向
bool directionTriggered = false; // 方向信号是否已触发
// 按钮状态相关变量
unsigned long debounce_duration = 50; // 防抖时间(50ms)
int previous_button_state = HIGH; // 上次按钮状态
int current_button_state = HIGH; // 当前按钮状态
unsigned long last_debounce_time = 0; // 上次状态变化时间
unsigned long press_start_time; // 按钮按下开始时间
unsigned long release_time; // 按钮按下持续时间
void setup() {
Serial.begin(9600);
// 初始化摇杆引脚
pinMode(X_pin, INPUT);
pinMode(Y_pin, INPUT);
pinMode(SW_pin, INPUT_PULLUP); // 启用内部上拉电阻
}
void loop() {
checkJoystick(); // 检测摇杆状态
checkButton(); // 检测按钮状态
}
// 检测摇杆状态(UP, DOWN, LEFT, RIGHT)
void checkJoystick() {
int xValue = analogRead(X_pin); // 读取X轴值
int yValue = analogRead(Y_pin); // 读取Y轴值
// 判断是否在中心位置
bool isCentered = (abs(xValue - 512) < CENTER_THRESHOLD && abs(yValue - 512) < CENTER_THRESHOLD);
// 如果回到中心位置,重置方向触发标志
// 只有回到中心位置之后才能触发方向键,也就是说不能位置为左的键滑到down
if (isCentered) {
directionTriggered = false; //如果回到中心说明方向键没有被触发
lastDirection = ""; //中心位置,空字符串
return;
}
// 判断方向
String currentDirection = "";
if (xValue < THRESHOLD_LOW) {
currentDirection = "RIGHT";
} else if (xValue > THRESHOLD_HIGH) {
currentDirection = "LEFT";
} else if (yValue < THRESHOLD_LOW) {
currentDirection = "DOWN";
} else if (yValue > THRESHOLD_HIGH) {
currentDirection = "UP";
}
// 如果方向发生变化,重置计时器
if (currentDirection != lastDirection) {
directionStartTime = millis(); //一旦方向键拨动到大于阈值的范围内,开始计时
lastDirection = currentDirection; //重置lastdirection为当前direction,这样如果一直停留在这个方向不会判定得到多个该方向的信号
directionTriggered = false; // 方向变化时重置触发标志
}
// 如果方向维持时间超过设定延时且未触发过,则触发信号
if (currentDirection != "" && !directionTriggered && millis() - directionStartTime >= DIRECTION_DELAY) {
Serial.println(currentDirection);
directionTriggered = true; // 标记方向信号已触发
}
}
// 检测按钮状态(单击、双击、长按)
void checkButton() {
if (debounced_button_press_check(SW_pin, LOW)) {
press_start_time = millis(); // 记录按钮按下时间
while (!debounced_button_press_check(SW_pin, HIGH)); // 等待按钮释放
release_time = millis() - press_start_time; // 计算按钮按下持续时间
if (release_time > 1000) {
Serial.println("LONG PRESSING"); // 长按
} else {
// 检测单击或双击
while (1) {
if (debounced_button_press_check(SW_pin, LOW)) {
Serial.println("DOUBLE CLICK"); // 双击
break;
}
if ((millis() - press_start_time) > 400) {
Serial.println("CLICK"); // 单击
break;
}
}
}
}
}
// 检测防抖后的按钮状态
bool debounced_button_press_check(int pin, bool expected_state) {
int button_reading = digitalRead(pin);
// 如果按钮状态变化,重置防抖计时器
if (button_reading != previous_button_state) {
last_debounce_time = millis();
}
previous_button_state = button_reading;
// 如果状态稳定超过防抖时间,则认为是有效状态
if ((millis() - last_debounce_time) > debounce_duration) {
if (button_reading != current_button_state) { //默认HIGH
current_button_state = button_reading;
if (current_button_state == expected_state) {
return true; // 返回true,表示检测到预期状态
}
}
}
return false; // 返回false,表示未检测到预期状态
}