直流无刷电机速度检测采用什么方式采集脉冲数更好?

2019-07-20 19:46发布

本帖最后由 特朗姆斯 于 2016-8-24 15:12 编辑

直流无刷电机控制方式比较简单,直接用PWM控制速度即可。

目前碰到的问题是在相同的PWM占空比下,两个相同的电机真实呈现的速度不一样,因此我想到了利用速度检测功能来对其进行校准。但是速度检测功能令我很头疼,目前采用的是把速度检测引脚连接到I/O引脚,用外部中断的方式采集一秒钟内的脉冲数来进行判断。按原子哥的说法是这种方式会使ARM频繁进入中断,不是理想的实现方式。

想到过用定时器捕获输入的方式,看完datasheet中关于定时器捕获输入的内容,似乎也是要通过中断来实现脉冲捕获,那和我使用的外部中断采集没有区别。

另外还有看到定时器外部时钟模式2,可以通过TIMx_CHx引脚触发开始计数,通过TIMx_ETR引脚来对脉冲进行计数。使用这种模式虽然可以不使用中断,但是要占用两个定时器,这两个定时器还必须是有TIMx_ETR引脚的高级定时器,加上额外的I/O资源开销似乎也是得不偿失。


目前研究下来差不多是上述情况,希望有大神给予指引。


ps:我用的直流无刷电机有配套的控制器,ARM采集的脉冲数由控制器发出。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
22条回答
yyx112358
1楼-- · 2019-07-20 21:12
特朗姆斯 发表于 2016-8-24 13:57
可能是我没讲清楚,我用了一个控制器控制直流无刷电机,这个控制器会返回脉冲数。

我想要统计1s内采 ...

我以前试过,这个方法至少可以测到5Hz~25MHz的频率,精度0.03%以下
[mw_shl_code=c,true]//TIM7->100ms
//TIM2_CH2->PB3
void TIM_Cnt_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        TIM_DeInit(TIM2);
        TIM_DeInit(TIM7);
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM7,ENABLE);          //TIM2时钟使能   
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);         //使能PORTA时钟       
//IO       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //GPIOA0
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;        //速度100MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //下拉
        GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PA0
       
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_TIM2); //PA0复用位定时器5
//TIM2配置       
        TIM_TimeBaseStructure.TIM_Prescaler=0;  //定时器分频
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseStructure.TIM_Period=0xFFFFFFFF;   //自动重装载值
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
       
        TIM_TIxExternalClockConfig(TIM2,TIM_TIxExternalCLK1Source_TI2,TIM_ICPolarity_Rising,0);//外部时钟源
//TIM7        100ms       
        TIM_TimeBaseStructure.TIM_Prescaler=18000-1;  //定时器分频
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseStructure.TIM_Period=1000-1;   //自动重装载值
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
//中断
  NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器、
        TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);//允许更新中断 ,允许CC1IE捕获中断       

        TIM_Cmd(TIM7,ENABLE );         //使能定时器5
  TIM_Cmd(TIM2,ENABLE );         //使能定时器5       
}
volatile u32 TIM_ExtCntFreq;
u32 TIM7_LastCnt;
void TIM7_IRQHandler(void)
{
        char        str[32];
        TIM_ExtCntFreq=(TIM2->CNT-TIM7_LastCnt)*10;
        sprintf(str,"%3.3f",TIM_ExtCntFreq/1000.0);//必须加这一句,莫明其妙
        TIM7_LastCnt=TIM2->CNT;
        TIM_ClearITPendingBit(TIM7,TIM_IT_Update);
}[/mw_shl_code]
无休
2楼-- · 2019-07-21 01:05
 精彩回答 2  元偷偷看……
特朗姆斯
3楼-- · 2019-07-21 03:18
 精彩回答 2  元偷偷看……
无休
4楼-- · 2019-07-21 06:18
特朗姆斯 发表于 2016-8-24 11:16
脉冲是由直流无刷电机提供的,不是主定时器提供脉冲

脉冲怎么会是由电机提供的,电机可以给自身提供脉冲?你用了编码器的吧?
yyx112358
5楼-- · 2019-07-21 11:07
配置两个定时器,定时器a设置为外部时钟计数器模式,定时器b设置为定时器(比如50ms溢出一次),然后定时器b中断函数中统计定时器a在这段时间内的增量就行
止天
6楼-- · 2019-07-21 11:32
本帖最后由 止天 于 2016-8-24 11:35 编辑

定时器捕获输入可以用dma   我用过,
计数模式只是用频率低的  

一周热门 更多>