2017-01-26 40 views
0

我正在用两个按钮写一个简单的草图。为了处理返回的事件数,我写了一个名为changeButtonStatus(作为一个参数,我通过一个按钮PIN)功能的按钮状态:几个按钮的一个处理函数

  • 0 - 没有点击,
  • 1 - 单一的点击,
  • 2 - 双击,
  • 3 - 长按,
  • 4 - 长按后发布。

在主循环中,我为每个我的两个按钮调用此函数,并使用Serial.println()打印出消息。
问题是,我的素描只适用于一个按钮,并且它不适用于两个或更多按钮。

这里是我的代码:

#include <elapsedMillis.h> 

int but1 = 3; 
int but2 = 4; 

int eventBut1, eventBut2; 

int currentButtonStatus = 0; // 0 - button is not pressed 
           // 1 - button is pressed for the first time 
           // 2 - button is released after being pressed 
           // 3 - button is pressed for the second time 


unsigned long currentButtonStatusStart1; // number of milliseconds when the status has changed to 1 
unsigned long currentButtonStatusStart2; // number of milliseconds when the status has changed to 2  
unsigned long currentButtonStatusStart3; // number of milliseconds when the status has changed to 3 

const int delayFalse = 30;    // if the value is less than 30 milliseconds, one press is not registered 
const int delayLongSingleClick = 400; // if the value is greater than 400 milliseconds, long press is reegistered 
const int delayDeltaDoubleClick = 300; // delay to registere double clck   


void setup() { 
    pinMode (but1, INPUT); 
    pinMode (but2, INPUT); 
    Serial.begin(9600); 
} 

void loop() { 
    eventBut1 = changeButtonStatus(but1); // variable to keep the state of but1 (not pressed, single press, double press, long press) 
    eventBut2 = changeButtonStatus(but2); // variable to keep the state of but2 (not pressed, single press, double press, long press) 

    if (eventBut1 > 0) { 
     if (eventBut1 == 1) {Serial.println("But1 Single click");} 
     if (eventBut1 == 4) {Serial.println("But1 is released after long press");} 
    } 

    if (eventBut2 > 0) { 
     if (eventBut2 == 1) {Serial.println("But2 Single click");} 
     if (eventBut2 == 2) {Serial.println("But2 Double press");} 
    } 
} 

/** 
* Change current button status 
* @return = 0 - not pressed 
*   1 - single click 
*   2 - double click 
*   3 - long press 
*   4 - released after long press 
*/ 
int changeButtonStatus(int butPin) { 
    // Event 
    int event = 0; 

    // Current button status 
    int currentButtonClick = digitalRead(butPin); 

    // Current time 
    unsigned long timeButton = millis(); 

    switch(currentButtonStatus) { 

    case 0: 
     // button has not been pressed 
     if(currentButtonClick) { 
     // fix button click 
     currentButtonStatus = 1; 
     currentButtonStatusStart1 = millis(); 
     } else { 
     // button is not pressed 
     } 
     break; 

    case 1: 
     // button is pressed for the first time 
     if(currentButtonClick) { 
     // button is still pressed 
     if(timeButton - currentButtonStatusStart1 >= delayLongSingleClick) { 
      // button long press state 
      event = 3; 
     } 

     } else { 
     // button has been released 
     if(timeButton - currentButtonStatusStart1 < delayFalse) { 
      currentButtonStatus = 0; 
      event = 0; 
     } else if(timeButton - currentButtonStatusStart1 < delayLongSingleClick) { 
      currentButtonStatus = 2; 
      currentButtonStatusStart2 = millis(); 
     } else { 
      // button has been released after long press 
      currentButtonStatus = 0; 
      event = 4;  
     } 
     } 
     break; 

    case 2: 
     if(currentButtonClick) { 
     // if the button has been pressed for the second time 

     // check how long the button has been released 
     if(timeButton - currentButtonStatusStart2 < delayFalse) { 
      currentButtonStatus = 1; 
     } else { 
      // fix second press 
      currentButtonStatus = 3; 
      currentButtonStatusStart3 = millis(); 
     } 
     } else { 
     // if the button is still released 

     // check for the single click 
     if(timeButton - currentButtonStatusStart2 > delayDeltaDoubleClick) { 
      // button has been released for too long, fix single click 
      currentButtonStatus = 0; 
      event = 1; 
     } 
     } 
     break; 

    case 3: 
     // confirm double click 

     if(currentButtonClick) { 
     // button is still pressed 
     // wait for the button to be released 

     } else { 
     // button has been released 

     // check for the debounce 
     if(timeButton - currentButtonStatusStart3 < delayFalse) { 
      // button has been released too early, probably it's a debounce 

     } else { 
      // fix double click 
      event = 2; 
      currentButtonStatus = 0; 
     } 
     } 
     break; 
    } 
    return event; 
} 

我会感激,如果你能帮我找出什么可能是问题。

+0

*您的问题:*您正在通过覆盖*共享变量(例如'currentButtonStatus')将有关不同*引脚*的事件混合在一起。 * /回答*除非您希望我们也提供正确的实施。 –

回答

0

我们可以看到一个问题,你用两个按钮共享一些全局变量:currentButtonStatus, currentButtonStatusStartX ...

你不应该在你的修正中定义另一组这些变量,你应该为按钮创建一个类,并在你的类中包含这些前面的全局变量。

我写过这样的代码,几乎没有变化。 从这一点,你可以改善和创建一个枚举,将取代事件按钮的常量0,1,2,3。

请注意,我检查了我的修改编译,但我没有用真正的按钮测试。

//#include <elapsedMillis.h> 

int butPin1 = 3; 
int butPin2 = 4; 

int eventBut1, eventBut2; 

class ButtonStat { 

    static const int delayFalse = 30;    // if the value is less than 30 milliseconds, one press is not registered 
    static const int delayLongSingleClick = 400; // if the value is greater than 400 milliseconds, long press is reegistered 
    static const int delayDeltaDoubleClick = 300; // delay to registere double clck   

    public: 
    explicit ButtonStat(int pinBut): pin(pinBut),currentButtonStatus(0), currentButtonStatusStart1(0), 
      currentButtonStatusStart2(0), currentButtonStatusStart3(0) {} 
    int changeButtonStatus(); 
    int getPin() {return pin;} 

    private: 
    int pin; 
    int currentButtonStatus;  // 0 - button is not pressed 
           // 1 - button is pressed for the first time 
           // 2 - button is released after being pressed 
           // 3 - button is pressed for the second time 

    unsigned long currentButtonStatusStart1; // number of milliseconds when the status has changed to 1 
    unsigned long currentButtonStatusStart2; // number of milliseconds when the status has changed to 2  
    unsigned long currentButtonStatusStart3; // number of milliseconds when the status has changed to 3 
} ; 

ButtonStat butt1 = ButtonStat(butPin1); 
ButtonStat butt2 = ButtonStat(butPin2); 

void setup() { 
    pinMode (butt1.getPin(), INPUT); 
    pinMode (butt2.getPin(), INPUT); 
    Serial.begin(9600); 
} 

void loop() { 
    eventBut1 = butt1.changeButtonStatus(); // variable to keep the state of but1 (not pressed, single press, double press, long press) 
    eventBut2 = butt2.changeButtonStatus(); // variable to keep the state of but2 (not pressed, single press, double press, long press) 

    if (eventBut1 > 0) { 
     if (eventBut1 == 1) {Serial.println("But1 Single click");} 
     if (eventBut1 == 4) {Serial.println("But1 is released after long press");} 
    } 

    if (eventBut2 > 0) { 
     if (eventBut2 == 1) {Serial.println("But2 Single click");} 
     if (eventBut2 == 2) {Serial.println("But2 Double press");} 
    } 
} 

/** 
* Change current button status 
* @return = 0 - not pressed 
*   1 - single click 
*   2 - double click 
*   3 - long press 
*   4 - released after long press 
*/ 
int ButtonStat::changeButtonStatus() { 
    // Event 
    int event = 0; 

    // Current button status 
    int currentButtonClick = digitalRead(pin); 

    // Current time 
    unsigned long timeButton = millis(); 

    switch(currentButtonStatus) { 

    case 0: 
     // button has not been pressed 
     if(currentButtonClick) { 
     // fix button click 
     currentButtonStatus = 1; 
     currentButtonStatusStart1 = millis(); 
     } else { 
     // button is not pressed 
     } 
     break; 

    case 1: 
     // button is pressed for the first time 
     if(currentButtonClick) { 
     // button is still pressed 
     if(timeButton - currentButtonStatusStart1 >= delayLongSingleClick) { 
      // button long press state 
      event = 3; 
     } 

     } else { 
     // button has been released 
     if(timeButton - currentButtonStatusStart1 < delayFalse) { 
      currentButtonStatus = 0; 
      event = 0; 
     } else if(timeButton - currentButtonStatusStart1 < delayLongSingleClick) { 
      currentButtonStatus = 2; 
      currentButtonStatusStart2 = millis(); 
     } else { 
      // button has been released after long press 
      currentButtonStatus = 0; 
      event = 4;  
     } 
     } 
     break; 

    case 2: 
     if(currentButtonClick) { 
     // if the button has been pressed for the second time 

     // check how long the button has been released 
     if(timeButton - currentButtonStatusStart2 < delayFalse) { 
      currentButtonStatus = 1; 
     } else { 
      // fix second press 
      currentButtonStatus = 3; 
      currentButtonStatusStart3 = millis(); 
     } 
     } else { 
     // if the button is still released 

     // check for the single click 
     if(timeButton - currentButtonStatusStart2 > delayDeltaDoubleClick) { 
      // button has been released for too long, fix single click 
      currentButtonStatus = 0; 
      event = 1; 
     } 
     } 
     break; 

    case 3: 
     // confirm double click 

     if(currentButtonClick) { 
     // button is still pressed 
     // wait for the button to be released 

     } else { 
     // button has been released 

     // check for the debounce 
     if(timeButton - currentButtonStatusStart3 < delayFalse) { 
      // button has been released too early, probably it's a debounce 

     } else { 
      // fix double click 
      event = 2; 
      currentButtonStatus = 0; 
     } 
     } 
     break; 
    } 
    return event; 
} 

另一个说法:你可能需要每个按钮的上拉电阻。如果你没有外部的,你可以修改pinMode声明:pinMode (butt1.getPin(), INPUT_PULLUP);

+0

感谢您的帮助。最后,我通过创建一个Button类找到了一个解决方案,它对我来说工作正常。不过,我也会尝试你的解决方案 –

相关问题