本帖最后由 suncat0504 于 2023-11-24 13:36 编辑
#申请原创# @21小跑堂
平时买个什么模块,需要测试是否正常。通常这种情况下,我优先选择用ESP8266或者其它可以在ArduinoIDE下使用的开发板来测试。原因无他,因为可以直接使用支持库、以及连接、下载、串口测试显示接收等方便,不需要额外做其他事情。所以当买来的旋转编码器在拿到手里后,立马就用ESP8266来测试了。
论坛里已经有不少伙计发了有关编码器的帖子,我这里也就不再详细说明编码器的资料了,只上干货。
先看看ESP8266的引脚图:
旋转编码器的接口:
编码器的电原理图:
输出信号:
A、B两相都输出方波,顺时针方向旋转时,A相超前B相90度,逆时针方向旋转时,B相超前A相90度;
为了方便接线和测试,我用洞洞板重新改了接线方式,使所有接线都放在一侧。使用ESP8266的D1,D2这两个口采集A、B数据。
为了方便看编码器旋转时信号的变化,首先使用以下程序进行测试:- // 本程序使用ESP8266测试旋转编码器,使用D1(GPIO5)接A,D2(GPIO4)接B
- // 引脚定义
- #defineBMQ_A 5
- #defineBMQ_B 4
- // 旋转标志变量
- unsignedchar flag = 0;
- // 上次状态
- unsignedchar status_old = 0;
- // 当前状态
- unsignedchar status_cur = 0;
- // 旋转计数,顺时针:+1;逆时针:-1
- int cnt = 0;
- void setup(){
- // 串口设置
- Serial.begin(115200);
-
- // LED设置
- pinMode(LED_BUILTIN, OUTPUT);
- // 设置D1(GPIO5)、D2(GPIO4)为数字输入口
- pinMode(BMQ_A, INPUT); // D1 - A
- pinMode(BMQ_B, INPUT); // D2 - B
- // 设置中断,下降沿和上升沿均触发中断
- //attachInterrupt(digitalPinToInterrupt(BMQ_A), a_proc, FALLING | RISING);
- //attachInterrupt(digitalPinToInterrupt(BMQ_B), b_proc, FALLING | RISING);
- status_old=digitalRead(BMQ_A)*2+digitalRead(BMQ_B);
- }
- void loop(){
- status_cur=digitalRead(BMQ_A)*2+digitalRead(BMQ_B);
- if(status_old != status_cur){
- status_old=status_cur;
- Serial.print("A:");
- Serial.print(digitalRead(BMQ_A));
- Serial.print(" B:");
- Serial.println(digitalRead(BMQ_B));
- }
- }
- // 中断处理函数,边沿触发
- IRAM_ATTR void a_proc(){
- status_cur=digitalRead(BMQ_A)*2+digitalRead(BMQ_B);
- if(status_cur != status_old){
- status_old=status_cur;
- Serial.print("a_proc ");
- Serial.print("A:");
- Serial.print(digitalRead(BMQ_A));
- Serial.print(" B:");
- Serial.println(digitalRead(BMQ_B));
- }
-
- }
- IRAM_ATTR void b_proc(){
- status_cur=digitalRead(BMQ_A)*2+digitalRead(BMQ_B);
- if(status_cur != status_old){
- status_old=status_cur;
- Serial.print("b_proc ");
- Serial.print("A:");
- Serial.print(digitalRead(BMQ_A));
- Serial.print(" B:");
- Serial.println(digitalRead(BMQ_B));
- }
- }
运行后,从串口收集到的信息如下:
初始化状态:A:0 B:0
1、顺时针旋转一格场合:
A:1 B:0
A:1 B:1
A:0 B:1
A:0 B:0
2、逆时针旋转一格场合
A:0 B:1
A:1 B:1
A:1 B:0
A:0 B:0
程序改为边沿中断触发处理场合(需要开放Setup中attachInterrupt的中断设置代码,注释掉loop中代码)
1、顺时针旋转一格场合:
a_proc A:1 B:0
b_proc A:1 B:1
a_proc A:0 B:1
b_proc A:0 B:0
2、逆时针旋转一格场合
b_proc A:0 B:1
a_proc A:1 B:1
b_proc A:1 B:0
a_proc A:0 B:0
和循环处理的取得数据变化是一致的。可以使用中断方式来处理。根据数据的变化规律,准备用以下逻辑进行判断处理,
1、初始化时记录A、B口数据,计算为A*2+B
2、中断发生时,采集数据,数据发生变化并且匹配顺时针或者逆时针的变化规律时,存储到标志数组,
3、采集到的变化数据够4个时,与变化规律进行比较,从而判断出是顺时针旋转,还是逆时针旋转。
整理代码如下:
以上代码是经过了以下测试,没有任何问题的,响应速度也很快:
1、慢速顺时针旋转测试
2、慢速逆时针旋转测试
3、快速顺时针旋转测试
4、快速逆时针旋转测试
5、快速旋转中顺时针、逆时针无规律快速切换测试
6、旋转一格不到,就回位,或者反转的测试
以上处理逻辑,应该同样适用于ARM、RISC等其它架构的单片机。
对不喜欢动手敲太多代码的朋友,你也可以选择安装别人做好的名为“Encoder”的库,有现成的例子可以帮助你。
|