EasyButton Arduino Library

repository·main·Indexed 19 days ago

https://github.com/evert-arias/easybutton

A lightweight Arduino library for debouncing momentary contact switches. It features an event-driven callback model to handle single presses, releases, long presses, and complex button sequences. The library includes specialized support for ESP32 touch sensors via EasyButtonTouch and software-based button emulation via EasyButtonVirtual.

Tokens
3K
Snippets
13
Records
14
Agent score
67%

What's inside EasyButton

  1. Overview of EasyButton

    main

    EasyButton is an Arduino library designed for debouncing momentary contact switches (such as tactile buttons). It allows developers to detect various button interactions using an event and callback system.

    Key features include:

    • Debouncing: Handles electrical noise in momentary switches.
    • Event Detection: Detects single presses, releases, long presses (held for a specific duration), and button sequences.
    • Sequence Counter: Tracks patterns of presses to trigger events when a specific sequence is matched.
    • Callbacks: Executes user-defined functions when specific button events occur.
  2. Initialize an EasyButton object

    main

    When instantiating a button class derived from EasyButtonBase, you must specify if the button uses active-low logic. If active_low is true, a low signal (GND) is interpreted as a press; otherwise, a high signal is interpreted as a press.

    // Example for a button connected to GND (Active Low)
    EasyButton button(true);
    
    // Example for a button connected to VCC (Active High)
    EasyButton button(false);
  3. Define a button press sequence with the Sequence class

    main

    The Sequence class is used to detect specific patterns of button presses within a defined time window. You initialize it by specifying the required number of presses (sequences) and the maximum duration allowed for the entire sequence to complete (duration) in milliseconds.

    Constructor Signatures

    • Sequence(uint8_t sequences, uint32_t duration): Creates a sequence detector requiring a specific number of presses within a given millisecond duration.
    • Sequence(): Creates an empty sequence detector (0 sequences, 0 duration).
    // Example: Detect a 3-press sequence that must be completed within 1000ms
    Sequence mySequence(3, 1000);
  4. Detect new presses and manage sequence state

    main

    Once a Sequence object is configured, use the following methods to manage its lifecycle and detect patterns:

    • newPress(uint32_t read_started_ms): Call this method whenever a button press is detected. It returns true if the current press completes the defined sequence pattern, and false otherwise. The read_started_ms parameter should be the current timestamp in milliseconds (e.g., from millis()).
    • enable(): Activates the sequence detection logic.
    • disable(): Deactivates the sequence detection logic.
    • reset(): Resets the internal counters and timers, clearing any progress toward a sequence.
    // Usage pattern
    mySequence.enable();
    
    // Inside your loop or interrupt handler
    if (buttonWasPressed) {
        if (mySequence.newPress(millis())) {
            // The sequence was successfully completed!
            doSomething();
            mySequence.reset();
        }
    }
  5. Query button state and timing

    main

    Use these methods to manually poll the button state during your loop. These methods return the state based on the last call to read().

    // Current state
    bool pressed = button.isPressed();   // true if currently pressed
    bool released = button.isReleased(); // true if currently released
    
    // State change detection (based on last read)
    bool wasPressed = button.wasPressed();     // true if state changed to pressed
    bool wasReleased = button.wasReleased();   // true if state changed to released
    
    // Duration-based state
    // Returns true if the button has been in the requested state for at least 'duration' ms
    bool held = button.pressedFor(1000);      // true if pressed for >= 1000ms
    bool idle = button.releasedFor(500);     // true if released for >= 500ms
  6. Initialize an EasyButton instance

    main

    To use EasyButton, instantiate the class by providing the pin number and optional configuration parameters. By default, it uses a 35ms debounce time, enables the internal pullup resistor, and assumes an active-low configuration (where a press pulls the pin to GND).

    Constructor Parameters:

    • pin: The Arduino pin number.
    • debounce_time: Debounce time in milliseconds (default: 35).
    • pullup_enable: Whether to enable the internal pullup resistor (default: true).
    • active_low: Whether the button is active-low (default: true).
    // Example: Initialize a button on pin 2 with 50ms debounce and active-high logic
    EasyButton button(2, 50, true, false);
  7. Use interrupts with EasyButton

    main

    If the hardware pin supports external interrupts, you can use enableInterrupt(callback_t callback) to trigger a function automatically when the button state changes (pressed or released).

    Important: When using interrupts, you must call update() in your main loop to update the button's internal pressed time tracking.

    • supportsInterrupt(): Returns true if the pin supports external interrupts.
    • enableInterrupt(callback): Registers a callback function.
    • disableInterrupt(): Removes the interrupt callback.
    • update(): Required for interrupt-based timing/logic.
    EasyButton button(2);
    
    void myCallback() {
      // Handle press/release event
    }
    
    void setup() {
      button.begin();
      if (button.supportsInterrupt()) {
        button.enableInterrupt(myCallback);
      }
    }
    
    void loop() {
      // Required when using interrupts
      button.update();
    }
  8. Register button event callbacks

    main

    You can register callback functions to be executed automatically when specific button interaction patterns are detected. The library supports standard presses, long presses (held for a specific duration), and button sequences.

    Note: On platforms with EASYBUTTON_FUNCTIONAL_SUPPORT (like ESP8266 or ESP32), you can use std::function for callbacks. On other platforms, you must use standard function pointers.

    // Standard press: triggers when button is pressed and released
    button.onPressed([]() {
        // handle press
    });
    
    // Long press: triggers when button is held for at least 'duration' ms
    button.onPressedFor(1000, []() {
        // handle long press
    });
    
    // Sequence: triggers when a specific sequence of presses is matched
    // Note: Requires EASYBUTTON_DO_NOT_USE_SEQUENCES to be NOT defined
    button.onSequence(1, 500, []() {
        // handle sequence
    });
  9. Use EasyButtonTouch for touch-based button inputs

    main

    The EasyButtonTouch class is a specialized version of EasyButton designed for ESP32 hardware that supports touch sensors. It uses an internal ExponentialFilter to smooth ADC readings and determine if a touch event has occurred based on a threshold.

    Key Behavior:

    • A button is considered pressed when the touchRead() value falls below the configured _touch_threshold.
    • It requires an ESP32 with SOC_TOUCH_SENSOR_SUPPORTED defined.

    Constructor Parameters:

    • pin: The touch sensor pin number.
    • debounce_time: Debounce time in milliseconds (default: 35).
    • threshold: The ADC threshold value (default: 50). If touchRead() is below this value, the button is pressed.
    // Example initialization
    EasyButtonTouch myButton(T3, 35, 50);
    
    void setup() {
      myButton.begin();
    }
    
    void loop() {
      if (myButton.isPressed()) {
        // Handle press
      }
    }
  10. Use EasyButtonVirtual for software-based button emulation

    main

    The EasyButtonVirtual class allows you to treat a boolean variable as a physical button. This is useful for simulating button presses via software, remote commands, or other non-GPIO interfaces.

    To use it, pass a reference to a boolean variable (button_abstraction) to the constructor. The class will then monitor the state of that boolean variable and apply debouncing logic to it, just as it would with a physical pin.

    Constructor Parameters

    • bool &button_abstraction: A reference to the boolean variable that represents the button state.
    • bool active_low: (Optional) Set to true if the 'pressed' state is represented by false (active low), or false if 'pressed' is true (active high). Defaults to true.
    // Example: Simulating a button using a boolean variable
    bool virtualPin = false;
    EasyButtonVirtual myVirtualButton(virtualPin, true);
    
    void setup() {
        myVirtualButton.begin();
    }
    
    void loop() {
        // Simulate a press by changing the variable
        virtualPin = false; 
        
        // Read the debounced state
        if (myVirtualButton.read()) {
            // Button is pressed
        }
    }
  11. Configure the touch threshold in EasyButtonTouch

    main

    You can adjust the sensitivity of the touch sensor using the following methods:

    • begin(int threshold): Initializes the button and sets the touch threshold immediately.
    • setThreshold(int threshold): Updates the _touch_threshold value used to determine if the button is pressed.
    EasyButtonTouch myButton(T3);
    
    void setup() {
      // Initialize with a specific threshold
      myButton.begin(100);
    }
    
    void loop() {
      // Change threshold dynamically
      myButton.setThreshold(150);
    }
  12. Setup and read EasyButton state

    main

    After instantiation, call begin() to initialize the pin. You can then use read() to get the current debounced state of the button.

    • begin(): Initializes the button object and the hardware pin.
    • read(): Returns true if the button is currently pressed, and false if it is released.
    EasyButton button(2);
    
    void setup() {
      button.begin();
    }
    
    void loop() {
      if (button.read()) {
        // Button is pressed
      }
    }