A rotary encoder library for embedded rust applications
All examples are based on the stm32h7xx-hal
, but are compatible with any project using embedded-hal
.
Its highly recommended to use the GPIO Interrupt driven implementation. Interrupts should occur on rising and falling edges for both CLK
and DT
.
```rust fn main() -> ! { // ... Initialize DT and CLK pins as desired. Typically PullUp Push-Pull. let mut rotaryencoder = RotaryEncoder::new( rotarydt, rotary_clk, );
// Optional: to configure sensitivity if needed
rotary_encoder.set_sensitivity(Sensitivity::Low);
loop {
// Update the encoder, which will compute its direction
rotary_encoder.update();
// Get the rotary values
let direction = rotary_encoder.direction();
if direction == Direction::Clockwise {
// Increment some value
} else if direction == Direction::AntiClockwise {
// Decrement some value
}
}
} ```
```rust
static ROTARY_ENCODER: Mutex
fn main() -> ! { // ... Initialize DT and CLK pins as desired. Typically PullUp Push-Pull. // ... Initialize interrupt on rising and falling edge interrupt::free(|cs| { ROTARYENCODER.borrow(cs).replace(Some( RotaryEncoder::new( rotarydt, rotary_clk, ) )); });
loop {}
}
fn handlerotary(rotaryencoder: &mut RotaryEncoder) { // Update the state of the rotary-encoder rotary_encoder.update();
// Get the rotary values
let direction = rotary_encoder.direction();
if direction == Direction::Clockwise {
// Increment some value
} else if direction == Direction::AntiClockwise {
// Decrement some value
}
}
fn EXTI1() { // DT rising or falling edge interrupt interrupt::free(|cs| { if let Some(ref mut rotaryencoder) = ROTARYENCODER.borrow(cs).borrowmut().derefmut() { // Clear DT GPIO EXTI interrupt rotaryencoder .borrowpins() .0 .clearinterruptpending_bit();
handle_rotary(rotary_encoder);
}
});
}
fn EXTI2() { // CLK rising or falling edge interrupt interrupt::free(|cs| { if let Some(ref mut rotaryencoder) = ROTARYENCODER.borrow(cs).borrowmut().derefmut() { // Clear CLK GPIO EXTI interrupt rotaryencoder .borrowpins() .1 .clearinterruptpending_bit();
handle_rotary(rotary_encoder);
}
});
} ```
If angular velocity is required, then the following example could be used:
```rust fn main() -> ! { // ... Initialize DT and CLK pins as desired. Typically PullUp Push-Pull. // ... Initialize interrupt on rising and falling edge let mut rotaryencoder = RotaryEncoderWithVelocity::new( rotarydt, rotary_clk, // optional configuration values to tweak velocity function Option::None, Option::None, Option::None, );
// Optional: to configure sensitivity if needed
rotary_encoder.borrow_inner().set_sensitivity(Sensitivity::Low);
loop {
// Update the encoder which will compute its direction and velocity.
// As velocity is a function of time, we need the current time.
// current_time should be derived from the RTC and SysTick.
rotary_encoder.update(current_time);
// Get the direction & velocity
let direction = rotary_encoder.direction();
let velocity = rotary_encoder.velocity();
if direction == Direction::Clockwise {
// Increment some value
} else if direction == Direction::AntiClockwise {
// Decrement some value
}
// As velocity is a function of time, we need to reduce its value over time.
// This value could also be called from a Timer.
rotary_encoder.decay_velocity();
}
} ```