You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino键盘模拟器新增按键后无输入自动输出字符故障求助

问题描述

我使用Arduino制作了一款键盘模拟器,外接开关按键,原计划在OSU游戏中测试使用。OSU虽支持单键游玩,但双键操作体验更佳,因此我尝试为模拟器新增第二个开关/按键,此次改动后模拟器完全失效,在无任何输入的情况下持续自动输出字符。我已两次重写脚本代码,若代码逻辑稍显杂乱还请谅解,恳请各位帮忙定位故障原因。

原始故障代码
#include <Keyboard.h>
void setup() {
  // put your setup code here, to run once:
pinMode (2, INPUT_PULLUP);
pinMode (5, INPUT_PULLUP);
Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  bool keyL = false;
bool keyR = false;
 
  Keyboard.begin();
 
  if (digitalRead (2) == 0){ //if switch 2 is activated
  keyL = true;
  }  
  else{
  }//do nothing
  if (digitalRead (5) == 0){
  keyR = true;
  }
  else{
  }//do nothing
  
  
  if (keyR = true){
  Keyboard.press ('c');
  delay (50);
  if (digitalRead (5) == 1){
    keyR = false;
   Keyboard.releaseAll(); 
  }
  }
  
  
  
  if (keyL = true){
  Keyboard.press ('z');
  delay (50);
  if (digitalRead (2) == 0){
    keyL = false;
   Keyboard.releaseAll(); 
  }
  }
  
}
核心故障原因
  • 最致命的语法错误:判断按键状态时把相等比较运算符==写成了赋值运算符=。if (keyR = true)和if (keyL = true)这两行根本不是在判断变量值,而是直接把keyR、keyL强制赋值为true,判断条件永远成立,所以不管有没有按键按下,程序都会一直执行按键按下的逻辑,这就是无输入时持续自动输出字符的核心原因。
  • 初始化逻辑位置错误:Keyboard.begin()是键盘功能的初始化函数,只需要在setup()里执行一次即可,放在loop()里会反复初始化键盘设备,导致按键状态混乱。
  • 按键逻辑混乱:代码使用INPUT_PULLUP上拉输入模式,按键按下时引脚读值为0,松开时读值为1。但左键的释放判断写的是if (digitalRead (2) == 0),等于按住按键时才触发释放,松开时反而不释放,和右键的释放判断逻辑都不一致。
  • 释放逻辑不符合双键使用需求:用Keyboard.releaseAll()释放所有按键,当两个键同时按下时,松开任意一个键都会把另一个按住的键也一起释放,双键操作时会出现断触。另外逻辑里嵌套的delay(50)会阻塞整个程序循环,导致按键响应延迟高,跟不上游戏的高速操作。
修复后可用代码
#include <Keyboard.h>

// 引脚、键值、消抖参数常量定义,后续修改无需翻找核心逻辑
const int LEFT_KEY_PIN = 2;
const int RIGHT_KEY_PIN = 5;
const char LEFT_KEY_MAP = 'z';
const char RIGHT_KEY_MAP = 'c';
const int DEBOUNCE_DELAY = 20;

void setup() {
  pinMode(LEFT_KEY_PIN, INPUT_PULLUP);
  pinMode(RIGHT_KEY_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  // 键盘初始化仅在setup执行一次
  Keyboard.begin();
}

void loop() {
  // 左键状态检测
  static bool lastLeftState = HIGH;
  bool currentLeftState = digitalRead(LEFT_KEY_PIN);
  if (currentLeftState != lastLeftState) {
    delay(DEBOUNCE_DELAY);
    currentLeftState = digitalRead(LEFT_KEY_PIN);
    if (currentLeftState == LOW) {
      Keyboard.press(LEFT_KEY_MAP);
    } else {
      Keyboard.release(LEFT_KEY_MAP);
    }
    lastLeftState = currentLeftState;
  }

  // 右键状态检测
  static bool lastRightState = HIGH;
  bool currentRightState = digitalRead(RIGHT_KEY_PIN);
  if (currentRightState != lastRightState) {
    delay(DEBOUNCE_DELAY);
    currentRightState = digitalRead(RIGHT_KEY_PIN);
    if (currentRightState == LOW) {
      Keyboard.press(RIGHT_KEY_MAP);
    } else {
      Keyboard.release(RIGHT_KEY_MAP);
    }
    lastRightState = currentRightState;
  }
}

修复对应调整:

  • 将Keyboard.begin()移至setup(),避免重复初始化
  • 所有条件判断修正为比较运算符==
  • 对齐上拉输入的电平判断逻辑,按下触发对应按键press、松开触发对应按键release,不再使用releaseAll,避免双键同时按时误释放
  • 用状态变化检测+短消抖代替原有的阻塞式长延时,按键响应速度更快,不会卡住主循环

内容的提问来源于stack exchange,提问作者DogshitProgrammer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:33:22