几个按钮的一个处理函数

时间:2017-01-26 18:46:18

标签: function arduino

我用两个按钮写一个简单的草图。为了处理按钮状态,我编写了一个名为changeButtonStatus的函数(作为参数,我传递一个按钮引脚),它返回一个事件编号:

  • 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;
}

如果你能帮助我找出可能存在的问题,我将感激不尽。

1 个答案:

答案 0 :(得分: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);