Skip to content

Papymakers/RobustButton

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RobustButton

Version française

Robust push-button handling for electrically noisy environments — where ordinary debouncing is not enough.

The problem nobody talks about

Every Arduino tutorial covers mechanical bounce: when you press a button, the metal contacts bounce for a few milliseconds, producing a burst of edges. A small RC capacitor smooths that away. Done.

But there is a second, very different problem that most tutorials ignore: false triggering by electromagnetic interference. The button is not touched, yet the input fires — because a transient pulse (a relay or contactor switching, a motor starting, an electricity meter's tariff changeover) coupled a spurious edge onto the line.

This library was born from a real case: a heating controller that received phantom commands every day at the same time, precisely when the Linky meter switched its tariff period. No one had pressed anything. The switching transient alone was enough to trigger the interrupt.

Why an RC capacitor is not enough

An RC debounce capacitor smooths the signal — but it does not distinguish a real press from a disturbance. It slows the transient down; it does not identify it. A sufficiently energetic EMI pulse passes through, arriving at the GPIO as a clean edge.

Worse: an oversized capacitor slows the real edge too, which can make an edge-triggered interrupt fire several times along the slope. You then need a Schmitt trigger to sharpen it back. It is a trade-off, rarely explained.

What this library does instead: temporal discrimination

The RC asks "is this signal fast?". This library asks a different question: "does this level persist?"

A real press lasts — your finger stays down for tens of milliseconds. An EMI transient is fleeting — microseconds to a few milliseconds. By requiring the active level to still be present after a confirmation delay, every transient is rejected by nature, regardless of its energy.

The pattern, non-blocking, is:

  1. The ISR does nothing but set a flag and a timestamp. No processing, no I2C, no serial, no logic inside the interrupt. This is the golden rule.
  2. update(), called in loop(), waits the confirmation delay, then re-reads the pin. Level still active → real press. Level gone → transient, ignored (and counted).

Defence in depth: hardware and software

The two approaches are complementary, each at its place:

  • Hardware (RC + optional Schmitt trigger) absorbs mechanical bounce and clips the most violent transients before the GPIO. It also protects the input physically.
  • Software (deferred confirmation) decides on persistence: it rejects anything that does not last as long as a real press — including EMI that made it past the RC.

Neither alone is optimal. RC alone lets energetic EMI through. Software alone works (this library proves it), but a hardware RC eases its job and adds physical protection. Use both when the environment is harsh.

Usage

#include <RobustButton.h>

RobustButton button(7);          // button between GPIO 7 and GND (active-low)

void setup() {
  button.begin();                // interrupt + deferred confirmation
}

void loop() {
  if (button.update()) {         // true once, when a press is confirmed
    // handle the press
  }
}

Tuning for noisy environments

button.setConfirmMs(40);         // required minimum duration of a real press
button.setDebounceMs(60);        // minimum interval between accepted presses

// Diagnose the disturbance: if this climbs at a fixed time of day,
// you have found your EMI source.
Serial.println(button.glitchCount());

API

Method Description
RobustButton(pin, activeLow=true) Constructor. activeLow=true: internal pull-up, button to GND.
begin(useInterrupt=true) Sets up the pin and (optionally) the interrupt. false = pure polling.
update() Call every loop. Returns true once when a press is confirmed. Non-blocking.
isPressed() Current raw level (active or not).
glitchCount() Number of transients rejected since boot (diagnostics).
setConfirmMs(ms) Confirmation window (default 30 ms).
setDebounceMs(ms) Minimum interval between accepted presses (default 50 ms).

License

MIT — Denis Mattera (Papy Makers)


The library code and comments are in English (src/RobustButton.h). A French-commented copy is available for reference in extras/RobustButton.fr.h — it is documentation only and is not compiled.

About

Robust push-button for electrically noisy environments

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages