旋转编码器编程原理实例
如何使用旋转编码器、编码开关,旋转编码开关、编码器的原理
在电子产品设计中,经常会用到旋转编码开关,也就是所说的旋转编码器、数码电位器、Rotary Encoder 。它具有左转,右转功能,有的旋转编码开关还有按下功能。为了使刚接触这种开关的朋友了解旋转开关的编程,我来介绍下它的原理和使用方法:
以我厂生产的EC11型编码开关为例:如图1:
三只脚:1 2 3脚一般是中间2脚接地,1、3脚上拉电阻后,当左转、右转旋转时,在1、3脚就有脉冲信号输出了。
两只脚:为按压开关,按下时导通,回复时断开。
在单片机编程时,左转和右转的判别是难点,用示波器观察这种开关左转和右转时两个输出脚的信号有个相位差,如图2。
由此可见,如果输出1为高电平时,输出2出现一个高电平,这时开关就是向顺时针旋转;当输出1 为高电平,输出2出现一个低电平,这时就一定是逆时针方向旋转。
所以,在单片机编程时只需要判断当输出1为高电平时,输出2当时的状态就可以判断出是左旋转或是右旋转了。
旋转编码开关(Rotary Encoder switch)
我前面介绍的2篇文章:“自己动手做收音机(LC72131) ”和“电脑USB接口LCD液晶显示板(LCD Smartie)”都使用了这种旋转编码开关(Rotary Encoder switch),一个使用3脚的,后面一个使用5脚的,大家可能对这种玩意都不是很了解,但涉及到有调整的地方,这个玩意使用真是很爽,我弄了2个,研究了一下,供大家参考,
5脚的ALPS:
<-- ALPS Incremental Encoder (EC11 series)
具有左转,右转,按下三个功能。4、5脚是中间按下去的开关接线 1 2 3脚 一般是中间2脚接地,1、3脚上拉电阻后,当左转、右转旋纽时,在1、3脚就有脉冲信号输出了。这是标准资料:
在单片机编程时,左转和右转的判别是难点,用示波器观察这种开关左转和右转时两个输出脚的
信号有个相位差,见下图:
由此可见,如果输出1为高电平时,输出2出现一个高电平,这时开关就是向顺时针旋转; 当输出
1 为高电平,输出2出现一个低电平,这时就一定是逆时针方向旋转.
所以,在单片机编程时只需要判断当输出1为高电平时,输出2当时的状态就可以判断出是左旋转
或是右旋转了。
还有另外一种3脚的,除了不带按钮开关外,和上面是一样的使用。
---------------------- 我是分隔线 ----------------------
编码器总结(类似音响上的音量调节旋钮) 1.要求旋转速度快,调节就快,速度慢,,调节就慢
2.机械的编码器要24脉冲/每转,勉强可以分辨3到4种速度(每隔100ms计算一次速度),,机械的缺点是有毛刺,,寿命短,,通常在1万转左右,,不过bounce的号称20万转 3.希望编码器每转的脉冲愈多愈好,霍尔的编码器和光电的编码器脉冲都很多,,但是价格都很高,,唉
4.cui的编码器最好了,啥都有,按钮功能也有,,配套的旋钮也有,,完美,,可是国内没有卖的
---------------------- 我是分隔线 ----------------------
旋转编码器
检测
工程第三方检测合同工程防雷检测合同植筋拉拔检测方案传感器技术课后答案检测机构通用要求培训
转动方向的电路
---------------------- 我是分隔线 ---------------------- 旋转编码器的抗抖动计数电路
摘要:旋转编码器应用于角度定位或测量时,由于旋转轴的晃动可能引起编码器输出波形的,从而引发误计数现象。介绍了一个抗抖动计数电路,滤除了旋转编码器因抖动而造成的误计数。
关键词:旋转编码器 抗抖动电路 数字电路
旋转编码器应用于角度定位或测量时,通常有A、B、Z三相输出。旋转编码器的输出波形见图1。A相和B相输出占空比为50%的方波。编码器每转一周,A相和B相输出固定数目的脉冲(如100个脉冲)。当编码器正向旋转时,A相比B相超前四分之一个周期;当编码器反向旋转时,B相比A相超前四分之一个周期。A相和B相输出方波的相位差为90?。编码器每转一周,Z相输出一个脉冲。由于编码器每转一周,A相和B相输出固定数目的脉冲,则A相或B相每输出一个脉冲,
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示编码器旋转了一个固定的角度。当Z相输出一个脉冲时,表示编码器旋转了一周。因此
旋转编码器可以测量角位移及位移方向。 问题出在伺服系统停止工作时,若无锁定,则旋转轴受外力(如风力影响)可能自由晃动,因而引起编码器输出波形抖动,如图2所示,从而引起误计数。在这种情况下,就不能对波形进行正确计数。虽然可以通过软件设置标志状态,用记录历史状态的变化来滤除误计数,但是程序耗费颇大。因此,本人设计了一个抗抖动计数电路。它能够自动消除抖动造成的误计数。 1 抗抖动计数电路原理图
图3是抗抖动计数电路原理图。此电路滤除了旋转编码器输出波形的抖动现象。该电路分为四个部分:译码电路U4A;互锁电路U5A、U5B;正旋计数链J1、J3、J5和反旋计数链J2、J4、J6。U4A为二四译码器,U5A、U5B为与门,J1,J6为D触发器。正旋计数链负责对编码器正向旋转的计数,反旋计数链负责对编码器反向旋转的计数。
2 抗抖动计数电路工作分析
图4为二四译码器输出的波形。译码器产生d、a、b、c四种不同的状态。在图3中当B=0、A=0时,译码器Q0输出为d状态,d状态为高电平。当B=0、A=1时,译码器Q1输入为a状态,a状态为高电平。当B=1、A=1时,译码器Q2输出为b状态,b状态为高电平。B状态不影响计数和方向确定,在图3电路中没有使用。当B=1、A=0时,译码器Q3输出为c状态,c状态为高电平。
当旋转编码器正向旋转时,译码器输出的状态顺序为d、a、b、c、d、a、b、c……。如图4所示。当B=0、A=0时,进入d状态,与门U5A的Pin2=a=0(Pin是管脚的意思),于是U5A的输出Pin3=0。D触发器J1的R=d=1、S=0,因此J1被清0.与门U5B的Pin5=c=0,于是U5B的输出Pin4=0。D触发器J2的R=d=1、S=0,因此J2也被清0。这时J1、J2的Q端都为1,与门U5的Pin1=Pin6=1,U5A和U5B都处于等待开门状态。当进入状态a时,Q1=a=1,U5A的Pin2=a=1。
由于c=0,所以J2的Q端仍为1,U5A的Pin1=1,U5A的输出Pin3=1.J1的R=d=0、S=1,因此J1被置1。J1的Q=1,Q=0。J1的Q=1,正旋标志送到了J3的D端。时J1的Q端关闭了U5B。
在下一个d出现之前,所有的c脉冲都不会改变J2的状态。这就说,J1、J3、J5组成的正旋计数链被打开,J2、J4、J6组成的反旋计数链被阻断。U5A、U5B、J1、J2完成互锁的功能。在进入状态a时,J3的R=a=1、S=0,J3被清0,J5的R=a=1、S=0,J5被清0.在进入状态c前,J3的R=a=0、S=0、D=1,J3处于待触发状态。J3的CLK=c,当c脉冲上升沿过后,D=1被打入J3的Q端,正旋标志送到了J5的D端。在进入状态d前,J5的R=a=0、S=0,J5处于待触发状态。J5的CLK=d,当d脉冲上升沿过后,D=1被打入J5的Q端,正旋标志送到了正旋计数输出端。正旋计数输出端由低电平变为高电平。到此为止,完成了一次正旋计数。当由状态d进入状态a时,J5的R=a=1、S=0,J5被清0,正旋计数输出端由高电平变为低电平。由此可知,当旋转编码器正向旋转时,对应A相 B相的每一个完整周期,正旋计数输出端都会产生相应的一个脉冲。
A的出现抢到了正旋计数权。只有在d重新出现后,脉冲c才可能有机会抢到反旋计数权。从而保证了一旦进入正旋计数状态,不全完成这一过程,就进入不了反旋计数状态。运行时有可能从状态a返回状态d,结果这只不过释放正旋计数权。因这时正旋标志还只在J3输入端上,a出现时已把J3清0。D状态只会把0送给J5的Q端,因此不会产生误计数。
当旋转编码器反向旋转时,译码器输出的状态顺序为d、c、b、a、d、c、b、a……。这种情况的分析方法与正向旋转的分析方法相同,这里不再叙述。
这就好比接力赛。在一个只允许上一个人的封闭的环形跑道上依次均匀设d、a、b、c、四个站,立四个裁判员。d点为起止点、出入口,持棒运动员沿环形跑道一站站往下跑。D裁判长的职责是:运行员往a去(顺行),告示:“有人,正向”;往c去(逆行),告示:“有人,反相”。其他裁判员的职责是给到达本站的运动员发签证(计数标志),往回跑,撤销签证。d裁判长的计分规则是:凭其他裁判的签证齐全加牌示,正,加一分,反,减一分,然后撤销签证。签证不齐到d,则不计分,撤销签证。运行员在跑道内来回跑或坐时,d裁判视而不见。
例如在图2中,当从状态d进入状态a时,正旋标志送到J3的D端。此后的a、b、a、b、a、b都不起作用,只是把J3和J5反复清0.当从状态c进入状态d时,正旋标志到正旋计数输出端,同时J1和J2被清零。在从状态d进入状态c后,反旋标志送到J4的D端。同时,D=0被打入J3的Q端,这时J5的D端为零。在从状态c回到状态d后,反旋计数权被释放。但是,由于J5的D
端为零,虽然这里再次出现状态d,该d脉冲不会发生计数,这就是抗抖动。
图5为抗抖动计数电路的输出波形。此电路计数频率可达10MHz。A相和B相输入前应予整形,必要时还要进行电隔离。
本人把此电路用于对在线云台角度的定位与测量。天线云台有两个旋转角度,俯仰角从0,90度,方位角从0,354度。旋转编码器用的是OMROM公司的E6A2。此编码器每转一周,A相或B相输出一百个脉冲。由此可得,抗抖动计数电路每输出一个脉冲,编码器旋转的角度是3.6度。如果加上变速齿轮将会提高角度测量精度。把抗抖动电路的正旋计数输出和反旋计数输出接到单片机的中断管理上,其下降沿时给单片机发中断。单片机把处理的角度信息送到显示屏上显示出来,从而完成了对天线云台角度的定位与测量。这套天线角度显示系统在实际使用中运行一直很稳定,没有出现过误计数现象。
---------------------- 我是分隔线 ---------------------- 1mm Size Metal Shaft Encoder EC11 Series
(Incremental Encoder)
Detail
Part number EC11E09204A4
Structure Vertical
Actuator configuration Flat
Actuator length 20mm
Torque 10?7mN?m
Number of detent 18
Number of pulse 9
Operating direction Vertical
Push-on switch Without
Operating life 15,000 cycles
Minimum order unit (pcs.) 1,200
-30? to +85? Operating temperature range
Maximum operating current (Resistive load) 10mA
Ratings 10mA 5V DC
Output of A and B signals,
Output signal proportionate to phase Electrical
difference performance
Insulation resistance 100MΩ min. 250V DC
Voltage proof 300V AC for 1 minute
Push-pull strength 100N Mechanical
Resistance to Manual performance 350? max. 3s max. soldering heat soldering
Durability Operating life 15,000 cycles
-40?3? for 240h Cold
Environmental 85?3? for 240h Dry heat performance
60?2?, 90 to 95%RH for 240h Damp heat
Photo
Dimensions
Mounting Hole Dimensions
Viewed from mounting side.
Output Wave
Sliding Noise
At R=5kΩ Chattering: 3ms max. Bounce: 2ms max.
Product Varieties
Single-shaft Type
1) Knourled Type Unit : mm Style (Shaft diameter : φ6)
2) Flat Type Unit : mm Style (Shaft diameter : φ6)
3) Slotted Type Unit : mm Style (Shaft diameter : φ6)
Notes are common to this series/models.
, This site catalog shows only outline specifications. When using the
products, please obtain formal specifications for supply.
, Please place purchase orders per minimum order unit (integer).
, Products other than those listed in the above chart are also available.
Please contact us for details.
, This products can be used in vehicles.
Although these products are designed to perform over a wide operating
temperature range, please ensure that you receive and read the formal
delivery specifications before use.
Inquiries about Products
For more information please contact: Products Information Center.
1-7, Yukigaya-otsukamachi, Ota-ku, Tokyo, 145-8501, Japan
Phone: +81 (3) 5499-8154
Series 288 Encoder 16 mm Rotary Encoder Low cost, robust design Miniature 16mm style
Bushing mounted
PC terminals, with shaft parallel
or perpendicular to PC board
2 bit, 4 bit Gray and 4 bit
Hexidecimal codes
available Continuous rotation
Available with 16 detents
Optional momentary switch
Electrical and Mechanical Specifications
Power Rating 100 milliwatts
Voltage Rating Operating maximum 50 VAC
Operating Temperature Standard: -25?C to +100?C
Contact Resistance 5,000 ohms static closed circuit maximum
1 megohm minimum open circuit Detent Points 16 detents available
Contact CTS for special requirements Momentary Switch Rating 16 VDC, 20 mA
Switch Life 15,000 actuations
Switch Contact Resistance Initial cycle - 100 milliohms MAX
After life cycle - 200 milliohms MAX Switch Operation Force 350 ? 150 g force (12.3 oz ? 5.3 oz) Switch Bounce 5 milliseconds MAX
Switch Travel Length 0.5 mm / .020"
Pull and Thrust on Shaft Withstand a pushing force and pulling force of 8 kg static load
applied to axial direction for 10 ? 1 second without physical
damage or electrical degradation
---------------------- 我是分隔线 ----------------------
按键旋转编码器(涡轮)程序
51:
void polling_volume_sw(void)
{
BYTE bSWValue=0;
static BYTE iLastData=0;
static BYTE iSWTempData = 0;
#if defined(SUPPORT_USE_SW_SCANF_CODER) ||
defined(SUPPORT_USE_SW_SCANF_LEVEL)
polling_check_vfdsw();
return;
#elif defined(VOLUME_SW_USE_IO)
GPIO_M_SET(13,1); //GAME DI
GPIO_M_SET(14,1); //GAME DO
GPIO_E_SET(13,0);
GPIO_E_SET(14,0);
bSWValue =( (GPIO_I_GET(14)<<1) | (GPIO_I_GET(13) ));
#endif
if(bSWValue != iSWTempData)
iSWTempData = bSWValue;
else
{
switch(bSWValue)
{
case 0:
if(iLastData ==2)
iLastData ++;
break;
case 1:
if(iLastData ==1)
iLastData++;
else if(iLastData ==3)
{
call_ir_func(IRC_VOLUME_UP);
iLastData = 0;
}
break;
case 2:
if(iLastData ==1)
iLastData ++;
else if(iLastData == 3)
{
call_ir_func(IRC_VOLUME_DN);
iLastData = 0;
}
break;
case 3:
iLastData =1;
break;
default:
break;
}
}
#endif
}
sunplus(dvd) 环境:需源程序支持:
//
// generic GPIO operations
//
#define GPIO_I_GET(a) ((regs0->gpio_in[a/16] >> (a%16)) & 0x01)
#define GPIO_O_SET(a,d) ((d) ? (regs0->gpio_out[a/16] |= (1<<(a%16))) \
: (regs0->gpio_out[a/16] &= ~(1<<(a%16))) ) #define GPIO_E_SET(a,d) ((d) ? (regs0->gpio_oe[a/16] |= (1<<(a%16))) \
: (regs0->gpio_oe[a/16] &= ~(1<<(a%16))) ) #define GPIO_M_SET(a,d) ((d) ? (regs0->gpio_master[a/16] |= (1<<(a%16))) \
: (regs0->gpio_master[a/16] &= ~(1<<(a%16))) )
#ifdef SUPPORT_XINZENYU_JOB_VOLUME //Refee 080905 BYTE volume_a_buf = 0;
BYTE volume_b_buf = 0;
void Check_Job_Volume_Key(void)
{
GPIO_M_SET(13,1); //Pin62 Game_D0
GPIO_M_SET(14,1); //Pin63 Game_D1
GPIO_E_SET(13,1);
GPIO_E_SET(14,1);
GPIO_O_SET(13,1);
GPIO_O_SET(14,1);
volume_a_buf = volume_a_buf<<1;
if(!GPIO_I_GET(13)) volume_a_buf++;
volume_b_buf = volume_b_buf<<1;
if(!GPIO_I_GET(14)) volume_b_buf++;
volume_a_buf = volume_a_buf & 0x7;
volume_b_buf = volume_b_buf & 0x7;
if(volume_a_buf == 0x04)
{
if(volume_b_buf >= 0x06)
call_ir_func(IRC_VOLUME_DN);
else
call_ir_func(IRC_VOLUME_UP);
volume_a_buf = 0;
volume_b_buf = 0;
}
}
#endif
---------------------- 我是分隔线 ---------------------- 这段不是很好,对于质量很差的编码器就问题较大了,需要加一些处理:
void Check_Job_Volume_Key(void) {
static unsigned char last_gpio1=0; static unsigned char last_gpio2=0; static unsigned char last_gpio3=0; static unsigned char last_gpio4=0; static unsigned char last_gpio5=0; static unsigned char last_gpio2_1=0;
unsigned char gpio1;
unsigned char gpio2;
regs0->gpio_first[1]|= (0x1<<5); //Set pin9 as GPIO21
regs0->gpio_first[1]|= (0x1<<13); //Set Pin52 as GPIO29
GPIO_M_SET(21,1);
GPIO_M_SET(29,1);
GPIO_E_SET(21,0);
GPIO_E_SET(29,0);
//GPIO_O_SET(21,1);
//GPIO_O_SET(29,1);
gpio1=GPIO_I_GET(21);
gpio2=GPIO_I_GET(29) ;
if
((gpio1)&&(last_gpio1)&&(last_gpio2)&&(!last_gpio3)&&(!last_gpio4)&&(!last_gpi
o5))
{
if (gpio2&&last_gpio2_1)
call_ir_func(IRC_VOLUME_DN); else if ((!gpio2)&&(!last_gpio2_1)) call_ir_func(IRC_VOLUME_UP); }
last_gpio2_1=gpio2;
last_gpio5=last_gpio4;
last_gpio4=last_gpio3;
last_gpio3=last_gpio2;
last_gpio2=last_gpio1;
last_gpio1=gpio1;
}
参考:
#include "reg51.h"
#define uint unsigned int
sbit CodingsWitch_A=P1_1; sbit CodingsWitch_B=P1_2;
uint CodingsWitchPolling()// {
static Uchar Aold,Bold; //定义了两个变量用来储蓄上一次调用此方法是编码开关两引
脚的电平
static Uchar st; //定义了一个变量用来储蓄以前是否出现了两个引脚都为高电平的
状态
uint tmp = 0;
if(CodingsWitch_A&&CodingsWitch_B)
st = 1; //
if(st) //如果st为1执行下面的步骤
{
if(CodingsWitch_A==0&&CodingsWitch_B==0) //如果当前编码开关的两个引
脚都为底电平执行下面的步骤
{
if(Bold) //为高说明编码开关在向加大的方向转
{
st = 0;
tmp++; //
}
if(Aold) //为高说明编码开关在向减小的方向转
{
st = 0;
tmp--; //设返回值
}
}
}
Aold = CodingsWitch_A; //
Bold = CodingsWitch_B; //储
return tmp; // }
//编码器计数程序
void encoder_cnt(void)
{
uchar temp;
temp = PIND; //取端口D管脚信号
couch_clr = (temp & 0x08); //取编码器清零信号
if(couch_clr != false) //有编码器清零信号
{
couch_num = 0; //水平床码清零
}
else
{
if(encoder_cnt_en == false) //编码器计数模块没有启动
{
pr_couch_ba = temp & 0x03; //取编码器A、B相电平信号
}
else
{
couch_ba = temp & 0x03; //取编码器A、B相电平信号
if(pr_couch_ba == 0x00)
{
if(couch_ba == 0x01)
{
couch_num++; //水平床码加1
}
else if(couch_ba == 0x10)
{
couch_num--; //水平床码减1
}
}
else if(pr_couch_ba == 0x01)
{
if(couch_ba == 0x11)
{
couch_num++; //水平床码加1
}
else if(couch_ba == 0x00)
{
couch_num--; //水平床码减1
}
}
else if(pr_couch_ba == 0x10)
{
if(couch_ba == 0x00)
{
couch_num++; //水平床码加1
}
else if(couch_ba == 0x11)
{
couch_num--; //水平床码减1
}
}
else if(pr_couch_ba == 0x11)
{
if(couch_ba == 0x10)
{
couch_num++; //水平床码加1
}
else if(couch_ba == 0x01)
{
couch_num--; //水平床码减1
}
}
}
pr_couch_ba = couch_ba;
}
}
旋转编码器的检测程序(MCS51)
//旋转编码器检测程序,,,,信号分别接在了,,,,和,,,,上
//程序作者:,,,,,,
//2005年1月15用,,,,编译、硬件测试通过
//注意:编码器的信号,程序未做消抖处理。测试中,,,,信号上各
//接了一只,,,的瓷片电容,工作很正常。如果不接电容,请自行编
//写信号消抖程序。
#include
sbit led=0xB1;//有一只,,,接在了RXD引脚上,用来指示正反转;
main()
{
EA=1; //总中断允许
EX0=1; //外部中断,允许
IT0=1; //外部中断,为边沿触发方式
while(1);;
}
/********************* 编码器中断函数
入口:无
出口:无
*********************/ void encoder(void) interrupt 0 { //外部中断0 if (INT1){
led=1;
}else{
led=0;
}
}
AVR程序
//外部中断0,用于编码开关解码,解码图: A接中断脚(AVR的PD2),以此为基准,B用来判断方向(连到AVR的PA1), C接地
//A -|
// | -----|__________|----------|____________
//C -|
//
//B -|
// | ----------|__________|----------|____________
//C -|
// CW ===>>> ROTATION //外部中断设置(ISC01=0,ISC00=1): INT0 引脚上任意的逻辑电平变化都将引发中断 #pragma interrupt_handler int0_isr:2 void int0_isr(void)
{
//external interupt on INT0
GICR=0; //禁止外部中断
if ((PIND & 0x04)==0) //先判断是高电平产生的中断还是低点平的中断
if ((PINA & 0x02)==0) //再判断B线上的电平
{
keycounter--;
keydirection=0;
}
else
{
keycounter++;
keydirection=1;
}
else
if ((PINA & 0x02)==0)
{
keycounter++;
keydirection=1;
}
else
{
keycounter--;
keydirection=0;
}
GICR=0x40;
}