Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dial backlash (needs testing) #31

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/bootload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ pub fn jump_to_bootloader_if_requested(dp: &stm32::Peripherals) {
let magic_num: u32 = read_backup_register(dp);

if magic_num == MAGIC_BOOTLOADER_NUMBER {
enable_backup_domain(&dp);
enable_backup_domain(dp);
write_to_backup_register(0, dp);
disable_backup_domain(&dp);
disable_backup_domain(dp);

unsafe {
cortex_m::asm::bootload(BOOTLOADER_FIRMWARE_MEMORY_LOCATION as *const u32);
Expand Down
52 changes: 45 additions & 7 deletions src/counter.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,64 @@
use hal::{prelude::*, qei::Qei, stm32::TIM1};
use hal::{
prelude::*,
qei::Qei,
stm32::TIM1,
timer::{Instant, MonoTimer},
};
use stm32f4xx_hal as hal;

pub struct Counter<PINS> {
const DETENT_RESET_TIMOUT_MS: u32 = 200;

pub struct Counter<'a, PINS> {
qei: Qei<TIM1, PINS>,
// Cache for the count returned by qei for detecting changes
last_count: u16,
timer: &'a MonoTimer,
last_update: Instant,
diff_accumulator: i16,
}

impl<PINS> Counter<PINS> {
pub fn new(qei: Qei<TIM1, PINS>) -> Self {
impl<'a, PINS> Counter<'a, PINS> {
pub fn new(qei: Qei<TIM1, PINS>, timer: &'a MonoTimer) -> Self {
let last_count = qei.count();
Counter { qei, last_count }
Counter { qei, last_count, last_update: timer.now(), timer, diff_accumulator: 0 }
}

pub fn poll(&mut self) -> Option<i8> {
let count = self.qei.count();
let diff = count.wrapping_sub(self.last_count) as i16;

let diff = self.update_counts(count);

if diff.abs() >= 4 {
self.last_count = count;
self.diff_accumulator = 0;
Some((diff / 4) as i8)
} else {
None
}
}

// Sometimes the accumulator gets out of sync with the physical detents. We require count to
// increment by 4 to fire a single tick but when the zero of accumulator lands in between
// detents (because of noise) we get backlash or missed ticks.
// Assume that when the dial rests for more than DETENT_RESET_TIMOUT_MS it is aligned to a detent
// and reset the accumulator.
fn update_counts(&mut self, count: u16) -> i16 {
if count != self.last_count {
self.last_update = self.timer.now();
}

if self.accumulator_timed_out() {
self.diff_accumulator = 0;
}

self.diff_accumulator += self.last_count.wrapping_sub(count) as i16;
self.last_count = count;

self.diff_accumulator
}

fn accumulator_timed_out(&self) -> bool {
let timeout_ticks =
self.timer.frequency().0 as f32 * (DETENT_RESET_TIMOUT_MS as f32 / 1000.0);
self.last_update.elapsed() > timeout_ticks as u32
}
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn main() -> ! {
let rotary_encoder_pins = (gpioa.pa8.into_alternate_af1(), gpioa.pa9.into_alternate_af1());
let rotary_encoder = Qei::new(rotary_encoder_timer, rotary_encoder_pins);

let mut counter = Counter::new(rotary_encoder);
let mut counter = Counter::new(rotary_encoder, &timer);

let button_pin = gpioa.pa10.into_pull_up_input();
let debounced_encoder_pin = Debouncer::new(button_pin, Active::Low, 30, 3000);
Expand Down
Loading