diff --git a/.cargo/config.toml b/.cargo/config.toml index 0d031f6..657505f 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -20,5 +20,5 @@ target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) [env] # defmt filters log levels at COMPILE time; without this, info!/debug! are -# stripped and only println! survives. "debug" enables debug/info/warn/error. -DEFMT_LOG = "debug" +# stripped and only println! survives. "info" enables info/warn/error. +DEFMT_LOG = "info" diff --git a/Cargo.toml b/Cargo.toml index 8f28893..9f197e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] # board support: re-exports the HAL as `f411::hal`, plus the L3gd20/Lsm303dlhc # interfaces and the `led` module -f411 = { path = "../code/f411" } +f411 = { path = "../f411" } cortex-m = "0.7.7" cortex-m-rt = "0.7.5" diff --git a/etc/rotary.md b/etc/rotary.md index 1299307..df136d2 100644 --- a/etc/rotary.md +++ b/etc/rotary.md @@ -29,33 +29,32 @@ Target board: **STM32F4-Discovery (STM32F411VE)**. Firmware: `src/main.rs` ## 2. Schematic ``` - STM32F4-Discovery Rotary encoder (EC11, 7-leg) + STM32F4-Discovery Rotary encoder (EC11, 7-leg) ┌──────────────┐ - │ 3V ●───────────┬───────────┬──────────────┐ + │ 3V ●───────────┬────────────┬──────────────┐ │ │ │ │ │ │ │ ┌┴┐ ┌┴┐ │ - │ │ 10k │ │ 10k │ │ │ (pull-ups + │ │ 10k │ │ 10k │ │ │ (pull-ups │ │ └┬┘ └┬┘ │ to 3V) │ │ │ │ │ - │ PE9 (CH1) ●─┼───────────┼────────────● A (CLK) │ + │ PE9 (CH1) ●───────────┼────────────● A (CLK) │ │ │ │ │ │ - │ │ 100n═╪═ 100n═╪═ │ + │ │ 100n ═╪═ 100n ═╪═ │ │ │ │ │ │ - │ PE11 (CH2) ●─┼───────────●────────────┼──● B (DT) │ - │ │ │ │ + │ 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. - └─────────────┘ + │ │ SW1 ●────┘ │ + │ PA0 ●──────────────────────────────────● SW2 │ (push-switch, ‖ B1) + │ GND ●──────┬───────────────────────────────────┘ + │ │ │ mount legs ●● → GND (shield) + └──────────────┘ │ + │ B1 (on-board) also sits 3V ↔ PA0 — + ┌─────┴──────┐ the encoder push-switch is in + │ both 100n │ PARALLEL with it. + │ caps → GND │ + └────────────┘ ``` --- @@ -63,20 +62,26 @@ Target board: **STM32F4-Discovery (STM32F411VE)**. Firmware: `src/main.rs` ## 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) + RC filter — repeat for each channel (A, B): + 3V rail ●━━━┯━━━━━━━━━━━┯━━━━● ← from Discovery 3V + │ │ + [10k] [10k] + A node ┼───→ PE9 │ + B node │ ┼───→ PE11 + [100n] [100n] + │ │ + GND rail ●━━━┷━━━━━━━━━━━┷━━━━● ← from Discovery GND + + + EC11 encoder — straddles the centre trench (┊): + ┌─────────────────────────────┐ + │ A C B ┊ SW1 SW2 │ + └──┬────┬────┬───────┬─────┬──┘ + │ │ │ │ └───────→ PA0 (SW2 ‖ on-board B1 button) + │ │ │ └─────────────→ 3V rail (SW1) + │ │ └─────────────────────→ B node (DT, channel B → PE11) + │ └──────────────────────────→ GND rail (C = common) + └───────────────────────────────→ A node (CLK, channel A → PE9) ``` Power both breadboard rails from the Discovery's **3V** and **GND** pins; tap diff --git a/src/main.rs b/src/main.rs index e520b85..b69d611 100644 --- a/src/main.rs +++ b/src/main.rs @@ -260,6 +260,11 @@ impl SetpointKnob { } } + /// Raw TIM1 counter, for debugging (does the timer see the encoder at all?). + fn raw_count(&self) -> u16 { + self.encoder.count() + } + /// Sample the encoder, fold any rotation into the setpoint, and return it. fn poll(&mut self) -> f32 { let now = self.encoder.count(); @@ -267,11 +272,26 @@ impl SetpointKnob { let delta = now.wrapping_sub(self.last_count) as i16; self.last_count = now; self.accum += delta; + // Any movement at all means TIM1 is wired and counting. No "knob:" lines + // while turning => the timer isn't seeing edges (pull-ups / pins / init). + if delta != 0 { + defmt::debug!( + "knob: count={=u16} delta={=i16} accum={=i16}", + now, + delta, + self.accum + ); + } let detents = self.accum / COUNTS_PER_DETENT; if detents != 0 { self.accum -= detents * COUNTS_PER_DETENT; // keep the remainder self.setpoint_c = (self.setpoint_c + detents as f32 * SETPOINT_STEP_C) .clamp(SETPOINT_MIN_C, SETPOINT_MAX_C); + defmt::debug!( + "knob: {=i16} detent(s) -> setpoint {=f32} C", + detents, + self.setpoint_c + ); } self.setpoint_c } @@ -346,11 +366,12 @@ fn main() -> ! { // temperature to one decimal by hand via deci-degrees. let t_dc = libm::roundf(temp_c * 10.0) as i32; // tenths of a degree C defmt::info!( - "T={=i32}.{=u32} C set={} C {}", + "T={=i32}.{=u32} C set={} C {} qei={=u16}", t_dc / 10, (t_dc % 10).unsigned_abs(), kettle.setpoint(), - kettle.state() + kettle.state(), + knob.raw_count() ); // ---- wait one tick, polling the on-switch + encoder ----