[原创] 旋转编码器解码

zhaojun_xf   2013-8-28 09:59 楼主
随着电子技术的发展,旋转编码器的应用越来越广泛。下面我们谈谈对旋转编码器的解码。

      旋转编码器是用来测量转速的装置,光电式旋转编码器通过光电转换,可将输出轴的角位移、角速度等机械量转换成相应的电脉冲以数字量输出(REP)。它分为单路输出和双路输出两种。技术参数主要有每转脉冲数(几十个到几千个都有),和供电电压等。单路输出是指旋转编码器的输出是一组脉冲,而双路输出的旋转编码器输出两组A/B相位差90度的脉冲,通过这两组脉冲不仅可以测量转速,还可以判断旋转的方向。

1.jpg
我的博客

回复评论 (11)

编码器的种类比较多,下面我们谈谈两路输出脉冲的编码器解码:
1.png



从上面的波形不难看出,左转时,A比B的波形快一些出现;而右转时,A比B的波形晚一些出现,其输出电平状态为:

左转: A - 0 1 1 0 0 1 1 0 0  
           B - 0 0 1 1 0 0 1 1 0  

右转: A - 0 0 1 1 0 0 1 1 0  
           B - 0 1 1 0 0 1 1 0 0


左转 : 当A和B的值组合(A<<1 | B)时,获取值为:-2-3-2-0
右转 : 当A和B的值组合(A<<1 | B)时,获取值为:-1-3-2-0
我的博客
点赞  2013-8-28 10:15
从上面的二进制可以看出,左转和右转的数据排列组合是不一样的。我们可以通过转换状态的变化只获取转换方向,并记录脉冲获取旋转幅度。

所以,可以通过获取之前状态和当前状态,来解码编码器的旋转。

例如: 之前状态为0,当前状态为2,则为左转开始;如果之前状态为0,当前状态为1,则是右转开始。
我的博客
点赞  2013-8-28 10:20
理解了上面的内容,下面解码就非常方便了。我们知道,两路输出有4总状态,而之前状态和当前状态组合就可能出现4x4 = 16种状态,但是,从上面的帖子可以看出,一种状态只可能转化到另外两种状态,而其他两种状态是不会出现的,即使出现,也是乱码或干扰,不被采用。

2.png
  1. /**************************************************************************************
  2. * FunctionName   : KEY_ReadRotaryVal()
  3. * Description    : 旋转编码器解码(定时1ms中断调用,不会漏掉脉冲)
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. **************************************************************************************/
  7. u8 KEY_ReadRotaryVal(void)
  8. {
  9.     u8 curSta;
  10.     static u8 preSta = 0;
  11.     static u8 tmpL = 0;
  12.     static u8 tmpR = 0;
  13.     u8 keyL, keyR, key = KEY_VAL_NO;
  14.    
  15.     keyL = GPIO_ReadInputDataBit(KEY_CL_PORT, KEY_CL_PIN);
  16.     keyR = GPIO_ReadInputDataBit(KEY_CR_PORT, KEY_CR_PIN);
  17.   
  18.     curSta = (0x01 << keyL) | keyR;
  19.    
  20.     if (preSta != curSta)
  21.     {
  22.         switch ((preSta<<4) | curSta)                                           // 前一状态+当前状态
  23.         {
  24.             case 0x02:
  25.             case 0x10:
  26.             case 0x23:
  27.             case 0x31:                                                          // 左转
  28.             {
  29.                 tmpR = 0;
  30.                 if (++tmpL >= KEY_ROT_TIM)                                      
  31.                 {
  32.                     tmpL = 0;
  33.                     KEYPar.Rotary++;
  34.                     key = KEY_VAL_CL;
  35.                 }
  36.                
  37.                 break;
  38.             }

  39.             case 0x01:
  40.             case 0x13:
  41.             case 0x20:
  42.             case 0x32:                                                          // 右转
  43.             {
  44.                 tmpL = 0;
  45.                 if (++tmpR >= KEY_ROT_TIM)
  46.                 {
  47.                     tmpR = 0;
  48.                     KEYPar.Rotary++;
  49.                     key = KEY_VAL_CR;
  50.                 }
  51.                
  52.                 break;
  53.             }

  54.             default: tmpL = 0; tmpR = 0; KEYPar.Rotary = 0; break;
  55.         }
  56.         
  57.         preSta = curSta;
  58.     }
  59.    
  60.     return key;
  61. }

[ 本帖最后由 zhaojun_xf 于 2013-8-28 10:41 编辑 ]
我的博客
点赞  2013-8-28 10:24
解码函数的返回值为转动方向,而全局变量KEYPar.Rotary中存放的是旋转脉冲个数,为滤波,还进行了4次计一出来,保证快速转动时,保证不会出现多余值。当然这个函数可以采用定时扫描,也可以采用中断读取。

为了保证不遗漏脉冲,建议每ms读取一次编码器。我们可以采用定时中断调用。
我的博客
点赞  2013-8-28 10:34
本解码方法非常简单易懂,特别是之前状态与当前状态的组合方法非常容易理解,特别直观。网友可以根据自己使用的编码器进行适当的修改获取自己需要的代码。
我的博客
点赞  2013-8-28 10:38

回复 6楼zhaojun_xf 的帖子

不错啊
点赞  2013-8-28 11:27
占座学习~~~~
http://weibo.com/u/1391449055
点赞  2013-8-28 14:25
这个和光电可增益编码器差不多吧!
点赞  2013-9-3 18:58
学习
点赞  2013-9-20 07:35
编码器,MARK,马上就要用了
点赞  2015-9-22 08:31

思路简单又实用,最重要的是还有滤波效果,不错

点赞  2021-5-4 22:51
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复