#encoder #rotary #real-time #driver

无std sb-rotary-encoder

嵌入式系统旋转编码器处理器

1个不稳定版本

0.1.0 2023年4月15日

1668嵌入式开发

MIT 许可证

15KB
255

sb-rotary-encoder

无std Rust包,用于处理旋转编码器信号。

特性

  • 平台无关,依赖最少。
  • 脉冲分割,用于处理有止点的编码器。
  • 通过时间戳计算速度,可选的加速度。
  • 整数处理,以获得最佳性能。
  • 自动对齐有止点的编码器(见下文说明)。

有止点的编码器

市场上有两种旋转编码器:有止点的和无止点的。有止点提供了步进控制的体验,但也有一些需要注意的副作用。

脉冲数量

止点的分辨率通常低于生成的脉冲分辨率。因此,需要几个脉冲才能达到一个步骤并触发相应的事件。在实际应用中,这些编码器模型通常每个止点使用2个或4个脉冲。

切换点

为了获得最佳的用户体验,编码器应该在达到下一个步骤时触发事件,即达到每个止点的脉冲数量时。不幸的是,由于编码器转动非常快或由于组件本身的自然磨损,有时可能会错过脉冲检测。在这种情况下,明显的切换点会移动,这在进一步的移动中是可以注意到的。

使用示例

对于大多数用例,建议处理间隔为1ms,这适合RTOS或SysTick计数器的常见1kHz频率设置。

// Number of pulses required for one step. 4 is a typical value for encoders with detents.
const PULSE_DIVIDER: i32 = 4;

// Update frequency in Hz, used for velocity calculation
const UPDATE_FREQUENCY: i32 = 1000;

// Create a new instance of an encoder.
let mut encoder = sb_rotary_encoder::RotaryEncoder::new();

// Some dummy input signals to be replaced by the real pin states.
let input_a = true;
let input_b = false;

// Some dummy tick value, can also be `None` if you don't want to use the velocity feature.
let tick = Some(42);

// Process the input and get an event if a step was recognized.
if let Some(event) = encoder.update(input_a, input_b, tick, PULSE_DIVIDER) {
    println!("{:?}", event);

    // If timestamps were used, the velocity can be calculated.
    // This is done as an additional step because it requires some calculations
    // which may not be always needed.
    if let Some(velocity) = event.velocity(UPDATE_FREQUENCY) {
        println!("{:?}", velocity);

        // The velocity allows to calculate a dynamic step value to accelerate the encoder
        // when moved quickly.
        let acceleration = velocity >> 4;
        let step = event.step() + (event.step() * acceleration);
    }
}

测试

运行 cargo test 进行单元测试。

许可证

在MIT许可证下发布。对本项目的任何贡献都必须在相同的许可证条件下提供。

作者:Oliver Rockstedt [email protected]

无运行时依赖