博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Arduino】旋转编码器的Arduino使用方法
阅读量:6800 次
发布时间:2019-06-26

本文共 3859 字,大约阅读时间需要 12 分钟。

以前用CRT显示器的时候,调整显示器的时候用一个圆盘转动和点击的方法就可以实现选择菜单和修改设置项的值,比多个按钮的方式方便很多。

鼠标滚轮也是这种操作方法,旋转+点击,只是方向不同。最近在网上买了旋转编码器模块,想把它用到实际制作中。在网上找了很多资料,测试发现其中的代码或多或少都有问题。于是决定自己研究一下旋转编码器的原理,只涉及高低电平应该会比较简单。

我买的旋转编码器模块有5个引脚,分别是VCC, GND, SW, CLK, DT。其中VCC和GND用来接电源和地,按缩写SW应该是Switch(开关)、CLK是Clock(时钟)、DT是Data(数据)。

 

网上的资料虽然代码不是很理想,但介绍的原理基本是没问题的。旋转编码器的操作是旋转和按压转轴,在按下转轴的时候SW引脚的电平会变化,旋转的时候每转动一步CLK和DT的电平是有规律的变化。在只接电源的情况下先测一下各种操作时引脚电平的变化,没有示波器只好用万用表测电压。

点击:SW(红)+GND(黑)时按下和松开按钮没有任何变化,VCC(红)+SW(黑)松开时表针指向0,按下时高电平。据此可以推测SW平时为高阻态,按下时接地。用Arduino检测的方法是设置连接SW的引脚为INPUT并上拉输出高电平,检测到引脚为低电平则表示按钮按下,以下代码可以正确检测出按钮的变化。

//定义引脚连接int SW= 4;  // SW->D4bool lastButtonStatus = false; void setup(){  pinMode(SW, INPUT);  digitalWrite(SW, HIGH);//连接按钮的引脚设为上拉  Serial.begin(9600);} void loop(){  bool buttonStatus = !digitalRead(SW);//高电平时未按下,状态为false  if (buttonStatus != lastButtonStatus)  {    Serial.println(buttonStatus ? "pressed" : "released");    lastButtonStatus = buttonStatus;//保存当前状态  }  delay(100);}

旋转:CLK(红)+GND(黑),每旋转一次(和方向无关),电平转换一次,DT(红)+GND(黑),变化情况和上一种情况一致,并且CLK和DT的电平保持一致。VCC(红)+CLK(黑),VCC(红)+DT(黑)也是同样的情况。CLK(红)+DT(黑)或者CLK(黑)+DT(红)时,每次旋转(和方向无关)指针都会轻微摆动然后归零,并且相邻两步指针的摆动方向相反。结论:每次旋转CLK和DAT引脚的电平都会变化,电平变化有时间差,但无法区分往哪个方向旋转。

编写测试代码,在按下按钮的时候读取CLK和DT的值:

1 //定义引脚连接 2 int CLK = 2;//CLK->D2 3 int DT = 3;//DT->D3 4 int SW = 4;//SW->D4 5   6 void setup() 7 { 8   pinMode(SW, INPUT); 9   digitalWrite(SW, HIGH);//连接按钮的引脚设为上拉10   pinMode(CLK, INPUT);11   pinMode(DT, INPUT);12   Serial.begin(9600);13 }14  15 void loop()16 {17   if (!digitalRead(SW)) //读取到按钮按下时读取CLK和DT的值18   {19     int clkValue = digitalRead(CLK);//读取CLK引脚的电平20     int dtValue = digitalRead(DT);//读取DT引脚的电平21     Serial.print("CLK:");22     Serial.print(clkValue);23     Serial.print("; DT:");24     Serial.println(dtValue);25     delay(1000);26   }27 }

测试发现不管顺时针还是逆时针旋转,每次按下按钮之后读取的CLK和DT的值都是一样的,并且相邻两步之间的值是不一样的,符合用万用表测量的结果。

万用表测量时发现CLK和DT的变化有一定的时间差,可以用Arduino在CLK电平变化的瞬间读取DT的值,可能会找到其中的规律。改成通过中断0监控CLK上的电平变化,读取CLK和DT的电平值:

1 //定义引脚连接 2 int CLK = 2;//CLK->D2 3 int DT = 3;//DT->D3 4 const int interrupt0 = 0;// Interrupt 0 在 pin 2 上 5   6 void setup() 7 { 8   pinMode(CLK, INPUT); 9   pinMode(DT, INPUT);10   attachInterrupt(interrupt0, ClockChanged, CHANGE);//设置中断0的处理函数,电平变化触发11   Serial.begin(9600);12 }13  14 void loop()15 {16 }17  18 //中断处理函数19 void ClockChanged()20 {21   int clkValue = digitalRead(CLK);//读取CLK引脚的电平22   int dtValue = digitalRead(DT);//读取DT引脚的电平23   Serial.print("CLK:");24   Serial.print(clkValue);25   Serial.print("; DT:");26   Serial.println(dtValue);27 }

顺时针旋转一步:

顺时针旋转3步(用横线分隔):

逆时针旋转3步(用横线分隔):

根据以上测试结果,每旋转一次触发的中断次数不一致,可能是硬件本身引起的,类似按钮抖动。多次测试之后,查看每次变化的最后一组值,顺时针旋转时CLK和DT的值不一致,逆时针旋转时CLK和DT的值一致。修改代码,顺时针时对计数值加1,逆时针时对计数值减1,按下按钮时计数值清零。

1 //定义引脚连接 2 int CLK = 2;//CLK->D2 3 int DT = 3;//DT->D3 4 int SW = 4;//SW->D4 5 const int interrupt0 = 0;// Interrupt 0 在 pin 2 上 6 int count = 0;//计数值 7 int lastCLK = 0;//CLK历史值 8   9 void setup()10 {11   pinMode(SW, INPUT);12   digitalWrite(SW, HIGH);13   pinMode(CLK, INPUT);14   pinMode(DT, INPUT);15   attachInterrupt(interrupt0, ClockChanged, CHANGE);//设置中断0的处理函数,电平变化触发16   Serial.begin(9600);17 }18  19 void loop()20 {21   if (!digitalRead(SW) && count != 0) //读取到按钮按下并且计数值不为0时把计数器清零22   {23     count = 0;24     Serial.print("count:");25     Serial.println(count);26   }27 }28  29 //中断处理函数30 void ClockChanged()31 {32   int clkValue = digitalRead(CLK);//读取CLK引脚的电平33   int dtValue = digitalRead(DT);//读取DT引脚的电平34   if (lastCLK != clkValue)35   {36     lastCLK = clkValue;37     count += (clkValue != dtValue ? 1 : -1);//CLK和DT不一致时+1,否则-138     Serial.print("count:");39     Serial.println(count);40   }41 }

测试发现大多数时候可以正确输出:

偶尔旋转不是很顺畅会出现跳动的情况,这时候能感觉到旋钮在两步之间跳动了一下。看到有人说在引脚和地之间接上滤波电容会好一些,实际测试发现并没有改善。推测由于旋钮是D字型的,用手旋转的时候确实会出现跳动的情况,装上旋钮帽之后应该会避免这种情况。

旋转编码器可以用于需要精确调整值(电位器不准确),操作菜单等场合。后续会使用旋转编码器制作一些小东西,也欢迎大家分享旋转编码器相关代码。

 

转载于:https://www.cnblogs.com/conexpress/p/4984802.html

你可能感兴趣的文章
爬虫采集-基于webkit核心的客户端Ghost.py [爬虫实例]
查看>>
学霸装学渣
查看>>
Microsoft Dynamics CRM 2015 完全安装好以后 完全备份
查看>>
git 在windows下的应用(一) - 本地仓库代码管理
查看>>
符合通用准则(common criteria compliance)
查看>>
APP-V5.0的Sequencer过程
查看>>
IBM X3650 M3服务器上RAID配置实战
查看>>
Objective-C中的@class,SEL和IMP等灵活机制
查看>>
2030中国足球称霸世界
查看>>
工信部:《关于加强电信和互联网行业网络安全工作的指导意见》
查看>>
开源可实现迁移
查看>>
融合式架构Nutanix深入分析一
查看>>
RHEL6.3下配置简单Apache https
查看>>
利用Cocos2dx-3.0新物理特性模拟弹珠迷宫
查看>>
Office 365系列之三:Office365初体验
查看>>
VMware View client for iPad在医疗行业的应用
查看>>
Altiris 7.1 Agent
查看>>
独家爆料:创宇云与小鸟云的故事
查看>>
Windows Server 2012 RMS for Exchange Server 2013
查看>>
Linux网络IP配置
查看>>