Files
kttl/etc/rotary.md
T
2026-06-28 20:40:29 +10:00

7.4 KiB
Raw Blame History

Rotary Encoder — Setpoint Control Wiring

Adds an EC11-class incremental rotary encoder to the kttl controller so the temperature setpoint can be dialled in live, and so the encoder's push-switch acts as the on-switch (identical to the board's B1 button).

Target board: STM32F4-Discovery (STM32F411VE). Firmware: src/main.rs (SetpointKnob, TIM1 in encoder mode).


1. Pin assignment

Encoder leg Discovery pin Function Extra parts
A (CLK) PE9 (TIM1_CH1) quadrature channel A 10 kΩ → 3V, 100 nF → GND
B (DT) PE11 (TIM1_CH2) quadrature channel B 10 kΩ → 3V, 100 nF → GND
C (common) GND rotary common —
SW1 3V push-switch leg —
SW2 PA0 push-switch leg (‖ B1) —
mount ×2 GND shield / mechanical optional

Use 3V, not 5V. The STM32F411 is a 3.3 V part; the pull-ups set the logic high level seen by the pins, and the switch drives PA0 directly. 3V matches the MCU and the existing B1 button exactly — no level shifting.


2. Schematic

   STM32F4-Discovery                         Rotary encoder (EC11, 7-leg)
   ┌──────────────┐
   │           3V ●───────────┬───────────┬──────────────┐
   │              │           │            │              │
   │              │          ┌┴┐          ┌┴┐             │
   │              │     10k  │ │     10k  │ │             │   (pull-ups
   │              │          └┬┘          └┬┘             │    to 3V)
   │              │           │            │              │
   │ PE9  (CH1) ●─┼───────────┼────────────●  A (CLK)     │
   │              │           │            │              │
   │              │      100n═╪═      100n═╪═             │
   │              │           │            │              │
   │ PE11 (CH2) ●─┼───────────●────────────┼──● B (DT)    │
   │              │                        │              │
   │              │                        ●  C (common)──┼──┐
   │              │                                       │  │
   │              │                  SW1 ●────────────────┘  │
   │          PA0 ●───────────────────┐  │   (push-switch)   │
   │              │                    │  ●  SW2 ─────────────┼──┐
   │          GND ●──────┬─────────────┼─────────────────────┘  │
   │              │      │             │   mount legs ●●─────────┘
   └──────────────┘      │             │              (to GND, shield)
                         │             │
                  ┌──────┴──────┐      │  B1 (on-board) also sits
                  │ both 100n   │      │  3V ↔ PA0 — encoder SW is
                  │ caps → GND  │      └─ in PARALLEL with it.
                  └─────────────┘

3. Breadboard view

        3V rail  ●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━●  ← jumper from Discovery 3V
        GND rail ●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━●  ← jumper from Discovery GND
        ┌──────────────────────────────────────────────────┐
        │  [10k]   [10k]          encoder straddles trench   │
        │   │ │     │ │         ┌──────────────────────┐    │
   3V ──┴─┘ └──┬──┘ └──┬──────┤ A    C    B │ SW1  SW2 ├─┐  │
        │      │       │       └──┼────┼────┼───┼────┼──┘ │  │
        │   [100n]  [100n]        │   GND   │  3V   PA0   │  │
        │     │       │           │         │             │  │
   GND ─┴─────┴───────┴───────────┘         │             │  │
        │                                   │             │  │
        │   A → PE9      B → PE11      SW2 → PA0          │  │
        └──────────────────────────────────────────────────┘
            (jumper)     (jumper)      (jumper, ‖ B1)

Power both breadboard rails from the Discovery's 3V and GND pins; tap everything else off those rails.


4. Why the resistors and caps

  • 10 kΩ pull-ups (A→3V, B→3V): required. This HAL's QEI driver puts the pins in alternate-function mode without enabling the internal pull-ups, so the channels would float. With the encoder common tied to GND, the lines idle high and each detent pulls them low.
  • 100 nF caps (A→GND, B→GND): recommended. Each forms an RC low-pass with its 10 kΩ pull-up, τ = R·C = 10 kΩ · 100 nF = 1 ms — long enough to absorb the ~1–5 ms of mechanical contact bounce, short enough that no hand-turned knob outruns it. Combined with the STM32 inputs' Schmitt-trigger hysteresis, this turns each bounced click into one clean edge. The cap's closure surge also provides wetting current to keep the low-current (~0.3 mA) contacts reliable.

5. Behaviour (firmware)

  • TIM1 encoder mode counts quadrature edges (×4). EC11s emit one full cycle per detent → 4 counter steps per detent (COUNTS_PER_DETENT).
  • Each detent moves the setpoint by SETPOINT_STEP_C (1 °C), clamped to [SETPOINT_MIN_C, SETPOINT_MAX_C] = [25, 100] °C. Power-on default is SETPOINT_DEFAULT_C = 25 °C.
  • The encoder is sampled every POLL_MS (20 ms) in the main poll loops (normal and fault), so the setpoint tracks smoothly and the per-second status log prints the live value.
  • Push-switch: wired in parallel with B1 (3V ↔ PA0). Pressing the knob is electrically identical to the board button and is handled by the existing PA0 polling — no extra code.

6. Alternatives

  • Drop the caps: enable TIM1's built-in digital input filter (sample-count debounce) in firmware instead. The RC filter is simpler and also gives wetting current + on-wire noise rejection, so it's preferred for a breadboard build.
  • KY-040 module: has onboard pull-ups — power it from 3.3 V (not 5 V) so CLK/DT/SW idle at a level the MCU pins accept; the external 10 kΩ/100 nF here can then be omitted.