Added doc
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# Quadratur-Encoder
|
||||
|
||||
**Dateien:** `hal/encoder.h`, `hal/encoder.cpp`, `config/pins.h`
|
||||
|
||||
## Hardware
|
||||
|
||||
4 mechanische Quadratur-Encoder mit je 2 Phasen-Pins (A, B). Pins sind INPUT_PULLUP.
|
||||
Encoder-SW-Tasten laufen **nicht** durch diesen HAL, sondern durch den Matrix-Scan (COL_0).
|
||||
|
||||
## Dekodierung
|
||||
|
||||
4-State-Lookup-Table über `(prev_state << 2) | cur_state`:
|
||||
|
||||
```
|
||||
Zustand = (A << 1) | B → 4 Bits: 00 / 01 / 10 / 11
|
||||
LUT[prev<<2 | cur] → +1 (CW), -1 (CCW), 0 (ungültig/Prellen)
|
||||
```
|
||||
|
||||
Mechanische Encoder erzeugen 4 Flanken pro Raste → Akkumulator zählt Halbschritte.
|
||||
Ein Event wird erst gefeuert wenn `|accum| >= 4` (= ein vollständiger Klick).
|
||||
|
||||
## ISR-Aufbau
|
||||
|
||||
8 ISR-Wrapper (je einer pro Pin, da `attachInterrupt` keinen Parameter unterstützt):
|
||||
|
||||
```cpp
|
||||
static void isr_enc0_a() { handle_encoder(0); }
|
||||
static void isr_enc0_b() { handle_encoder(0); }
|
||||
// ... analog für Encoder 1–3
|
||||
```
|
||||
|
||||
`attachInterrupt(..., CHANGE)` auf beiden Pins jedes Encoders.
|
||||
|
||||
`handle_encoder()` → `encoder_cb(enc_id, direction)` → `CEventQueue::push(ENC_CW / ENC_CCW)`
|
||||
|
||||
## ISR-Sicherheit
|
||||
|
||||
- `s_state[]` und `s_accum[]` sind `volatile`
|
||||
- `CEventQueue::push()` ist ISR-sicher (atomare Index-Inkremente auf Single-Core-M0+, kein Heap)
|
||||
- Der Callback-Pointer `s_cb` wird einmalig in `setup()` gesetzt, bevor Interrupts aktiviert werden
|
||||
|
||||
## Initialisierung
|
||||
|
||||
Initialer Zustand von A/B wird beim `encoder_init()` gelesen damit der erste Interrupt korrekt ausgewertet wird (kein "Phantom-Step" beim Einschalten).
|
||||
Reference in New Issue
Block a user