基于RT-thread的正交编码测速

一、介绍

通过 RT-Thread 提供的 I/O 设备管理接口来访问脉冲编码器设备,实现正交编码测速。

参考链:Pulse Encoder 设备 、  HWTIMER 设备

正交编码原理这里就不介绍了,网上资料很多,直接进入正题。

硬件平台:AT32F407(需要增加驱动) 或者 STM32F107

系统:RT-thread V4.1.0

二、应用代码

/*
//计算尾轴转速
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define DBG_SECTION_NAME "rot_speed"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>

#define HWTIMER_DEV_NAME   "timer3"     /* 定时器名称 */
#define PULSE_ENCODER_DEV_NAME    "pulse4"    /* 脉冲编码器名称 */

rt_device_t pulse_encoder_dev = RT_NULL;   /* 脉冲编码器设备句柄 */

#define PERIOD_TIME  2000  //采样周期ms t
#define PULSE_PER     4    //每转采样一次,有四个脉冲(N)

//计算公式:
//每毫秒采样的脉冲数:一定周期(ms)内采样的总脉冲数/周期      
//4分频,一圈4个脉冲
//1ms的圈数:一定周期(ms)内采样的总脉冲数/(周期 *4)
//转速(圈/分钟):一定周期(ms)内采样的总脉冲数/(周期 *4)    乘以60*1000(分钟)

/* 定时器超时回调函数 */
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
     rt_int32_t count;
    /* 读取脉冲编码器计数值 */
    rt_device_read(pulse_encoder_dev, 0, &count, 1);
    /* 清空脉冲编码器计数值 */
    rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_CLEAR_COUNT, RT_NULL);

    int speed = 60*1000*count/(PERIOD_TIME*PULSE_PER);

    LOG_D("get count:%d, speed:%d",count,speed); 
        
    return 0;
}



//脉冲计数初始化
static int pulse_encoder_init()
{
    rt_err_t ret = RT_EOK;
    
    rt_uint32_t index;
   
    /* 查找脉冲编码器设备 */
    pulse_encoder_dev = rt_device_find(PULSE_ENCODER_DEV_NAME);
    if (pulse_encoder_dev == RT_NULL)
    {
        LOG_E("pulse encoder sample run failed! can't find %s device!", PULSE_ENCODER_DEV_NAME);
        return RT_ERROR;
    }

    /* 以只读方式打开设备 */
    ret = rt_device_open(pulse_encoder_dev, RT_DEVICE_OFLAG_RDONLY);
    if (ret != RT_EOK)
    {
        rt_kprintf("open %s device failed!\n", PULSE_ENCODER_DEV_NAME);
        return ret;
    }

    return ret;
}

//定时周期初始化
static int hwtimer_init()
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find(HWTIMER_DEV_NAME);
    if (hw_dev == RT_NULL)
    {
        LOG_E("hwtimer sample run failed! can't find %s device!", HWTIMER_DEV_NAME);
        return RT_ERROR;
    }

    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    if (ret != RT_EOK)
    {
        LOG_E("open %s device failed!", HWTIMER_DEV_NAME);
        return ret;
    }

    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb);

    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    if (ret != RT_EOK)
    {
        LOG_E("set mode failed! ret is :%d", ret);
        return ret;
    }

    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 0;      /* 秒 */
    timeout_s.usec = PERIOD_TIME*1000;     /* 微秒 */

    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        LOG_E("set timeout value failed");
        return RT_ERROR;
    }

    /* 延时ms */
    rt_thread_mdelay(500);

    /* 读取定时器当前值 */
    rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
    LOG_D("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
    
    return ret;
}


int  tail_rot_speed_init(){

    pulse_encoder_init();
    hwtimer_init();
}

三、bsp驱动

如果使用的是STM32的bsp包,驱动是不需要修改的,可以直接使用;如果是AT32的平台需要添加驱动。
注意:
        在RT-thread提供的bsp中,在STM32中有脉冲编码器的驱动        
                  bsp\stm32\libraries\HAL_Drivers\drv_pulse_encoder.c
        在at32中没有发现脉冲编码器对应的驱动,需要增加,自己根据STM32的驱动进行了修改。

驱动链接地址:基于AT32的RT-thread脉冲编码驱动

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值