用中断方式去检测旋转编码器的 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();
}
我这个读取数值时,有问题,用步进电机带动转一周时,每次读的数值都不一样。
高人有无可靠稳定的算法呢? 一定要消抖动,也可用扫描方式读取,本站之前有讨论过的,你找找看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+
注意软解是不适合跑高速的 手动的那种一周12-30线的解码非常容易,加个电容消抖,一个引脚中断后看看另一个引脚状态就OK了。用步进电机带高分辨率旋转编码器的时候,电机的速度很重要,高速启动的时候可能就会丢步,编码器输出肯定有差别。速度太低,电机如果有抖动,问题更糟。我试过50-300转的带200线编码器,计数非常精确。我使用DSP算得 谢谢【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) 设标志位,正转B下沿A=1,OK。这样可消除抖动 【4楼】 JYLJYL
兄弟可以来点小例子不? 可靠,稳定。估计要用状态机了。 我用PIC和ALPS EC11B旋转编码器采用中断方式做了个硬件试验,应该说比较可靠,用电容消抖,并有PROTEUS仿真,仅供参考.点击此处下载 ourdev_476051.rar(文件大小:40K) (原文件名:rosw3.rar)
http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_476052.png
(原文件名:r.png) TO LS兄弟,如果编码器走得很慢或很快时,你这个恐怕都会出现数值不准吧。 我做过实验,似乎没发现什么问题.当时用串口调试,快慢都试过. 先谢谢【9楼】 eezm 兄弟
你可否讲下你的思路呢? mark mark 中断方式检测旋转编码器
芯片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;} // 数值减小清除左旋转有效
} To 【13楼】 xuelx
你的程序不错,谢谢! 最近看的头都大了 硬件电路到底该怎么接 给个实例吧,用起来没问题的,不存在多次来回低速抖动时计数不准的现象,当然有软解码的通病:速度上不去(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;
}
}
再给个硬件的,仿真过但没实际用过 请问一下,为什么ALPS有三相的旋转编码器,是不是空出C相不要接,然后另外两个A,B上拉,接PIC单片机口变化中断,只要有口变化中断,是A口就+1,是B口-1,
这样是不是最简单的检测方法呀。有没有人这样做过?
xuelx 发表于 2011-7-26 16:58 static/image/common/back.gif
中断方式检测旋转编码器
芯片ATMEGA128
13楼程序今天试着用了一下,要转两格才能自加自减啊? 嗯,学习中....,下午有空实验一下xuelx,coleyao大侠的程序...
感谢你们的分享.. 学习了,顶下 路过,学习一下 程序不错,这个是1倍速度的解码方式,防抖动
是1倍速度的解码方式 路过,看看大婶们 记下了,学习学习 只搞过那种手动的几十线的- -用的1ms的轮询
用中断的话搞个定时器,在中断触发后禁用IO中断,开定时器,定时器中断里面再重新开IO中断实现延时不知道靠谱不 mark 标记 如果再来测速度的话,这个程序怎么改? 旋转编码器,mark 注意软解是不适合跑高速的 30K
可以 大于30K就不稳定了 mark 如果频率高,还是不要这样用吧?特别是还有其他程序的时候,你的程序不会只单单处理编码器吧?当然做做数字电位器之类的另当别论。 shinehjx 发表于 2009-8-29 14:25
一定要消抖动,也可用扫描方式读取,本站之前有讨论过的,你找找看http://www.ourdev.cn/bbs/bbs_list.jsp? ...
为什么软解不适合跑高速 xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器
芯片ATMEGA128
感觉写错了吧,向左旋转,怎么会是Right=0XFF 额,编码器和步进电机怎么用啊 傻孩子大师的思路很不错的喔,用外部中断,上升沿下降沿都触发,再判断其他端口的信息 请问上面各位讲的编码器,是不是型号为EC11之类的? i=(PINE>>4)&0x03; // 读取编码器的A.B脚电平值 (AB接PE4 PE5)PE4是外部中断4
请讲一下,14楼的这句是如何检测PE4,PE5脚的电平值?我不是太理解。谢谢了。 似乎有些懂了。“PINE>>”是将PINE的值右移4位,然后和0x03(00000011)相与,得到 i 值的。 本帖最后由 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;} // 数值减小清除左旋转有效
} xuelx 发表于 2011-7-26 16:58
中断方式检测旋转编码器
芯片ATMEGA128
好方法,还从没用过软解码
页:
[1]