mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
fix(ui): debounce the Hall sensor poll against reed-switch contact bounce
pollHallSensor() acted on the raw pin reading immediately, unlike every other physical-input path in this file (MomentaryButton, pollCardKB()'s own last-raw edge check). A cheap mechanical reed switch -- one of the two sensor types the docs explicitly recommend wiring here, alongside a solid-state Hall IC -- can chatter for a few ms while the magnet crosses the trigger distance, so a poll every loop() tick during that window could flip _locked and fire _display->turnOff()/turnOn() repeatedly in that short span: wasted work on any panel, and a real cost on e-ink where each is a slow full-panel operation. A raw reading now has to hold steady for HALL_DEBOUNCE_MS (25ms, same threshold as MomentaryButton's ISR_DEBOUNCE_MS) before it replaces _hall_magnet_present and triggers the lock/unlock actions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2255,11 +2255,24 @@ void UITask::pollCardKB() {
|
||||
// there's nothing to show), opening unlocks and wakes it, with no combo or
|
||||
// keypress either way. Independent of Auto-lock (Settings > Display), which is
|
||||
// a timeout-driven setting -- this is a direct physical event.
|
||||
//
|
||||
// Debounced against a mechanical reed switch chattering for a few ms as the
|
||||
// magnet crosses the trigger distance -- a raw flip only becomes the new
|
||||
// _hall_magnet_present once it's been steady for HALL_DEBOUNCE_MS, so a bounce
|
||||
// can't fire the lock/unlock actions (each including a full display
|
||||
// off/on -- slow and disruptive on e-ink) more than once per real transition.
|
||||
void UITask::pollHallSensor() {
|
||||
#if defined(PIN_HALL_SENSOR)
|
||||
bool present = HALL_ACTIVE_HIGH ? (digitalRead(PIN_HALL_SENSOR) == HIGH)
|
||||
: (digitalRead(PIN_HALL_SENSOR) == LOW);
|
||||
if (present == _hall_magnet_present) return;
|
||||
bool raw = HALL_ACTIVE_HIGH ? (digitalRead(PIN_HALL_SENSOR) == HIGH)
|
||||
: (digitalRead(PIN_HALL_SENSOR) == LOW);
|
||||
if (raw != _hall_candidate) {
|
||||
_hall_candidate = raw;
|
||||
_hall_candidate_since = millis();
|
||||
}
|
||||
if (_hall_candidate == _hall_magnet_present) return; // no debounced change yet
|
||||
if (millis() - _hall_candidate_since < HALL_DEBOUNCE_MS) return; // not steady long enough
|
||||
|
||||
bool present = _hall_candidate;
|
||||
_hall_magnet_present = present;
|
||||
|
||||
if (present) { // cover closed
|
||||
|
||||
@@ -219,6 +219,13 @@ class UITask : public AbstractUITask {
|
||||
#define HALL_ACTIVE_HIGH 0
|
||||
#endif
|
||||
bool _hall_magnet_present = false;
|
||||
// Contact-bounce guard for a mechanical reed switch (a Hall-effect IC reads
|
||||
// clean, but the docs recommend either): a raw reading only replaces
|
||||
// _hall_magnet_present once it's held steady for HALL_DEBOUNCE_MS, same
|
||||
// threshold and reasoning as MomentaryButton's ISR_DEBOUNCE_MS.
|
||||
static const uint32_t HALL_DEBOUNCE_MS = 25;
|
||||
bool _hall_candidate = false;
|
||||
uint32_t _hall_candidate_since = 0;
|
||||
#endif
|
||||
void pollHallSensor();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user