搜索
bottom↓
回复: 42

用中断方式去检测旋转编码器的 AB相信号,怎么读取才可以做到稳定可靠的数值呢? 高人指

[复制链接]

出0入0汤圆

发表于 2009-8-29 13:04:13 | 显示全部楼层 |阅读模式
#define   SET_SIN_B_DWON    EICRA &= ~(1<<ISC10)//int1  DOWN
#define   SET_SIN_B_UP      EICRA |= (1<<ISC10)//int1  上 UP
#define   SIN_B_CHECK       (EICRA & (1<<ISC10))


#define   SET_SIN_A_DWON    EICRA &= ~(1<<ISC00)//int0  DOWN
#define   SET_SIN_A_UP      EICRA |= (1<<ISC00)//int0  上 UP
#define   SIN_A_CHECK       (EICRA & (1<<ISC00))


#pragma vector=INT0_vect
__interrupt void INT0_vect_ISR(void)
{
      CLI();
      
   
      SIN_A_UP_Flag=1;countt=0;//这里是两个标志
      if(SIN_B_IN==0)SET_SIN_B_UP ;  //B相判断 是高还是低电平
      else SET_SIN_B_DWON;
  
      SEI();
        
}

#pragma vector=INT1_vect
__interrupt void INT1_vect_ISR(void)
{  
  CLI();

  if(SIN_A_UP_Flag==1)
  {
       if(countt==0)
       {
             if(SIN_B_CHECK)//B相是否是上升沿中断
              {
                SET_SIN_B_DWON ; //再设为下降没中断
                SIN_B_UP_Flag=ZEN;//再设标志
                if(++Rotary_Count > RE_Number)Rotary_Count=1;
              }
             else
              {
                SET_SIN_B_UP;
                SIN_B_UP_Flag=FAN;
                if(--Rotary_Count < 1) Rotary_Count=RE_Number;
             }
       }
       else
       {
            if(SIN_B_UP_Flag==ZEN)
              {
                  SET_SIN_B_UP;
                  if(++Rotary_Count > RE_Number)Rotary_Count=1;
              }
            else
             {   
                  SET_SIN_B_DWON ;
                  if(--Rotary_Count<1) Rotary_Count=RE_Number;  
            }
            
       }
     countt++;
     if(countt==2) {countt=0;SIN_A_UP_Flag=0;}
}

SEI();

}
我这个读取数值时,有问题,用步进电机带动转一周时,每次读的数值都不一样。

高人有无可靠稳定的算法呢?

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2009-8-29 14:25:13 | 显示全部楼层
一定要消抖动,也可用扫描方式读取,本站之前有讨论过的,你找找看http://www.ourdev.cn/bbs/bbs_list.jsp?search_text=%B1%E0%C2%EB%C6%F7&search_mode=1&bbs_id=9999&Submit2=+%CB%D1+%CB%F7+

注意软解是不适合跑高速的

出0入0汤圆

发表于 2009-8-29 14:55:54 | 显示全部楼层
手动的那种一周12-30线的解码非常容易,加个电容消抖,一个引脚中断后看看另一个引脚状态就OK了。用步进电机带高分辨率旋转编码器的时候,电机的速度很重要,高速启动的时候可能就会丢步,编码器输出肯定有差别。速度太低,电机如果有抖动,问题更糟。我试过50-300转的带200线编码器,计数非常精确。我使用DSP算得

出0入0汤圆

 楼主| 发表于 2009-8-29 15:59:03 | 显示全部楼层
谢谢【1楼】 shinehjx  &  【2楼】 plank

我用手转动编码器一周时,对比起来。感觉挺准的。就是挂上步进电机 4细分  3S转一周时,出现数值不准。

感觉就像 【2楼】 plank  兄弟说的那样“编码器输出肯定有差别。速度太低,电机如果有抖动,问题更糟”。

我不想增加硬件的前提下,有无更好一点的算法啊。

顺随上个     “旋转编码器 抗抖动电路 数字电路”


(原文件名:未命名.jpg)


(原文件名:未命名11.jpg)

这个是网上下的ourdev_475944.pdf(文件大小:158K) (原文件名:旋转编码器的抗抖动计数电路.pdf)

出0入0汤圆

发表于 2009-8-29 21:47:00 | 显示全部楼层
设标志位,正转B下沿A=1,OK。这样可消除抖动

出0入0汤圆

 楼主| 发表于 2009-8-29 21:56:39 | 显示全部楼层
【4楼】 JYLJYL
兄弟可以来点小例子不?

出0入0汤圆

 楼主| 发表于 2009-8-29 23:52:57 | 显示全部楼层
可靠,稳定。估计要用状态机了。

出0入0汤圆

发表于 2009-8-30 00:10:29 | 显示全部楼层
我用PIC和ALPS EC11B旋转编码器采用中断方式做了个硬件试验,应该说比较可靠,用电容消抖,并有PROTEUS仿真,仅供参考.点击此处下载 ourdev_476051.rar(文件大小:40K) (原文件名:rosw3.rar)



(原文件名:r.png)

出0入0汤圆

 楼主| 发表于 2009-8-30 00:50:47 | 显示全部楼层
TO LS兄弟,如果编码器走得很慢或很快时,你这个恐怕都会出现数值不准吧。

出0入0汤圆

发表于 2009-8-30 08:34:11 | 显示全部楼层
我做过实验,似乎没发现什么问题.当时用串口调试,快慢都试过.

出0入0汤圆

 楼主| 发表于 2009-8-30 12:16:56 | 显示全部楼层
先谢谢【9楼】 eezm 兄弟
你可否讲下你的思路呢?

出0入0汤圆

发表于 2011-1-4 01:19:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-4 10:10:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-26 16:58:35 | 显示全部楼层
中断方式检测旋转编码器

芯片ATMEGA128  
A  -->PE4  外部中断4  
B  -->PE5

      
连续两次检测A.B相电平  确认左 右旋转时序。

已经过实际使用    计数准确

下面是原码

//外部中断初始化
void ext_int4_init()
{
EICRB=0x01;    // 外部中断4任意电平变化触发中断
EIMSK=0X10;    // 使能外部中断4
}


//外部中断4处理旋转编码器

void ext_int4_isr(void)
{
    uchar i;                  // 局部变量
    static uchar Left,Right;  //左 右旋转方向静态变量
       
    i=(PINE>>4)&0x03;         // 读取编码器的A.B脚电平值 (AB接PE4 PE5)PE4是外部中断4
   
   
   
        if(i==0)                  //判断A.B电平 如果都是低电平表示向右旋转
          {Left=0XFF;Right=0X00;} // 左旋转的变量赋值有效 右旋转无效
          
        else if(i==2)             //判断A.B电平 如果A是低电平 B是高电平表示向左旋转
          {Right=0XFF;Left=0X00;} //右旋转的变量赋值有效  左旋转无效
       
        else if((Right&i)==0x01)  //将有效的右旋再次与A.B电平对比  确认是右旋
          {num++;Right=0X00;}     // 数值增加  清除右旋转有效
       
        else if((Left&i)==0x03)   //将有效的左旋再次与A.B电平对比  确认是左旋
         {num--;Left=0X00;}       // 数值减小  清除左旋转有效

     
     
}

出0入0汤圆

发表于 2011-8-20 11:12:02 | 显示全部楼层
To 【13楼】 xuelx
   你的程序不错,谢谢!

出0入0汤圆

发表于 2012-4-11 19:00:49 | 显示全部楼层
最近看的头都大了 硬件电路到底该怎么接

出0入0汤圆

发表于 2012-4-12 08:04:34 | 显示全部楼层
给个实例吧,用起来没问题的,不存在多次来回低速抖动时计数不准的现象,当然有软解码的通病:速度上不去(for mega128 at 8M)。
#pragma interrupt_handler TIMER3_OVF_ISR: 30                    
void TIMER3_OVF_ISR(void)                                       
{                                                              
    TCNT3=0xfc41;                                               // 125uS
    if(!Comparing) {                                            
                           PulAPol=PINE; PulLastState=PulAPol; Comparing++;   
                                                   PulAPol&=0x40; PulLastState&=0xc0; PulAPol>>=6;   
                                           }                                                   
        if(Comparing)                                                         
         {                                                                    
            PulBPol=PINE;                                                     
      PulState=PulBPol;                                                
      PulState&=0xc0;                                                   
                  PulBPol&=0x80;                                                   
                  PulBPol>>=7;                                                      
                  if(PulState!=PulLastState)
                          {
                                  if(PulBPol==PulAPol)
                                          {
                                                  RunRight=1; BMQCounterTotal--;
                                          }
                            else
                                    {
                                            RunRight=0; BMQCounterTotal++;
                                          }
                            Comparing=0;  
                          }  
         }                                                                    
    if(!Comparing) {                                                   
                           PulAPol=PulState; PulLastState=PulAPol; Comparing++;
                                                   PulAPol&=0x40; PulLastState&=0xc0; PulAPol>>=6;      
                                           }                                                     
}   

出0入0汤圆

发表于 2012-4-12 08:10:54 | 显示全部楼层
再给个硬件的,仿真过但没实际用过

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-4-21 10:46:46 | 显示全部楼层
请问一下,为什么ALPS有三相的旋转编码器,是不是空出C相不要接,然后另外两个A,B上拉,接PIC单片机口变化中断,只要有口变化中断,是A口就+1,是B口-1,
这样是不是最简单的检测方法呀。有没有人这样做过?

出115入0汤圆

发表于 2012-4-26 21:04:02 | 显示全部楼层
xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器

芯片ATMEGA128  

13楼程序今天试着用了一下,要转两格才能自加自减啊?

出0入76汤圆

发表于 2012-11-21 11:09:20 | 显示全部楼层
嗯,学习中....,下午有空实验一下xuelx,coleyao大侠的程序...
感谢你们的分享..

出0入0汤圆

发表于 2012-12-14 23:04:08 | 显示全部楼层
学习了,顶下

出0入0汤圆

发表于 2012-12-15 13:32:20 来自手机 | 显示全部楼层
路过,学习一下

出0入0汤圆

发表于 2013-1-26 23:32:08 | 显示全部楼层
程序不错,这个是1倍速度的解码方式,防抖动

出0入0汤圆

发表于 2013-2-21 21:19:35 | 显示全部楼层

是1倍速度的解码方式

出0入0汤圆

发表于 2013-2-21 21:27:12 | 显示全部楼层
路过,看看大婶们

出0入0汤圆

发表于 2013-10-29 17:17:02 | 显示全部楼层
记下了,学习学习

出0入0汤圆

发表于 2013-10-29 17:28:02 | 显示全部楼层
只搞过那种手动的几十线的- -用的1ms的轮询
用中断的话搞个定时器,在中断触发后禁用IO中断,开定时器,定时器中断里面再重新开IO中断实现延时不知道靠谱不

出0入0汤圆

发表于 2014-4-17 15:49:23 | 显示全部楼层
mark 标记

出0入0汤圆

发表于 2014-4-21 14:14:19 | 显示全部楼层
如果再来测速度的话,这个程序怎么改?

出0入0汤圆

发表于 2014-4-21 21:30:14 | 显示全部楼层
旋转编码器,mark

出0入0汤圆

发表于 2014-4-23 05:25:24 | 显示全部楼层
注意软解是不适合跑高速的 30K
可以 大于30K就不稳定了

出0入0汤圆

发表于 2014-4-23 09:23:28 来自手机 | 显示全部楼层
mark            

出0入0汤圆

发表于 2014-4-24 14:47:25 | 显示全部楼层
如果频率高,还是不要这样用吧?特别是还有其他程序的时候,你的程序不会只单单处理编码器吧?当然做做数字电位器之类的另当别论。

出0入0汤圆

发表于 2014-8-13 11:32:05 | 显示全部楼层
shinehjx 发表于 2009-8-29 14:25
一定要消抖动,也可用扫描方式读取,本站之前有讨论过的,你找找看http://www.ourdev.cn/bbs/bbs_list.jsp? ...

为什么软解不适合跑高速

出0入0汤圆

发表于 2014-8-13 16:28:33 | 显示全部楼层
xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器

芯片ATMEGA128  

感觉写错了吧,向左旋转,怎么会是Right=0XFF

出0入0汤圆

发表于 2014-8-13 16:45:18 | 显示全部楼层
额,编码器和步进电机怎么用啊

出0入0汤圆

发表于 2014-9-30 11:21:37 | 显示全部楼层
傻孩子大师的思路很不错的喔,用外部中断,上升沿  下降沿都触发,再判断其他端口的信息

出0入0汤圆

发表于 2014-10-5 15:10:23 | 显示全部楼层
请问上面各位讲的编码器,是不是型号为EC11之类的?

出0入0汤圆

发表于 2014-10-5 15:59:41 | 显示全部楼层
    i=(PINE>>4)&0x03;         // 读取编码器的A.B脚电平值 (AB接PE4 PE5)PE4是外部中断4
请讲一下,14楼的这句是如何检测PE4,PE5脚的电平值?我不是太理解。谢谢了。

出0入0汤圆

发表于 2014-10-5 16:03:47 | 显示全部楼层
似乎有些懂了。“PINE>>”是将PINE的值右移4位,然后和0x03(00000011)相与,得到 i 值的。

出0入0汤圆

发表于 2014-10-5 16:18:47 | 显示全部楼层
本帖最后由 rjx 于 2014-10-5 16:21 编辑

再问:
14楼的不用中断也可以吧,改成一般的子函数也行吧?如改成这样行吗?烦请解答一下。

void EC11(void)
{
    uchar i;                  // 局部变量
     static uchar Left,Right;  //左 右旋转方向静态变量
         
    i=(PINE>>4)&0x03;         // 读取编码器的A.B脚电平值 (AB接PE4 PE5)PE4是外部中断4  
   
   
         if(i==0)                  //判断A.B电平 如果都是低电平表示向右旋转
           {Left=0XFF;Right=0X00;} // 左旋转的变量赋值有效 右旋转无效
           
         else if(i==2)             //判断A.B电平 如果A是低电平 B是高电平表示向左旋转
           {Right=0XFF;Left=0X00;} //右旋转的变量赋值有效  左旋转无效
         
        else if((Right&i)==0x01)  //将有效的右旋再次与A.B电平对比  确认是右旋
           {num++;Right=0X00;}     // 数值增加  清除右旋转有效
         
        else if((Left&i)==0x03)   //将有效的左旋再次与A.B电平对比  确认是左旋
          {num--;Left=0X00;}       // 数值减小  清除左旋转有效     
      
}

出0入0汤圆

发表于 2014-10-5 16:32:56 | 显示全部楼层
xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器

芯片ATMEGA128  

好方法,还从没用过软解码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-4 02:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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