rotary working

This commit is contained in:
Nathan Rashleigh committed 2026-06-30 11:32:12 +10:00
1 parent 5386699f7b
commit 143f524f2a
4 files changed
+63 -37

No files matched your search

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