野火电子论坛

标题: 立创·梁山派开发板-21年电赛F题-送药小车-如何计算小车轮... [打印本页]

作者: LCKFB    时间: 2023-7-21 11:18
标题: 立创·梁山派开发板-21年电赛F题-送药小车-如何计算小车轮...
送药小车代码仓库:https://gitee.com/lcsc/medical_car更好的观看体验请去:https://dri8c0qdfb.feishu.cn/wiki/UjwwwO0KZii5bykPcE4cJZafnAg
送药小车立创开源平台资料:https://oshwhub.com/li-chuang-kai-fa-ban/21-dian-sai-f-ti-zhi-neng-song-yao-xiao-che


如何计算轮子转速推荐查看资料编码器计数原理与电机测速原理——多图解析
在这里,我们选用的电机是直流减速电机带霍尔编码器接口,GD32也带硬件正交编码器。
简要介绍正交编码器(Quadrature Encoder)是一种常用于测量机械设备(比如电机、滑台,伸缩杆等)旋转或线性运动的速度和位置的传感器。它具有两个输出信号通道A和B,它们分别输出正交相位差90度的脉冲信号。通过测量这些脉冲信号,可以获得设备的运动速度和方向。关于正交编码器测速,主要有三种方法:M法、T法和M/T法。



M法、T法和M/T法都是常用的正交编码器测速方法,它们各有优缺点。根据实际应用需求,可以选择合适的测速方法以获得最佳的测速性能。
用伪代码的方式实现一下测速代码宏定义及公共变量
  1. #include "gd32fxxx.h"

  2. #define MOTOR_PULSE_PER_REVOLUTION 13
  3. #define MOTOR_REDUCTION_RATIO 20
  4. #define MOTOR_WHEEL_STRAIGHT_MM 64.0
  5. #define TIME_INTERVAL_MS 20

  6. #define PULSE_TO_METER_FACTOR (MOTOR_WHEEL_STRAIGHT_MM * 3.1415926 / (1000 * MOTOR_PULSE_PER_REVOLUTION * MOTOR_REDUCTION_RATIO * 4))

  7. volatile uint32_t pulse_count = 0;
  8. volatile uint32_t last_pulse_time = 0;
复制代码

1. M法(脉冲计数法)
  1. void encoder_init(void) {
  2.     // 初始化硬件正交编码器功能,使能四倍频
  3. }

  4. void timer_init(void) {
  5.     // 初始化定时器,设置固定的时间间隔为20ms
  6.     // 配置中断优先级和使能中断
  7. }

  8. void TIMERx_IRQHandler(void) { // 定时器中断处理函数
  9.     // 检查定时器更新中断标志
  10.     if (timer_interrupt_flag_get(TIMERx, TIMER_INT_FLAG_UP) != RESET) {
  11.         // 计算速度,单位为m/s
  12.         float speed = (float)pulse_count / (TIME_INTERVAL_MS / 1000.0) * PULSE_TO_METER_FACTOR;
  13.         // 重置脉冲计数
  14.         pulse_count = 0;
  15.         // 清除定时器更新中断标志
  16.         timer_interrupt_flag_clear(TIMERx, TIMER_INT_FLAG_UP);
  17.     }
  18. }

  19. int main(void) {
  20.     // 初始化编码器
  21.     encoder_init();
  22.     // 初始化定时器
  23.     timer_init();
  24.     while (1) {
  25.         // 处理其他任务或进入低功耗模式
  26.     }
  27. }
复制代码

2. T法(周期测量法)
  1. void encoder_init(void) {
  2.     // 初始化硬件正交编码器功能,使能四倍频
  3.     // 初始化输入捕获,用于测量编码器A通道的脉冲周期
  4.     // 配置中断优先级和使能中断
  5. }

  6. void TIMERx_IRQHandler(void) { // 输入捕获中断处理函数
  7.     // 检查输入捕获中断标志
  8.     if (timer_interrupt_flag_get(TIMERx, TIMER_INT_FLAG_CCx) != RESET) {
  9.         // 读取当前脉冲时间
  10.         uint32_t current_pulse_time = timer_channel_capture_value_register_read(TIMERx, TIMER_CH_x);
  11.         // 计算脉冲周期
  12.         uint32_t pulse_period = current_pulse_time - last_pulse_time;
  13.         // 更新上一次脉冲时间
  14.         last_pulse_time = current_pulse_time;

  15.         // 计算速度,单位为m/s
  16.         float speed = 1.0 / pulse_period * PULSE_TO_METER_FACTOR;
  17.         // 清除输入捕获中断标志
  18.         timer_interrupt_flag_clear(TIMERx, TIMER_INT_FLAG_CCx);
  19.     }
  20. }

  21. int main(void) {
  22.     // 初始化编码器
  23.     encoder_init();
  24.     while (1) {
  25.         // 处理其他任务或进入低功耗模式
  26.     }
  27. }
复制代码

3. M/T法
  1. void encoder_init(void) {
  2.     // 初始化硬件正交编码器功能,使能四倍频
  3.     // 初始化输入捕获,用于测量编码器A通道的脉冲周期
  4.     // 配置中断优先级和使能中断
  5. }

  6. void timer_init(void) {
  7.     // 初始化定时器,设置固定的时间间隔为20ms
  8.     // 配置中断优先级和使能中断
  9. }

  10. void TIMERx_IRQHandler(void) { // 输入捕获中断处理函数
  11.     // 检查输入捕获中断标志
  12.     if (timer_interrupt_flag_get(TIMERx, TIMER_INT_FLAG_CCx) != RESET) {
  13.         // 读取当前脉冲时间
  14.         uint32_t current_pulse_time = timer_channel_capture_value_register_read(TIMERx, TIMER_CH_x);
  15.         // 计算脉冲周期
  16.         uint32_t pulse_period = current_pulse_time - last_pulse_time;
  17.         // 更新上一次脉冲时间
  18.         last_pulse_time = current_pulse_time;
  19.         // 增加脉冲计数
  20.         pulse_count++;

  21.         // 清除输入捕获中断标志
  22.         timer_interrupt_flag_clear(TIMERx, TIMER_INT_FLAG_CCx);
  23.     }
  24. }

  25. void TIMERy_IRQHandler(void) { // 定时器中断处理函数
  26.     // 检查定时器更新中断标志
  27.     if (timer_interrupt_flag_get(TIMERy, TIMER_INT_FLAG_UP) != RESET) {
  28.         // 计算速度,单位为m/s
  29.         float speed = (float)pulse_count / (float)pulse_period * PULSE_TO_METER_FACTOR;
  30.         // 重置脉冲计数
  31.         pulse_count = 0;
  32.         // 清除定时器更新中断标志
  33.         timer_interrupt_flag_clear(TIMERy, TIMER_INT_FLAG_UP);
  34.     }
  35. }

  36. int main(void) {
  37.     // 初始化编码器
  38.     encoder_init();
  39.     // 初始化定时器
  40.     timer_init();
  41.     while (1) {
  42.         // 处理其他任务或进入低功耗模式
  43.     }
  44. }
复制代码



实际使用的程序实际使用中我用的是M法测速,详情请看2_code->applications->bsp_encoder.c文件。









欢迎光临 野火电子论坛 (https://www.firebbs.cn/) Powered by Discuz! X3.4