Skip to content

Conversation

@obra
Copy link
Member

@obra obra commented Aug 7, 2025

Summary

Fixes encoder sensitivity issues on the Preonic by implementing direction-aware debouncing that eliminates double events and wrong-direction spurious events.

Problem

  • Preonic encoders have 12 physical detents per rotation but generate 24 electrical events
  • Users get double the expected key events (2 events per detent instead of 1)
  • Encoder bounce and rapid direction changes cause spurious events in wrong direction

Root Cause

  • Quadrature encoders produce 2 electrical transitions per mechanical detent
  • SwRotaryEncoder fires callback on every electrical transition
  • Simple counter approaches get out of sync on direction changes

Solution: Direction-Aware Decimation

Implement smart filtering in encoderEventCallback():

  • Track direction for each encoder independently
  • Reset counter on direction changes to prevent wrong-direction events
  • Process every Nth event within same direction (N=2 for Preonic)

Technical Details

// Configuration constant
static constexpr uint8_t ENCODER_STEPS_PER_DETENT = 2;

// Direction-aware decimation logic
static int8_t encoder_last_direction[NUM_ENCODERS] = {0};
static uint8_t encoder_step_counters[NUM_ENCODERS] = {0};

int8_t direction = (step < 0) ? -1 : 1;

// Reset counter on direction change to avoid wrong-direction events
if (encoder_last_direction[encoder_index] \!= direction) {
  encoder_step_counters[encoder_index] = 0;
  encoder_last_direction[encoder_index] = direction;
}

// Only process every Nth event in the same direction
if (++encoder_step_counters[encoder_index] % ENCODER_STEPS_PER_DETENT \!= 0) return;

Results

  • Correct sensitivity: 12 events per rotation (1 per detent)
  • No wrong-direction events: Direction changes reset counter
  • Configurable: Easy to adjust for different encoder types
  • Per-encoder: Independent handling for mixed encoder types

Test Plan

  • Build verification passes
  • Hardware test: Verify 12 events per full rotation
  • Direction test: No spurious events on direction changes
  • Bounce test: Clean events during rapid/partial rotations

🤖 Generated with Claude Code

PROBLEM: Preonic encoders have 12 physical detents per rotation but generate
24 electrical events, causing double the expected key events. Additionally,
encoder bounce and rapid direction changes can cause spurious events in the
wrong direction.

SOLUTION: Implement direction-aware decimation in encoderEventCallback():
- Track direction for each encoder independently
- Reset counter on direction changes to prevent wrong-direction events
- Only process every Nth event within the same direction (N=2 for Preonic)

CONFIGURATION: ENCODER_STEPS_PER_DETENT constant allows adjustment for
different encoder types.

RESULT: Clean 1:1 mapping between physical detents and key events, with
elimination of bounce-induced wrong-direction events.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@obra
Copy link
Member Author

obra commented Aug 7, 2025

This fixes #1469

@obra obra merged commit c29ba86 into master Aug 7, 2025
15 checks passed
@obra obra deleted the feature/preonic-encoder-debouncing branch August 7, 2025 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants