2017-01-26 45 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類找到了一個解決方案,它對我來說工作正常。不過,我也會嘗試你的解決方案 –

相關問題