arduino中的多按钮按下管理
multiple button press management in arduino
所以我的问题更多是关于寻找一个优雅的解决方案。
我有几个连接到 arduino 的按钮,它们可以按预期单独工作。
为简单起见,只看两个。我想要同时按下按钮 A、B 和 A + B 时执行不同的操作 (AB)。我可以检查在任何给定时刻按下了哪些按钮并执行操作,问题是,总是先按下一个按钮,以便立即调用方法,我没有真正确定性的行为。
我所做的是延迟并检查在给定时间内是否也按下了另一个按钮:
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();
}
}
}
问题是,此代码取决于按钮按下行为。
我确信我可以通过大量测试和检查何时按下什么来找到足够的解决方案。虽然有更多的按钮,但这似乎会产生大量的 if 嵌套,我想很多人在设计固件之前都遇到过这个问题。
所以我的问题是是否以及如何以更清洁的方式完成此操作。
杂项:
如果有人按住按钮,我希望这个动作一遍又一遍地重复。
编码是用 C++ 完成的。
doA、B、AB 操作需要一些时间(1-2 秒)。
如果您有一组 Button 对象会怎样。每个 Button 都有一个 "pressed" 属性 和一个 public setter 方法,允许客户端(您的循环)仅将其设置为真。在您的循环中,您每次都遍历 Button 集合,检查每个按钮上的 "digitalRead"。只要至少按下 1 个按钮 returns 0(按下),您就会在循环中启动一个计时器,例如您使用的 150 毫秒。自然地,您将每个适当的按钮设置为已按下。当计时器倒计时时,其他按钮也可以设置。即使 digitalRead 变高,之前设置的那些也会保持设置。在 150 毫秒延迟结束时,您会立即收集所有按钮按下事件。为按下的任何组合调用 "doAB" 方法 - doA、doACF、doBEK 等。清除计时器并让所有按钮按下变为假。当您收集新闻状态时,后一部分可能会发生。现在您的响应逻辑只发生在一个地方。
这种方法避免了您进行的多个按钮字母组合检查。一旦检测到输入,您就可以在您选择的时间激活输入会话。它也适用于按住按钮的重复操作。
这应该与您的版本相同(或更好)
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();
}
}
}
尝试将所有按钮状态合并到一个变量中,例如:
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
}
如果您有按钮 C,则将 allBtnStates = A + 2*B;
更改为 allBtnStates = A + 2*B + 4*C;
并相应地计算出所有条件。希望对您有所帮助!
所以我的问题更多是关于寻找一个优雅的解决方案。 我有几个连接到 arduino 的按钮,它们可以按预期单独工作。 为简单起见,只看两个。我想要同时按下按钮 A、B 和 A + B 时执行不同的操作 (AB)。我可以检查在任何给定时刻按下了哪些按钮并执行操作,问题是,总是先按下一个按钮,以便立即调用方法,我没有真正确定性的行为。 我所做的是延迟并检查在给定时间内是否也按下了另一个按钮:
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();
}
}
}
问题是,此代码取决于按钮按下行为。 我确信我可以通过大量测试和检查何时按下什么来找到足够的解决方案。虽然有更多的按钮,但这似乎会产生大量的 if 嵌套,我想很多人在设计固件之前都遇到过这个问题。 所以我的问题是是否以及如何以更清洁的方式完成此操作。
杂项:
如果有人按住按钮,我希望这个动作一遍又一遍地重复。
编码是用 C++ 完成的。
doA、B、AB 操作需要一些时间(1-2 秒)。
如果您有一组 Button 对象会怎样。每个 Button 都有一个 "pressed" 属性 和一个 public setter 方法,允许客户端(您的循环)仅将其设置为真。在您的循环中,您每次都遍历 Button 集合,检查每个按钮上的 "digitalRead"。只要至少按下 1 个按钮 returns 0(按下),您就会在循环中启动一个计时器,例如您使用的 150 毫秒。自然地,您将每个适当的按钮设置为已按下。当计时器倒计时时,其他按钮也可以设置。即使 digitalRead 变高,之前设置的那些也会保持设置。在 150 毫秒延迟结束时,您会立即收集所有按钮按下事件。为按下的任何组合调用 "doAB" 方法 - doA、doACF、doBEK 等。清除计时器并让所有按钮按下变为假。当您收集新闻状态时,后一部分可能会发生。现在您的响应逻辑只发生在一个地方。
这种方法避免了您进行的多个按钮字母组合检查。一旦检测到输入,您就可以在您选择的时间激活输入会话。它也适用于按住按钮的重复操作。
这应该与您的版本相同(或更好)
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();
}
}
}
尝试将所有按钮状态合并到一个变量中,例如:
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
}
如果您有按钮 C,则将 allBtnStates = A + 2*B;
更改为 allBtnStates = A + 2*B + 4*C;
并相应地计算出所有条件。希望对您有所帮助!