简体   繁体   English

arduino中的多按钮按下管理

[英]multiple button press management in arduino

So my Question is more about the search for an elegant solution. 所以我的问题更多是关于寻找一个优雅的解决方案。 I have several pushbuttons connected to arduino which individualy work as intended. 我有几个连接到arduino的按钮,它们可以按预期工作。 For simplicity just look at two. 为了简单起见,请看两个。 I want different actions on press of buttons A, B and A + B at the same time (AB). 我想要同时按下(AB)按钮A,B和A + B进行不同的操作。 I can check which buttons are pressed at any given moment and perform the action, the problem is, one button is always pressed first so that method gets called immediatly and I have not really deterministic behavior. 我可以检查在任何给定时刻按下了哪些按钮并执行操作,问题是,总是先按下一个按钮,这样才能立即调用该方法,而我并没有真正的确定性行为。 What I have done is put a delay and check if the other button is also pressed in given time: 我所做的是延迟并检查是否在给定时间内也按下了另一个按钮:

void loop() {

delay(100);
A = digitalRead(ButtonA);
B = digitalRead(ButtonB);
if (A == 0) {
    delay(150);
    B = digitalRead(ButtonB);
    if (B == 0) {
        doAB();
    }
    else {
        doA();
    }
}

A = digitalRead(ButtonA);
B = digitalRead(ButtonB);
if (B == 0) {
    delay(150);
    A = digitalRead(ButtonA);
    if (A == 0) {
        doAB();
    }
    else {
        doB();
    }
}

} }

The Problem is, that this code depends on button pushing behavior. 问题在于,该代码取决于按钮的按下行为。 I'm sure I can find a sufficient solution with lots of testing and checking what gets pressed when. 我敢肯定,我可以找到足够的解决方案,并进行大量的测试和检查何时按下了。 With more Buttons though this seems to give an awful lot of if-nesting and I imagine many people had this problem before at designing firmware. 尽管有了更多的Buttons,这似乎带来了很多if-nested,我想很多人在设计固件之前都会遇到这个问题。 So my question is if and how this can be done in a cleaner way. 所以我的问题是,是否以及如何以一种更清洁的方式完成此工作。

misc: 其他:

If someone holds Buttons I want that action to be repeated over and over. 如果有人握住按钮,我希望该操作一遍又一遍地重复。

The coding is done in C++. 编码是用C ++完成的。

doA,B,AB actions are taking some time (1-2sec). doA,B,AB操作需要一些时间(1-2秒)。

Try combine all buttons state into one variable, like: 尝试将所有按钮状态组合到一个变量中,例如:

int allBtnStates;
unsigned long btnTimeStamp = 0;
void loop() {
  A = digitalRead(ButtonA);
  B = digitalRead(ButtonB);
  allBtnStates = A + 2*B;
  if(allBtnStates < 3){ //Any button pressed
    if(btnTimeStamp == 0) btnTimeStamp = millis(); //Create timestamp
    else if(millis() - btnTimeStamp > 150){
      switch(allBtnStates){
        case 2: doA(); break; //Only A pressed
        case 1: doB(); break; //Only B pressed
        case 0: doAB(); break; //Both A and B pressed
      }
      btnTimeStamp = 0; //Reset timestamp
    }
  }
  //Monitor other input if needed
}

If you have button C, then change allBtnStates = A + 2*B; 如果有按钮C,则更改allBtnStates = A + 2*B; to allBtnStates = A + 2*B + 4*C; allBtnStates = A + 2*B + 4*C; and work out all the conditions accordingly. 并据此计算所有条件。 Hope that helps! 希望有帮助!

What if you had a collection of Button objects. 如果您有一个Button对象集合,该怎么办。 Each Button would have a "pressed" property and a public setter method that allows clients (your loop) to only set it true. 每个Button都有一个“ pressed”属性和一个公共setter方法,该方法允许客户端(您的循环)仅将其设置为true。 In your loop you iterate over the Button collection each time, checking for a "digitalRead" on each button. 在循环中,您每次都遍历Button集合,并检查每个按钮上的“ digitalRead”。 As soon as at least 1 button returns 0 (pressed), you start a timer in the loop for say the 150 ms you use. 一旦至少有1个按钮返回0(按下),您便会在循环中启动一个计时器,例如使用150毫秒。 Naturally you set each appropriate Button to pressed. 自然,您将每个适当的按钮都设置为按下。 While the timer is counting down it is possible for other Buttons to get set too. 当计时器倒计时时,其他按钮也可能被设置。 Ones that were previously set stay set even if their digitalRead goes high. 先前设置的数字即使其digitalRead变高也会保持设置。 At the end of the 150 ms delay, you collect all Button presses at once. 在150毫秒延迟结束时,您会立即收集所有按钮按下情况。 Call the "doAB" method for whatever combination was pressed- doA, doACF, doBEK, etc. Clear the timer and have all Button presses go false. 对于所按下的任何组合,请调用“ doAB”方法-doA,doACF,doBEK等。清除计时器,并使所有按钮按下均变为假。 This latter part can happen when you collect the press status. 当您收集印刷机状态时,可能会发生后一部分。 Now your response logic happens in just one place. 现在,您的响应逻辑仅发生在一个地方。

This approach avoids the multiple button letter combination checks you had. 这种方法避免了您进行的多按钮字母组合检查。 Once input is detected you sort of activate an input session for a time of your choosing. 一旦检测到输入,您就可以在选定的时间内激活输入会话。 It works for repeated action on holding buttons too. 它也适用于反复按住按钮的操作。

this should do the same (or better) as your version 这应该与您的版本相同(或更好)

void loop() {
  delay(100);
  A = digitalRead(ButtonA);
  B = digitalRead(ButtonB);
  if (A == 0 || B == 0) {
      delay(150);
      A = digitalRead(ButtonA);
      B = digitalRead(ButtonB);
      if (A == 0 && B == 0) {
          doAB();
      } else if (A == 0) {
          doA();
      } else {
          doB();
      }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM