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

Arduino RichShield计算器修改长按按键连续跳状态问题咨询

Arduino RichShield计算器按键误触发修复方案

问题根源

现有代码采用电平触发逻辑判断按键输入,长按按键时IO口电平持续为LOW,状态切换后的固定延时结束后,下一轮loop循环会再次检测到低电平,触发连续状态跳转。

修复思路

改用下降沿触发+软件消抖逻辑:

  • 仅检测按键从松开(HIGH)到按下(LOW)的跳变瞬间才触发状态切换
  • 加入50ms消抖时长过滤按键机械抖动导致的异常电平跳变
  • 用非阻塞的millis()计时替代原代码中分散的阻塞延时,避免影响按键检测灵敏度

修改后完整代码

#include "Display.h"
// 按键和LED引脚定义
const int PIN_BUTTON = 9;
const int PIN_LEDR = 4;
const int PIN_LEDG = 5;
const int PIN_LEDB = 6;
const int PIN_LEDY = 7;

// 新增按键消抖相关变量
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 可根据实际按键手感调整消抖时长

// 电位计相关变量
const int PIN_POTMETER = 14;
int MAX_NUM = 20;
int MIN_NUM = -20;
int potValue = 0;
int potValueForCalculations = 0;

// 运算相关变量
int buttonCounter = 0;
float inputValue1;
float inputValue2;
float result;
char mathOperator;

void setup() {
  pinMode(PIN_LEDR, OUTPUT);
  pinMode(PIN_LEDG, OUTPUT);
  pinMode(PIN_LEDB, OUTPUT);
  pinMode(PIN_LEDY, OUTPUT);
  pinMode(PIN_POTMETER, INPUT);
  pinMode(PIN_BUTTON, INPUT_PULLUP);
  Display.show("----");
  delay(3000);
}

void loop() {
  // 按键消抖&有效按下检测逻辑
  int currentButtonState = digitalRead(PIN_BUTTON);
  bool buttonPressed = false;
  if (currentButtonState != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // 仅检测从松开到按下的下降沿,触发一次有效按下
    if (currentButtonState == LOW && lastButtonState == HIGH) {
      buttonPressed = true;
    }
  }
  lastButtonState = currentButtonState;

  // 状态1:选择第一个操作数
  if (buttonCounter == 0) {
    potValue = analogRead(PIN_POTMETER);
    potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM);
    Display.show(potValueForCalculations);
    delay(100);

    if (buttonPressed) {
      inputValue1 = potValueForCalculations;
      buttonCounter = 1;
    }
  }
  // 状态2:选择运算符
  else if (buttonCounter == 1) {
    potValue = analogRead(PIN_POTMETER);
    if (potValue <= 256) {
      Display.show("a");
      mathOperator = 'a';
    }
    else if (potValue > 256 && potValue <= 512) {
      Display.show("s");
      mathOperator = 's';
    }
    else if (potValue > 512 && potValue <= 768) {
      Display.show("t");
      mathOperator = 't';
    }
    else {
      Display.show("d");
      mathOperator = 'd';
    }

    if (buttonPressed) {
      buttonCounter = 2;
    }
  }
  // 状态3:选择第二个操作数
  else if (buttonCounter == 2) {
    potValue = analogRead(PIN_POTMETER);
    potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM);
    Display.show(potValueForCalculations);
    delay(100);

    if (buttonPressed) {
      inputValue2 = potValueForCalculations;
      buttonCounter = 3;
    }
  }
  // 状态4:展示运算结果
  else if (buttonCounter == 3) {
    digitalWrite(PIN_LEDG, HIGH);
    digitalWrite(PIN_LEDR, LOW);

    if (mathOperator == 'a') {
      result = inputValue1 + inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 's') {
      result = inputValue1 - inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 't') {
      result = inputValue1 * inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 'd') {
      if (inputValue2 == 0) {
        digitalWrite(PIN_LEDR, HIGH);
        digitalWrite(PIN_LEDG, LOW);
        Display.show("Err");
      }
      else {
        result = inputValue1 / inputValue2;
        Display.show(result);
      }
    }

    if (buttonPressed) {
      buttonCounter = 4;
    }
  }
  // 重置状态
  else if (buttonCounter >= 4) {
    digitalWrite(PIN_LEDR, LOW);
    digitalWrite(PIN_LEDG, LOW);
    digitalWrite(PIN_LEDB, LOW);
    digitalWrite(PIN_LEDY, LOW);
    Display.show("");
    buttonCounter = 0;
  }
}

效果说明

修改后仅短按按键会触发状态切换,长按、按键抖动都不会触发异常跳转,操作响应流畅度也会比原来加阻塞延时的方案更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:57:03