项目作者: mickey9801

项目描述 :
Powerful button tools for managing various button events of standalone button or button array.
高级语言: C++
项目地址: git://github.com/mickey9801/ButtonFever.git
创建时间: 2019-12-27T16:32:31Z
项目社区:https://github.com/mickey9801/ButtonFever

开源协议:MIT License

下载


ButtonFever

Powerful button tools for managing various button events of standalone button or button array. Tested on ESP32 and should also work on Arduino too.

ButtonFever is upgrade version of MultiButton library, provide much powerful button features.

BfButton class handled standalone button debouncing, trigger callback function for single press, double press, and long press events. The class can distinguish different pressing pattern and trigger corresponding callback, i.e. single press vs double press.

BfButtonManager class manage multiple buttons with single analog pin. The class also provide printReading() method for you to check the analog pin reading. In theory you may add more buttons in the circuit.

Installation

  1. Arduino Library Manager (Recommended)
  2. Download or clone this repository into your arduino libraries directory

Standalone Button Usage

BfButton class can be used alone to handle press event of a single digital button.

  1. Include BfButton class

    1. #include <BfButton.h>
  2. Create button object

    1. BfButton(button_mode_t mode, uint8_t pin, bool pullup=true, uint8_t buttonLogic=LOW);

    By default, the object will use internal pullup of the board, but you may also use external pullup/pulldown as example you concern, e.g. awake from deep sleep mode using button.

    Parameters:

    Parameter | Description
    ———————————————|——————
    button_mode_t mode | Declare button mode. Assign BfButton::STANDALONE_DIGITAL for standalone digital button.
    uint8_t pin | GPIO of the button
    bool pullup=true | Use internal pullup
    uint8_t buttonLogic=LOW | Button logic. Possible value: HIGH (pulldown) or LOW (pullup, default)

    1. const unsigned int btnPin = 12;
    2. BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, false, HIGH); // using external pulldown
  3. Declare button callback

    Button callback must contain 2 parameters:

    Parameter | Description
    —————————————|——————
    BfButton *btn | BfButtons object itself
    BfButton::press_pattern_t pattern | Press pattern of the event. Possible value:

    • BfButton::SINGLE_PRESS
    • BfButton::DOUBLE_PRESS
    • BfButton::LONG_PRESS
      • You may declare different callback for different press pattern, or you may use single callback for all pattern.

        1. void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) {
        2. Serial.print(btn->getID());
        3. switch (pattern) {
        4. case BfButton::SINGLE_PRESS:
        5. Serial.println(" pressed.");
        6. break;
        7. case BfButton::DOUBLE_PRESS:
        8. Serial.println(" double pressed.");
        9. break;
        10. case BfButton::LONG_PRESS:
        11. Serial.println(" long pressed.");
        12. break;
        13. }
        14. }
      • In setup() of the sketch, assign callback for button press events

        1. void setup() {
        2. btn.onPress(pressHandler)
        3. .onDoublePress(pressHandler) // default timeout
        4. .onPressFor(pressHandler, 1000); // custom timeout for 1 second
        5. }
        • BfButton& onPress ( callback_t callback )

          Single press event handler

        • BfButton& onDoublePress ( callback_t callback, unsigned long timeout=300 )

          Detect double press within timeout.

        • BfButton& onPressFor ( callback_t callback, unsigned long timeout=3000 )

          Trigger long press event when continue pressed for a while (ie. timeout).

      • In loop() of the sketch, read button status.

        1. void loop() {
        2. btn.read();
        3. }

Example

  1. #include <BfButton.h>
  2. const unsigned int btnPin = 12;
  3. BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, false, HIGH); // I added a pulldown myself
  4. void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) {
  5. Serial.print(btn->getID());
  6. switch (pattern) {
  7. case BfButton::SINGLE_PRESS:
  8. Serial.println(" pressed.");
  9. break;
  10. case BfButton::DOUBLE_PRESS:
  11. Serial.println(" double pressed.");
  12. break;
  13. case BfButton::LONG_PRESS:
  14. Serial.println(" long pressed.");
  15. break;
  16. }
  17. }
  18. void setup() {
  19. Serial.begin(115200);
  20. while (!Serial);
  21. Serial.println();
  22. btn.onPress(pressHandler)
  23. .onDoublePress(pressHandler) // default timeout
  24. .onPressFor(pressHandler, 1000); // custom timeout for 1 second
  25. }
  26. void loop() {
  27. btn.read();
  28. }

Button Array

BfButtonManager class manage multiple buttons with single analog pin.

Reference Circuit

Multiple Button Circuit

Determin Voltage Readings for Each Button

To determin voltage range for each button in the array, you may check the actual readings with printReading() method.

The following sketch calculate the avarage reading of a button from 5 readings:

  1. #include <BfButtonManager.h>
  2. uint16_t reading, avg;
  3. uint16_t sum = 0;
  4. const unsigned int pin = 35;
  5. void setup() {
  6. Serial.begin(115200);
  7. while (!Serial);
  8. Serial.println();
  9. }
  10. void loop() {
  11. static unsigned int i = 0;
  12. reading = BfButtonManager::printReading(pin);
  13. if (reading > 100) { // button pressed
  14. sum += reading;
  15. if (i == 4) {
  16. avg = sum / 5;
  17. Serial.print("Avarage Reading: ");
  18. Serial.println(avg);
  19. sum = 0;
  20. }
  21. i++;
  22. if (i > 4) i = 0;
  23. } else { // button released
  24. sum = 0;
  25. i = 0;
  26. }
  27. delay(200);
  28. }

NOTE: Readings of analog pin may vary upon other connected devices. Voltage ranges for each button should determin based on measurement of the final circuit with all required devices initialized.

Usage

  1. Include BfButton class and BfButtonManager class

    1. #include <BfButtonManager.h>
    2. #include <BfButton.h>
  2. Create button manager object

    1. BfButtonManager(uint8_t pin, uint8_t btnNum);

    Parameters:

    Parameter | Description
    ————————-|——————
    uint8_t pin | Analog pin of the button array
    uint8_t btnNum | Number of buttons in the array

    1. const unsigned int btnPin = 35;
    2. BfButtonManager manager(btnPin, 4);
  3. Create button objects and assign an ID for the button

    1. BfButton(button_mode_t mode, uint8_t id);

    Parameters:

    Parameter | Description
    ———————————————|——————
    button_mode_t mode | Declare button mode. Assign BfButton::ANALOG_BUTTON_ARRAY for button in button array.
    uint8_t id | ID of the button

    1. BfButton btn1(BfButton::ANALOG_BUTTON_ARRAY, 0);
    2. BfButton btn2(BfButton::ANALOG_BUTTON_ARRAY, 1);
    3. BfButton btn3(BfButton::ANALOG_BUTTON_ARRAY, 2);
    4. BfButton btn4(BfButton::ANALOG_BUTTON_ARRAY, 3);
  4. Declare button callback

    (see above: Standalone Button Usage)

  5. In setup() of the sketch, assign callback to events

    (see above: Standalone Button Usage)

  6. In setup() of the sketch, add button to button manager and provide the voltage range of the button

    1. BfButtonManager& addButton(BfButton* btn, uint16_t minVoltageReading, uint16_t maxVoltageReading);

    Parameters:

    Parameter | Description
    —————————————-|——————
    BfButton* btn | Button object
    uint16_t minVoltageReading | Minimum voltage reading of the button
    uint16_t maxVoltageReading | Maximum voltage reading of the button

    1. manager.addButton(&btn1, 3000, 3150);
  7. In setup() of the sketch, initialize button manager for reading analog pin

    1. manager.begin();
  8. In loop() of the sketch, update button state

    1. void loop() {
    2. manager.loop();
    3. }

Example

  1. #include <BfButtonManager.h>
  2. #include <BfButton.h>
  3. const unsigned int btnPin = 35;
  4. BfButtonManager manager(btnPin, 4);
  5. BfButton btn1(BfButton::ANALOG_BUTTON_ARRAY, 0);
  6. BfButton btn2(BfButton::ANALOG_BUTTON_ARRAY, 1);
  7. BfButton btn3(BfButton::ANALOG_BUTTON_ARRAY, 2);
  8. BfButton btn4(BfButton::ANALOG_BUTTON_ARRAY, 3);
  9. void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) {
  10. Serial.print(btn->getID());
  11. switch (pattern) {
  12. case BfButton::SINGLE_PRESS:
  13. Serial.println(" pressed.");
  14. break;
  15. case BfButton::DOUBLE_PRESS:
  16. Serial.println(" double pressed.");
  17. break;
  18. case BfButton::LONG_PRESS:
  19. Serial.println(" long pressed.");
  20. break;
  21. }
  22. }
  23. void setup() {
  24. Serial.begin(115200);
  25. while (!Serial);
  26. Serial.println();
  27. btn1.onPress(pressHandler);
  28. btn1.onDoublePress(pressHandler);
  29. btn1.onPressFor(pressHandler, 2000);
  30. manager.addButton(&btn1, 3000, 3150);
  31. btn2.onPress(pressHandler);
  32. btn2.onPressFor(pressHandler, 1500);
  33. manager.addButton(&btn2, 2190, 2350);
  34. // You may change event handler methods in any order!
  35. btn3.onPressFor(pressHandler, 1000)
  36. .onPress(pressHandler)
  37. .onDoublePress(pressHandler, 300);
  38. manager.addButton(&btn3, 1390, 1550);
  39. btn4.onPress(pressHandler);
  40. manager.addButton(&btn4, 600, 750);
  41. manager.begin();
  42. }
  43. void loop() {
  44. manager.loop();
  45. }

Other methods

BfButton class

  • uint8_t getID ()

    Return button pin number for digital button, or ID for button in button array.

  • uint8_t getPin ()

    Alias of getID().

BfButtonManaget class

  • BfButtonManager& setADCResolution ( uint16_t resolution )

    Set resolution for ADC. The library will set build-in ADC for Arduino and ESP32 by default.

  • static uint16_t printReading ( uint8_t pin )

    Print analog pin reading through Serial port and return the reading.

    1. int reading = MultiButtons::printReading(14);

Button Array In Theory

Voltage Divider Rule

Vout = Vin(R2/R1+R2)

Vin = 3.3V # ESP32
R1+R2 = 5KΩ = 5000Ω

Voltage of each button

  • Button 1 Vout = 3.3(4000/5000) = 2.64V
  • Button 2 Vout = 3.3(3000/5000) = 1.98V
  • Button 3 Vout = 3.3(2000/5000) = 1.32V
  • Button 4 Vout = 3.3(1000/5000) = 0.66V

ADC convertion (12bit for ESP32)

0 ~ 3.3V = 0 ~ 4095
3.3V/4095 = 0.81mV

Button MultiMeter Measurement Expected Value
1 2.62V 3259
2 1.96V~1.97V 2420~2432
3 1.30V~1.31V 1605~1617
4 0.65V 802

It is required an adjustment for ESP32 ADC with the following equation:

Vout = e / 4095.0 * 3.3 + 0.1132

Button Circuit Measurement Serial Debug Data Calculated Voltage w’ Adjustment
1 2.61V 3070~3103 2.59V~2.61V
2 1.95V~1.96V 2237~2255 1.92V~1.93V
3 1.30V 1456~1461 ~1.29V
4 0.64V~0.65V 658~664 0.64V~0.65V

Reference