OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9952|回复: 28

现在可以用编码器读取计数器的值了,但是怎么去测速呢?

[复制链接]

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
发表于 2015-7-21 23:11:27 | 显示全部楼层 |阅读模式
5金钱
编码器怎么去测速呢?怎么通过PWM去控制直流电机呢?求教各位大神!最近在用直流电机,希望大家可以帮帮忙!谢谢啦!

最佳答案

查看完整内容[请看2#楼]

你的两个中断服务程序里,一个count,一个i均是局部变量,每次进中断它们的值都是0; 整个测速过程存在四种状态:处于起始捕获状态,处于编码器工作状态,处于尾捕获状态,TIM2超时状态; 每一状态需要做的事情当然也是不一样的;TIM2和TIM3均共享当前状态,你可以先画出一个流程图,不急着先写程序; 另外,n=60*(1000000)*M1/(M2*4*400);  这里变量的类型需要注意其最大边界?M2的高频脉冲计数很可能会溢出的,需要 进 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-21 23:11:28 | 显示全部楼层
你的两个中断服务程序里,一个count,一个i均是局部变量,每次进中断它们的值都是0;
整个测速过程存在四种状态:处于起始捕获状态,处于编码器工作状态,处于尾捕获状态,TIM2超时状态;
每一状态需要做的事情当然也是不一样的;TIM2和TIM3均共享当前状态,你可以先画出一个流程图,不急着先写程序;
另外,n=60*(1000000)*M1/(M2*4*400);  这里变量的类型需要注意其最大边界?M2的高频脉冲计数很可能会溢出的,需要
进行溢出统计,不然高频计数值不正确
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165462
金钱
165462
注册时间
2010-12-1
在线时间
2114 小时
发表于 2015-7-21 23:40:39 | 显示全部楼层
帮顶。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-21 23:52:29 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
谢谢原子哥!
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-22 05:40:59 | 显示全部楼层
求助各位大神!!!
回复

使用道具 举报

39

主题

598

帖子

0

精华

高级会员

Rank: 4

积分
875
金钱
875
注册时间
2013-12-18
在线时间
41 小时
发表于 2015-7-22 08:39:18 | 显示全部楼层
你不会是在做飞思卡尔的比赛把?我当年也是做过那个比赛,我还记得我用的是欧姆龙的编码器,不知道名字记得对不对,时间比较久了,我给你点建议:
1.你最好不要=着别人来教你告诉你一步一步该怎么做,不管你是不是在做飞思卡尔的比赛,我推荐你去飞思卡尔的淘宝店也好,哪也好,上面关于编码器测速的资料数不胜数,还比较好学,都是实践的工程师给你写的,不是那帮搞科研的,读起来就不一样。还有许多程序程序的例子,不过是基于飞思卡尔处理器的,你要用别的处理器,稍微改改就行,都差不多的。我当时也这么过来的,慢慢就解决了。
2.直流电机也好步进电机也好,驱动板是必须的把,这个你应该是有的把?或者自己画个PCB用,买也可以,都不贵的,很简单的,我以前都是用L298N或者ULN2003A,都是比较低级简单的,驱动小电机没问题的,好用好学,原理简单,说道PWM,那你就不用求助帖子了,自习去看看原子哥的资料,例程,不完全手册什么的,上面说的很详细,PWM之前,把定时器也学一下。
3.这个是我个人抛开技术上的建议,我在做项目的过程中也经常求助帖子或者问高手,但是貌似与你的问题不同,你的问的编码器测速,PWM控制电机,随便上个百度,关键字也不用多少考虑,随便一搜,出来的结果和资料我保证你几个晚上都读不完,这不是什么稀奇的问题,太大众化了,可以说是被人做烂的东西了,至少我比赛的时候就已经是了。很好找答案的呀,你自己搜过吗?资料很难懂吗?反正我个人是遇到问题,自己实在搜不到,找不到,没办法解决,才发帖求助,你的这2个问题或许论坛里有大神会耐心告诉你一步一步怎么做,但是我希望你能自己解决。加油。
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-22 09:14:13 | 显示全部楼层
回复【5楼】w417074951:
---------------------------------
太感谢了!我不是在在做飞思卡尔的比赛,是要自己做点东西,用的欧姆龙的编码器!百度过编码器测速,但是资料太杂了,很难找到有用的信息!PWM控制电机以前用过,这个不是问题,就是不会编码器测速!您的建议给了我很大动力!真心感谢您的建议!
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-22 15:39:39 | 显示全部楼层
2点建议:
1,建议先看一看M/T测速法,理解其原理后,测速代码就很好写了;
2,然后看一看PID控制相关资料,将编码器的测速反馈给PID,输出对应的PWM对直流电机进行调速;
原理性的东西还是要自己去看的,论坛里的大神都很忙的
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-22 17:51:31 | 显示全部楼层
回复【7楼】joe_knight:
---------------------------------
嗯,看过M T M/T这几种测速方法了。看懂了大概,还在琢磨怎么写代码!编码器的测速还要反馈给PID去控制电机啊?
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-22 18:10:17 | 显示全部楼层
闭环控制当然要用到PID了,至于你是用P还是PI或者是PID控制看具体需求,一般用PI控制基本都能满足要求
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-22 18:23:15 | 显示全部楼层
回复【9楼】joe_knight:
---------------------------------
嗯,好吧!PID还完全没有接触过呢!
你能帮我看看这个编码器的代码对吗?用的400线的增量式编码器!
void TIM_Encoder(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    GPIO_InitTypeDef GPIO_Initstructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);    
    
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_Initstructure);  

    TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period=400*4-1;
    TIM_TimeBaseInitStruct.TIM_Prescaler=0;
    
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);   
       
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, 
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 6;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);    

    TIM3->CNT=0;
  
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); 

    TIM_Cmd(TIM3,ENABLE);    
}
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-23 09:54:35 | 显示全部楼层
回复【10楼】张晓斌:
---------------------------------
如果你GPIO和TIM时钟在别处都有使能的话,编码器接口配置没什么问题;
另外,你配置完编码器接口之后,还有测速周期Tc和高频脉冲计数都需要加进来的(M/T测速的话)
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-23 23:38:31 | 显示全部楼层
回复【11楼】joe_knight:
---------------------------------
测速周期可以用另一个定时器中断来设定吗?高频脉冲计数?是指在测速周期内读取TIM3的计数器值吗?还有我想不明白,400线的编码器为什么预装载值会是400*4呢?是因为编码器转动一周产生400个脉冲,然后在上升沿读取,4倍计数,这样理解对吗?
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-24 10:09:25 | 显示全部楼层
使用另一个定时器中断来进行周期测速,高频计数脉冲就是M/T法的M2,编码器计数是M1,测速的公式N= (60 * f0*M1) / (P*M2),式中,
P在你项目里是400*4,f0是测速高频脉冲定时器的频率;编码器A和B相,相位差90,每一个边沿会进行一次计数,那么每一线就是4次计数了;
对于M/T法测速,这里说的还比较详细:http://www.61ic.com/Article/C2000/C24X/200407/129.html
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-24 16:05:19 | 显示全部楼层
回复【13楼】joe_knight:
---------------------------------
基本上明白了,太感谢了!
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-24 17:22:32 | 显示全部楼层
回复【13楼】joe_knight:
---------------------------------
思路是不是这样啊!我用TIM2产生5ms中断,TIM3作为编码器计数。进入TIM2中断后,使能TIM3,然后M1=TIM3->CNT,M2=TIM2->CNT。这样的话M2应该是确定的就是TIM2的计时器预装载值,这样对吗?
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-24 18:08:55 | 显示全部楼层
TIM2的5ms是否满足低速要求(一个测速周期至少要能检测到一个码盘脉冲),这个需要评估;
 假定Tim2周期为5ms,那Tc = 5ms,而不是高频脉冲计数M2,高频脉冲顾名思义,频率相对较高,计数值增长较快,需要另外一个计数器来进行计数;
 TIM3的计数值就是M1,这个没错的;
 另外,需要注意的是提高测速精度,需要规避误差产生的条件,12楼的链接里误差分析也说明了这点。
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-24 18:43:27 | 显示全部楼层
回复【16楼】joe_knight:
---------------------------------
哦哦!如果还是TIM2产生5MS定时中断,那么进入TIM2中断后,应该使能TIM3和TIIM5,TIM5作为高频f0脉冲,这样就可以实现TIM3和TIM5的同步,然后M1=TIM3->CNT,M2=TIM5->CNT.测速的电机转速低,所以5MS应该可以了!通过M1计算得到弧长,也就是角位移,然后根据M2 f0可以得到脉冲时间,这样就可以得到转速。对了,在退出中断是得失能TIM3和TIM5.
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-25 19:57:35 | 显示全部楼层
回复【16楼】joe_knight:
---------------------------------
void TIM5_Configuration(void)
{
   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    
   TIM_ClearITPendingBit(TIM5,TIM_IT_Update); 
   
   TIM_TimeBaseInitStructure.TIM_ClockDivision=0;
   TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
   TIM_TimeBaseInitStructure.TIM_Period=1600;
   TIM_TimeBaseInitStructure.TIM_Prescaler=71;
    
   TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);
    
   TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);
    
   //TIM_Cmd(TIM5,ENABLE);
}//TIM5作为高速脉冲计数
void TIM2_Configuration(void)
{
   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    
   TIM_ClearITPendingBit(TIM2,TIM_IT_Update); 
   
   TIM_TimeBaseInitStructure.TIM_ClockDivision=0;
   TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
   TIM_TimeBaseInitStructure.TIM_Period=50-1;
   TIM_TimeBaseInitStructure.TIM_Prescaler=7199;//定时5ms
    
   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    
   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    
   TIM_Cmd(TIM2,ENABLE);
}

void TIM2_IRQHandler(void)
{
  u16 M1=0,M2=0;
    
  TIM_Cmd(TIM3,ENABLE);
  TIM_Cmd(TIM5,ENABLE);
    
  M1=TIM3->CNT;
  M2=TIM5->CNT; 
  n=60*(1000000)*M1/(M2*4*400); 
  
  TIM_Cmd(TIM3,DISABLE);
  TIM_Cmd(TIM5,DISABLE);
    
  TIM_ClearITPendingBit(TIM2,TIM_IT_Update); 
    
}
这样有什么问题吗?为什么测得的n一直是0呢?是按照那个思路啊?哪里不对啊?
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-27 10:43:31 | 显示全部楼层
你在TIM2的5ms中断里做的是什么呀:打开TIM3和TIM5后就读计数器?读完然后就关闭?这样在一个测速周期内TIM3和TIM5都不工作,测出来不是0都怪了。
先禁用定时器,再读数,最后再使能定时器,这流程是不是你想要的?
但这样测速是不精确的,尤其对于慢速系统。
1,我们先来看Tc是不是满足需求,n = (60 × M1)/(P × Tc),为了在一个Tc内至少能收到一个编码脉冲,那么M1=1,P恒量4×400,n >= 60000 / (4 ×400 × 5),n>=7.5rpm,
也就是说,在低于7.5rmp的转速时,你的测速周期就不能满足需求,如果有示波器,可以通过编码脉冲的波形可以看一看不同转速下的最小Tc;
2,为什么说这样测速精度不够呢?copy一段,你好好理解一下:Tc开始时刻与码盘输出脉冲上升沿并非一定同步到达。同样,TC结束时刻也很难刚好与码盘的输出脉冲上升沿同步。这两个时间差都与转速的大小有关,而与高频计数时钟的频率无关。由此引起的计数和计时的时间偏差可能比高频时钟周期大得多,从而降低测速的精度;
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-27 15:45:45 | 显示全部楼层
回复【19楼】joe_knight:
---------------------------------
蒙圈了。。。应该是初始化时使能TIM3和TIM5,然后在TIM2中断里面禁用TIM3和TIM5,读取计数值放到M1和M2里面在进行计算。这样也不能实现。然后又仔细看了看那篇文章,换了种思路,  
主函数中   
 if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)==1)//TIM3的PC6 C7作为编码器接口
      {
        TIM3->CNT=0;
        TIM_Cmd(TIM5,ENABLE);
      }
然后在TIM2中断里
void TIM2_IRQHandler(void)
{
  u16 M1=0,M2=0;
   
    if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)==1)
    {    
  TIM_Cmd(TIM3,DISABLE);
  TIM_Cmd(TIM5,DISABLE);    
   
  M1=TIM3->CNT;
  M2=TIM5->CNT; 
    
  TIM3->CNT=0;
  TIM5->CNT=0;
  n=60*(1000000)*M1/(M2*4*400); 
  
  TIM_Cmd(TIM3,ENABLE);
  TIM_Cmd(TIM5,ENABLE);
    } 
  TIM_ClearITPendingBit(TIM2,TIM_IT_Update); 
    
}
但是这样也不可以啊!这样应该可以啊!奔溃了。。。
回复

使用道具 举报

1

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2015-7-16
在线时间
3 小时
发表于 2015-7-27 16:15:30 | 显示全部楼层
之前我做过的是这样的一个思路:在tc中断到达时,TIM3配置为输入捕获(双边沿),在TIM3捕获中断内禁用捕获,再配置TIM3为编码器模式,使能高频脉冲计数定时器;
在下一次tc中断再次到达后,禁用TIM3,读取TIM3计数M1和,然后又将TIM3配置成输入捕获模式;在TIM3捕获中断内又禁用捕获,禁用高频脉冲计数定时器,读取TIM5计数M2,计算转速;
如果再下一次的tc中断到达时,尾捕获还未产生,读取TIM5计数M2,计算转速;所以这里的测速周期实际是Tc~2Tc;
这里提供一个思路,优化空间还很大。。。
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-27 18:18:56 | 显示全部楼层
回复【21楼】joe_knight:
---------------------------------
void TIM2_IRQHandler(void)
{    
  u8 count=0;
   if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
   {
      
    if(count==0)//第一次进入中断后
    {
        TIM3_Cap_Init();//输入捕获模式
        count++;  
    }        
    if(count==2)//第二次进入中断
    {
        count=0;
        TIM_Cmd(TIM3,DISABLE);
        M1=TIM3->CNT;
        TIM3->CNT=0;//计数器清零
        TIM3_Cap_Init();  
    }             
   TIM_ClearITPendingBit(TIM2,TIM_IT_Update); 
   }   
}
void TIM3_IRQHandler(void)
{
    u8 i=0;
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
        TIM_ClearFlag(TIM3,TIM_IT_Update);
    if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET|TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
    {   
        if(i==0)//第一次捕获
        {     
        TIM_Cmd(TIM3,DISABLE);
        TIM3->CNT=0;
        TIM_Encoder();
        TIM_Cmd(TIM5,ENABLE);
        i++;
        }
        if(i==2)//第二次捕获
        {
           i=0;
          TIM_Cmd(TIM5,DISABLE);
          M2=TIM5->CNT;  
        }
        TIM_ClearFlag(TIM3,TIM_IT_CC1);
        TIM_ClearFlag(TIM3,TIM_IT_CC2);
    }
}
我是按照你给的思路写的啊,但结果还是一样的。唉。。。对自己失望了。
回复

使用道具 举报

20

主题

120

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-4
在线时间
5 小时
 楼主| 发表于 2015-7-28 22:30:30 | 显示全部楼层
回复【23楼】joe_knight:
---------------------------------
哦哦,可能是溢出没有处理好吧,我再弄弄吧!真心谢谢你!
回复

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
159
金钱
159
注册时间
2016-3-8
在线时间
16 小时
发表于 2016-4-6 14:08:51 | 显示全部楼层
同问11111
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2015-12-2
在线时间
7 小时
发表于 2016-4-20 13:12:36 | 显示全部楼层
楼主,你的编码器能精确地测速;了吗??
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2015-12-2
在线时间
7 小时
发表于 2016-4-20 20:57:27 | 显示全部楼层
楼主能用编码器准确滴测速了吗??
回复

使用道具 举报

5

主题

36

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
255
金钱
255
注册时间
2016-11-5
在线时间
70 小时
发表于 2017-5-2 09:51:10 来自手机 | 显示全部楼层
楼主你搞定了吗?能分享一下吗?我也在做测速,谢谢
回复

使用道具 举报

5

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2017-7-13
在线时间
14 小时
发表于 2017-8-5 15:33:15 | 显示全部楼层
楼主 你的测速问题解决了吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-20 05:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表