A rotary encoder library for embedded rust applications
angular-velocity
feature flag)Examples use the stm32h7xx-hal
crate and are compatible with any project using embedded-hal
.
It is recommended to use the interrupt driven example
.
rust
fn main() -> ! {
// Configure DT and CLK pins, typically pullup input
let rotary_dt = gpio_pin_1.into_pull_up_input()
let rotary_clk = gpio_pin_2.into_pull_up_input();
// Initialize the rotary encoder
let mut rotary_encoder = RotaryEncoder::new(
rotary_dt,
rotary_clk,
);
// Optional, configure sensitivity if needed
rotary_encoder.set_sensitivity(Sensitivity::Low);
// Application loop
loop {
// Update the encoder, which will compute its direction
rotary_encoder.update();
match rotary_encoder.direction() {
Direction::Clockwise => {
// Increment some value
}
Direction::AntiClockwise => {
// Decrement some value
}
Direction::None => {
// Do nothing
}
}
}
}
Trigger GPIO pin interrupts for both DT
and CLK
on both rising and falling edges
```rust
static ROTARY_ENCODER: Mutex
fn main() -> ! { // Configure DT typically as pullup input & interrupt on rising/falling edges let mut rotarydt = rotarydt.intopullupinput(); rotarydt.makeinterruptsource(syscfg); rotarydt.triggeronedge(exti, Edge::RisingFalling); rotarydt.enableinterrupt(exti); // Configure CLK typically as pullup input & interrupt on rising/falling edges let mut rotaryclk = rotaryclk.intopullupinput(); rotaryclk.makeinterruptsource(syscfg); rotaryclk.triggeronedge(exti, Edge::RisingFalling); rotaryclk.enableinterrupt(exti); // Initialize Rotary Encoder and safely store in static global interrupt::free(|cs| { ROTARYENCODER.borrow(cs).replace(Some( RotaryEncoder::new( rotarydt, rotary_clk, ) )); });
loop {}
} /// Called from the GPIO interrupt vector fn handlerotaryinterrupt() { // Retrieve Rotary Encoder from safely stored static global interrupt::free(|cs| { if let Some(ref mut rotaryencoder) = ROTARYENCODER.borrow(cs).borrowmut().derefmut() { // Borrow the pins to clear the pending interrupt bit (which varies depending on HAL) let mut pins = rotaryencoder.borrowpins(); pins.0.clearinterruptpendingbit(); pins.1.clearinterruptpendingbit(); // Update the encoder, which will compute its direction rotaryencoder.update(); match rotaryencoder.direction() { Direction::Clockwise => { // Increment some value } Direction::AntiClockwise => { // Decrement some value } Direction::None => { // Do nothing } } } }); } ```
For experimental angular velocity support use the RotaryEncoderWithVelocity
struct. This functionality is gated behind the angular-velocity
crate feature flag.
rust
fn main() -> ! {
// Configure DT and CLK pins, typically pullup input
let rotary_dt = gpio_pin_1.into_pull_up_input()
let rotary_clk = gpio_pin_2.into_pull_up_input();
// Initialize Rotary Encoder with Velocity functionality
let mut rotary_encoder = RotaryEncoderWithVelocity::new(
rotary_dt,
rotary_clk,
);
// Optional settings
rotary_encoder.set_sensitivity(Sensitivity::Low);
rotary_encoder.set_velocity_action_ms(5); // The window of time that the velocity may increase
rotary_encoder.set_velocity_inc_factor(0.2); // How quickly the velocity increases over time
rotary_encoder.set_velocity_dec_factor(0.01); // How quickly the velocity decreases over time
// Application loop
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 a monotonously rising time in ms (akin to Arduino's `millis()`)
rotary_encoder.update(current_time);
// Get the velocity
let velocity = rotary_encoder.velocity();
// Match the direction
match rotary_encoder.direction() {
Direction::Clockwise => {
// Increment some value by some factor multiplied by velocity
}
Direction::AntiClockwise => {
// Decrement some value by some factor multiplied by velocity
}
Direction::None => {
// Do nothing
}
}
// As velocity is a function of time, we need to reduce its value over time
// This method could also be called from a Timer
rotary_encoder.decay_velocity();
}
}