EC09旋转编码器含C示例程序(实测可用)
1.1 前言
最近正在做一个基于EC09-6.5C-TZ-GW编码器的无极调光项目,功能是可以通过两个Encoder编码器调节灯具的亮度和色温。但之前从未使用过这个编码器,故整理做个记录,顺便分享给需要的小伙伴参考使用,因本人水平有限,请谨慎参考和使用。
2.1 基础信息
我手上的是12P/360°的,指的是旋转360°发生12个周期脉冲 。
2.2 编码器原理图:
( 原理图说明:上图为编码器的原理图,A 和 B 分别接单片机的IO口。如果连接A B 的单片机IO是准双向IO,上拉电阻可省略; 如果电源纹波较大,且程序无消抖处理,建议A、B端各加一个104的滤波电容。)
基本工作原理:
通过旋转轴来拨动编码器内的两个开关,使两个开关周期性开合从而实现两组带有相位差的周期性的信号输出。MCU则是通过编程来识别这两组信号的差异从而识别不同的信号输入。
优势:可以连续地调整改变信号,对于需要连续输入的场景尤其方便,而且体验更好。
2.3 仿真测试板:
2.4 EC09 输出波形数据分析
官方手册数据:
实际抓取正转数据:
实际抓取反转数据:
数据分析:
2.4.1 如何区分正反转?
如图所示,根据上下两路的数据位置,可以区分出正反转,把他们转换成 1/0 就好理解和程序处理了。可知,正转:0 - 1 ;反转: 1 - 0;
缺点,需要统计两个都变成低电平前高电平的时间,需要计时和考虑何时清零的问题;因此,使用了第二种方式,即运动趋势判断法;
运动趋势判断法:
上图是正转的下降沿数据截图,考虑到拧动过程会有很多干扰,但是他们的特点是,正转时B会首先有个下降沿,随后是杂波,此时A仍旧保持高电平,忽略后面的杂波,
仅考虑A B 哪个首先产生下降沿,同时判断另一个是否为高电平,即可知此时是否在正转。反转同理。
(PS: 如果使用下降沿判断,需要开上拉或者外部上拉,保证闲时处于高电平)
2.4.2 如何判断转了几圈?
这个项目EC09是:12P/360°,也就是说转一圈会产生12个脉冲数据,统计都变低后的个数即可知转动圈数(下降沿一次进入,防止重复++)。
2.4.3 程序如何检测和判断?
使用1ms扫描,此处判断趋势方法不做消抖处理,具体使用步骤(编程逻辑思路)如下:
step 1.先判断转动的方向,确定是正传还是反转;
step 2.判断编码器的转动数据,进行处理;
3.1 程序源码
判断方法:即通过判断趋势的方式进行判断此时是在正转还是反转。
/****************************************************** *函数名称: EC09_编码器A获取 驱动函数 *函数描述: *判断条件: *其它说明: *时间周期: 1ms *******************************************************/ void EC09_A1B1_Driver(void) { /**********************EC09状态分析**********************/ // 先判断旋转方向 if(encoder.pinA1_low_now==1 && encoder.pinB1_low_now==0) // 判断首个变低电平后另一个的状态 { encoder.EC1_Positive_Flag = 1; //正转标志 } else if(encoder.pinA1_low_now==0 && encoder.pinB1_low_now==1) { encoder.EC1_Negative_Flag = 1; //反转标志 } else if(encoder.pinA1_low_now==0 && encoder.pinB1_low_now==0) { if( encoder.EC1_Positive_Flag ) { encoder.EC1_Positive_Flag = 0; //正转标志 encoder.add_sub1_status = 1; //+ } if( encoder.EC1_Negative_Flag ) { encoder.EC1_Negative_Flag = 0; //正转标志 encoder.add_sub1_status = 2; //- } if( ++encoder.dislock_times >= 2 ) // 如果进入收藏模式,只要旋钮动作即解除 { encoder.dislock_times = 0; dislove_daemon(); } PIN_ECA1B1_Update(); } else { encoder.EC1_Positive_Flag = 0; // 停止旋转,复位 encoder.EC1_Negative_Flag = 0; } }
下面是编码器A B 状态检测处理函数,目的是为了给上一个函数告知此时的状态,从而进行处理;
/****************************************************** *函数名称: EC09_IO状态扫描 *函数描述: *判断条件: *其它说明: *时间周期: 1ms *******************************************************/ void EC09_A1B1_Scan() { if( PIN_ECA1_PIN ) { encoder.pinA1_low_now = 0; } else encoder.pinA1_low_now = 1; if( PIN_ECB1_PIN ) { encoder.pinB1_low_now = 0; } else encoder.pinB1_low_now = 1; }