foxpro2005 发表于 2012-11-20 20:13:04

用旋转编码器来测位置,有一个问题请教

本帖最后由 foxpro2005 于 2012-11-20 20:19 编辑

有一个类似于升降运动的设备,它是通过电机经减速器后带动的,我现在想用一个旋转编码器装在减速器的轴上来间接测量升降的位置,
本来想用绝对型编码器,看了一下,好点的价格太贵了。 想用正交增量型编码器,有便宜点的,它只有AB两相,不带Z想零脉冲。
只有贵点的才带Z相输出。

如果我用不带Z相输出的,设备在长期工作,在升降运动(正反转)一段时间之后,会不会产生累积误差,造成位置偏差(错误)。
如果有,采用何种方式来修正会比较好?

另外,看了网上高手们的帖子,都说编码器脉冲解析在中断来处理 ,抗干扰不好处理,如果转速比较高(或者高分辨率)还会造成MCU负担
过重,干不了别的事?   看到好多程序都是扫描的方式来做的,难道真的只能这样?

我对编码器不是很熟,还请高手们给参考意见,小弟在此先谢了。

kazenoai 发表于 2012-11-20 20:16:52

可以再加一个当作参考位置的接近传感器...

coleyao 发表于 2012-11-20 20:19:32

和算法有关,如果不丢脉冲,好的算法不会有往返几次多或少脉冲的情况,搜一下,很多资料的

foxpro2005 发表于 2012-11-20 20:19:35

kazenoai 发表于 2012-11-20 20:16 static/image/common/back.gif
可以再加一个当作参考位置的接近传感器...

谢谢,好快哦。

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

coleyao 发表于 2012-11-20 20:19 static/image/common/back.gif
和算法有关,如果不丢脉冲,好的算法不会有往返几次多或少脉冲的情况,搜一下,很多资料的 ...

大侠,您好,我就是怕这种情况的出现,造成这个问题。可以给点提示或参考么?
谢谢..

xzq1019@163.com 发表于 2012-11-20 21:35:15

这个。。。。推荐一个芯片ST288,鉴相很好。具体内部的计数,用计数器很好啊。

coleyao 发表于 2012-11-21 05:58:20

foxpro2005 发表于 2012-11-20 20:21 static/image/common/back.gif
大侠,您好,我就是怕这种情况的出现,造成这个问题。可以给点提示或参考么?
谢谢.. ...

http://www.amobbs.com/thread-3552331-1-1.html

foxpro2005 发表于 2012-11-21 10:22:07

coleyao 发表于 2012-11-21 05:58 static/image/common/back.gif
http://www.amobbs.com/thread-3552331-1-1.html

再次感谢coleyao大侠,现在认真学习中。

coleyao 发表于 2012-11-21 11:48:21

foxpro2005 发表于 2012-11-21 10:22 static/image/common/back.gif
再次感谢coleyao大侠,现在认真学习中。

不客气,如果对速度有要求,不怕麻烦就用CPLD或数字电路,怕麻烦的话就用高频率的单片机,如stm32 CM0内部主频可达48MHZ, CM3好像是72MHZ。

foxpro2005 发表于 2012-11-21 12:16:49

我现用的是M16, 目前OSC=8M的,编码器准备装在减速器上的。

fwluck 发表于 2012-11-21 13:10:20

如果安全性很高的话一种方式是不可取的。的多种方式并用。

yuyu87 发表于 2012-11-21 13:22:12

用LPC17XX吧,带旋转编码器硬件 计数

foxpro2005 发表于 2012-11-21 18:09:52

硬件限制,只好用M16的

foxpro2005 发表于 2012-11-23 23:14:10

coleyao 发表于 2012-11-21 11:48 static/image/common/back.gif
不客气,如果对速度有要求,不怕麻烦就用CPLD或数字电路,怕麻烦的话就用高频率的单片机,如stm32 CM0内 ...

以下是我学习您的代码,得出的分析 及 代码添加的注释:
1. 最大响应频率为2K,所以必须小于2K(实际上可能远小于2K,正确识别估计可能在1K左右)。

2. 原理: 是通过定时器不断(125us定时中断, 故允许的最大响应频率=4K)的扫描来检测AB相引脚上的电平变化(把上电首次(且只有首次才会)与对比成功后这一时刻的状态,同当前的检测状态作对比,以判断AB相电平是否发生变化);发生变化后,再判断B相电平与之前保存的A相电平的关系,来判断是右转(B==A时),还是左转(B !=A 时)。
但我感觉好像分别在AB相脉冲的上升沿,下降沿都有在计数,这样在A和B相的1个脉冲的上下沿共计数了4次? 这么做有点不是很理解。后面的计数中是不是对计数有除以4处理?

coleyao 大侠 ,您看我的理解正确么?

另外,有个问题想请教,对于抗干扰的处理。
1. 假如,在对比状态时,B相上现一次干扰,在低电平时突然有一个干扰脉冲, 会不会引起判断错误?
2. 我在想,可不可通过对 AB相电平变化的顺列来做抗干扰处理,如:右转是AB: 10 - 11 - 01 - 00,相当于一个完整脉冲周期(360度)才认为有效。

/*给个实例吧,用起来没问题的,不存在多次来回低速抖动时计数不准的现象,
当然有软解码的通病:速度上不去(for mega128 at 8M)。
*/
#pragma interrupt_handler TIMER3_OVF_ISR: 30                  
void TIMER3_OVF_ISR(void)                                       
{                                                            
    TCNT3=0xfc41;        // 125uS
       
    if(!Comparing){                                                // Comparing == 0, 首次对比(这一部分是针对刚上电时的情况)
      PulAPol = PINE;                                                // 读取AB相引脚电平状态(A相-PINE6,B相-PINE7)
                PulLastState = PulAPol;                         // 记录下本次的AB相引脚电平状态
                Comparing++;                                         // 标志进入连续对比状态
               
      PulAPol &= 0x40;                                         // 记录下本次A相(PINE6)引脚电平状态
                PulLastState &= 0xc0;                         // 记录下本次的AB相(只保留 B相-PINE7,A相-PINE6引脚)电平状态
                PulAPol >>= 6;                                         // 把A相状态位右移到第1位
    }                                                   
      
        if(Comparing)                                                // Comparing >= 1, 第2..N次, 连续对比状态
    {                                                                  
      PulBPol = PINE;                                              // 再次读取AB相引脚电平状态(A相-PINE6,B相-PINE7)
                PulState = PulBPol;                             // 记录下当前AB相位引脚电平状态
                PulState &= 0xc0;                             // 记录下当前的AB相(只保留 B相-PINE7,A相-PINE6引脚)电平状态
               
      PulBPol &= 0x80;                                         // 记录下当前的B相(PINE7)引脚电平状态
      PulBPol >>= 7;                                                // 把B相状态位右移到第1位
               
      if(PulState != PulLastState){                     // 把当前状态与前一次对比是否发生变化? 无变化则继续在对比状态.
            if(PulBPol == PulAPol){                             // 已经发生了变化, 通过对比A、B相引脚电平的关系,判断是右转,还是左转?
                RunRight = 1;                                     // 相同: 则为右转
                                BMQCounterTotal--;
            }
            else{                                                        // 不同: 则为左转
                RunRight = 0;
                                BMQCounterTotal++;
                        }
                        Comparing = 0;                             // 标志进入保存当前(对比成功后的)状态
                }
    }
       
    if(!Comparing){                                            // 记录下当前(对比成功后的)A相状态,及AB相的引脚电平状态,
      PulAPol = PulState;                                      // 以供后续检测,对比电平状态的变化。
                PulLastState = PulAPol;
                Comparing++;
      
                PulAPol &= 0x40;
                PulLastState &= 0xc0;
                PulAPol >>= 6;      
    }                                                   
}

281229961 发表于 2012-11-24 00:21:40

cpld 四倍频,输出一路方向 一路脉冲 直接单片机中断 接收在中断里判断方向 进行加减计数就可以了!

coleyao 发表于 2012-11-24 08:52:19

foxpro2005 发表于 2012-11-23 23:14 static/image/common/back.gif
以下是我学习您的代码,得出的分析 及 代码添加的注释:
1. 最大响应频率为2K,所以必须小于2K(实际上可 ...

1)如果某个脚有脉冲干扰,应该是左移和右移各加一,对最终结果不影响;
2)如果四次完整的计数才算一个周期,那碰到一半或1/4的计数该如何处理!
另外,我那个计数取决于定时器周期,主频越高,定时器周期就可以设置得越小,处理速度也越快,再有我程序里面计数与脉冲之间应该有2倍关系,我认为这样计数更准确一些。

foxpro2005 发表于 2012-11-24 09:06:17

coleyao 发表于 2012-11-24 08:52 static/image/common/back.gif
1)如果某个脚有脉冲干扰,应该是左移和右移各加一,对最终结果不影响;
2)如果四次完整的计数才算一个 ...

另外,我那个计数取决于定时器周期,主频越高,定时器周期就可以设置得越小,处理速度也越快,再有我程序里面计数与脉冲之间应该有2倍关系,我认为这样计数更准确一些。

1. 定时器周期设得越小, CPU的负担会很重。 (对于相同的脉冲频率,相比INT中断而言)

2. 我觉得程序里面计数与脉冲之间 应该有4倍关系,   因为是对AB相脉冲的上下沿的变化都变检测判断。 如果是2倍关系,可能检测会不准确。

coleyao 发表于 2012-11-24 09:18:14

本帖最后由 coleyao 于 2012-11-24 09:22 编辑

foxpro2005 发表于 2012-11-24 09:06 static/image/common/back.gif
另外,我那个计数取决于定时器周期,主频越高,定时器周期就可以设置得越小,处理速度也越快,再有我程序 ...

那个周期的问题,只能折中处理,在不影响其它程序和中断处理的基础上尽量把周期设短一些,编码器工作的时候尽量与一些实时要求高的任务错开,在定时中断中的代码越少越好,能放到中断外面处理的尽量不要放到中断里面。至于那个计数和脉冲的倍数关系,你可以画时序图验证一下,我印象里面是两倍关系(程序是1年前写的,印象不是很深了)。

foxpro2005 发表于 2012-11-24 09:55:57

coleyao 发表于 2012-11-24 09:18 static/image/common/back.gif
那个周期的问题,只能折中处理,在不影响其它程序和中断处理的基础上尽量把周期设短一些,编码器工作的 ...

我刚画了时序图,您看是这样的么?


这样应该是至少4倍的关系。

coleyao 发表于 2012-11-24 10:12:05

foxpro2005 发表于 2012-11-24 09:55 static/image/common/back.gif
我刚画了时序图,您看是这样的么?




呵呵,那就应该是4倍关系了,我用编码器的时候比较简单,只有一个基数,这个数值定了就好,不关心它究竟是怎么算出来的。

foxpro2005 发表于 2012-11-24 10:21:41

coleyao 发表于 2012-11-24 10:12 static/image/common/back.gif
呵呵,那就应该是4倍关系了,我用编码器的时候比较简单,只有一个基数,这个数值定了就好,不关心它究竟 ...

非常感谢您,这么及时与给力的指导。
页: [1]
查看完整版本: 用旋转编码器来测位置,有一个问题请教