cyxavr 发表于 2009-8-29 13:04:13

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

#define   SET_SIN_B_DWON    EICRA &= ~(1<<ISC10)//int1DOWN
#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)//int0DOWN
#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();

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

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

shinehjx 发表于 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+

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

plank 发表于 2009-8-29 14:55:54

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

cyxavr 发表于 2009-8-29 15:59:03

谢谢【1楼】 shinehjx&【2楼】 plank

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

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

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

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

http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_475942.jpg
(原文件名:未命名.jpg)

http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_475943.jpg
(原文件名:未命名11.jpg)

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

JYLJYL 发表于 2009-8-29 21:47:00

设标志位,正转B下沿A=1,OK。这样可消除抖动

cyxavr 发表于 2009-8-29 21:56:39

【4楼】 JYLJYL
兄弟可以来点小例子不?

cyxavr 发表于 2009-8-29 23:52:57

可靠,稳定。估计要用状态机了。

eezm 发表于 2009-8-30 00:10:29

我用PIC和ALPS EC11B旋转编码器采用中断方式做了个硬件试验,应该说比较可靠,用电容消抖,并有PROTEUS仿真,仅供参考.点击此处下载 ourdev_476051.rar(文件大小:40K) (原文件名:rosw3.rar)


http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_476052.png
(原文件名:r.png)

cyxavr 发表于 2009-8-30 00:50:47

TO LS兄弟,如果编码器走得很慢或很快时,你这个恐怕都会出现数值不准吧。

eezm 发表于 2009-8-30 08:34:11

我做过实验,似乎没发现什么问题.当时用串口调试,快慢都试过.

cyxavr 发表于 2009-8-30 12:16:56

先谢谢【9楼】 eezm 兄弟
你可否讲下你的思路呢?

wpnx 发表于 2011-1-4 01:19:10

mark

xuejianhua1986 发表于 2011-1-4 10:10:51

mark

xuelx 发表于 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;}       // 数值减小清除左旋转有效

   
   
}

yzlyear 发表于 2011-8-20 11:12:02

To 【13楼】 xuelx
   你的程序不错,谢谢!

lisen090 发表于 2012-4-11 19:00:49

最近看的头都大了 硬件电路到底该怎么接

coleyao 发表于 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;      
                                           }                                                   
}   

coleyao 发表于 2012-4-12 08:10:54

再给个硬件的,仿真过但没实际用过

鱼尾之恋 发表于 2012-4-21 10:46:46

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

newkey 发表于 2012-4-26 21:04:02

xuelx 发表于 2011-7-26 16:58 static/image/common/back.gif
中断方式检测旋转编码器

芯片ATMEGA128


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

foxpro2005 发表于 2012-11-21 11:09:20

嗯,学习中....,下午有空实验一下xuelx,coleyao大侠的程序...
感谢你们的分享..

YOU1 发表于 2012-12-14 23:04:08

学习了,顶下

jz701209李 发表于 2012-12-15 13:32:20

路过,学习一下

john_8 发表于 2013-1-26 23:32:08

程序不错,这个是1倍速度的解码方式,防抖动

mdj-fish 发表于 2013-2-21 21:19:35


是1倍速度的解码方式

mcusy 发表于 2013-2-21 21:27:12

路过,看看大婶们

韦斯克拉 发表于 2013-10-29 17:17:02

记下了,学习学习

NEWT 发表于 2013-10-29 17:28:02

只搞过那种手动的几十线的- -用的1ms的轮询
用中断的话搞个定时器,在中断触发后禁用IO中断,开定时器,定时器中断里面再重新开IO中断实现延时不知道靠谱不

zjk 发表于 2014-4-17 15:49:23

mark 标记

吴杰 发表于 2014-4-21 14:14:19

如果再来测速度的话,这个程序怎么改?

qingaixww 发表于 2014-4-21 21:30:14

旋转编码器,mark

hddgf 发表于 2014-4-23 05:25:24

注意软解是不适合跑高速的 30K
可以 大于30K就不稳定了

xckhmf 发表于 2014-4-23 09:23:28

mark            

huangxiaolpbany 发表于 2014-4-24 14:47:25

如果频率高,还是不要这样用吧?特别是还有其他程序的时候,你的程序不会只单单处理编码器吧?当然做做数字电位器之类的另当别论。

犬火 发表于 2014-8-13 11:32:05

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

为什么软解不适合跑高速

犬火 发表于 2014-8-13 16:28:33

xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器

芯片ATMEGA128


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

机器人天空 发表于 2014-8-13 16:45:18

额,编码器和步进电机怎么用啊

ALUMEI 发表于 2014-9-30 11:21:37

傻孩子大师的思路很不错的喔,用外部中断,上升沿下降沿都触发,再判断其他端口的信息

rjx 发表于 2014-10-5 15:10:23

请问上面各位讲的编码器,是不是型号为EC11之类的?

rjx 发表于 2014-10-5 15:59:41

    i=(PINE>>4)&0x03;         // 读取编码器的A.B脚电平值 (AB接PE4 PE5)PE4是外部中断4
请讲一下,14楼的这句是如何检测PE4,PE5脚的电平值?我不是太理解。谢谢了。

rjx 发表于 2014-10-5 16:03:47

似乎有些懂了。“PINE>>”是将PINE的值右移4位,然后和0x03(00000011)相与,得到 i 值的。

rjx 发表于 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;}       // 数值减小清除左旋转有效   
      
}

0demon0 发表于 2014-10-5 16:32:56

xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器

芯片ATMEGA128


好方法,还从没用过软解码
页: [1]
查看完整版本: 用中断方式去检测旋转编码器的 AB相信号,怎么读取才可以做到稳定可靠的数值呢? 高人指