因此,我的问题更多是关于寻找优雅解决方案的问题。 我有几个连接到arduino的按钮,它们可以按预期工作。 为了简单起见,请看两个。我想要同时按下(AB)按钮A,B和A + B进行不同的操作。我可以检查在任何给定时刻按下了哪些按钮并执行操作,问题是,总是先按下一个按钮,这样才能立即调用该方法,而我并没有真正的确定性行为。 我所做的是延迟并检查是否在给定时间内也按下了另一个按钮:
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();
}
}
}
问题是,此代码取决于按钮的按下行为。 我敢肯定,我可以找到足够的解决方案,并进行大量的测试并检查什么时候按下了。尽管有了更多的Buttons,这似乎带来了很多if-nested,我想很多人在设计固件之前都会遇到这个问题。 所以我的问题是,是否以及如何以一种更清洁的方式来完成这项工作。
其他:
如果有人按住按钮,我希望一遍又一遍地重复该操作。
编码是用C ++完成的。
doA,B,AB操作需要一些时间(1-2秒)。
答案 0 :(得分:3)
尝试将所有按钮状态组合到一个变量中,例如:
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;
并据此计算所有条件。希望有帮助!
答案 1 :(得分:1)
如果您有一个Button对象集合,该怎么办。每个Button都有一个“ pressed”属性和一个公共setter方法,该方法允许客户端(您的循环)仅将其设置为true。在循环中,您每次都遍历Button集合,并检查每个按钮上的“ digitalRead”。一旦至少有1个按钮返回0(按下),您便会在循环中启动一个计时器,例如使用150毫秒。自然,您将每个适当的按钮都设置为按下。当计时器倒计时时,其他按钮也可能被设置。先前设置的数字即使其digitalRead变高也会保持设置。在150毫秒延迟结束时,您会立即收集所有按钮按下情况。对于所按下的任何组合,请调用“ doAB”方法-doA,doACF,doBEK等。清除计时器,并使所有按钮按下均变为假。当您收集印刷机状态时,可能会发生后一部分。现在,您的响应逻辑只发生在一个地方。
此方法避免了对多个按钮字母组合的检查。一旦检测到输入,您就可以在选定的时间内激活输入会话。它也适用于反复按住按钮的操作。
答案 2 :(得分:1)
这应该与您的版本相同(或更好)
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();
}
}
}