以前用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= ; // SW->D4
bool lastButtonStatus = false; void setup()
{
pinMode(SW, INPUT);
digitalWrite(SW, HIGH);//连接按钮的引脚设为上拉
Serial.begin();
} void loop()
{
bool buttonStatus = !digitalRead(SW);//高电平时未按下,状态为false
if (buttonStatus != lastButtonStatus)
{
Serial.println(buttonStatus ? "pressed" : "released");
lastButtonStatus = buttonStatus;//保存当前状态
}
delay();
}

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

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

 //定义引脚连接
int CLK = ;//CLK->D2
int DT = ;//DT->D3
int SW = ;//SW->D4 void setup()
{
pinMode(SW, INPUT);
digitalWrite(SW, HIGH);//连接按钮的引脚设为上拉
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
Serial.begin();
} void loop()
{
if (!digitalRead(SW)) //读取到按钮按下时读取CLK和DT的值
{
int clkValue = digitalRead(CLK);//读取CLK引脚的电平
int dtValue = digitalRead(DT);//读取DT引脚的电平
Serial.print("CLK:");
Serial.print(clkValue);
Serial.print("; DT:");
Serial.println(dtValue);
delay();
}
}

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

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

 //定义引脚连接
int CLK = ;//CLK->D2
int DT = ;//DT->D3
const int interrupt0 = ;// Interrupt 0 在 pin 2 上 void setup()
{
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
attachInterrupt(interrupt0, ClockChanged, CHANGE);//设置中断0的处理函数,电平变化触发
Serial.begin();
} void loop()
{
} //中断处理函数
void ClockChanged()
{
int clkValue = digitalRead(CLK);//读取CLK引脚的电平
int dtValue = digitalRead(DT);//读取DT引脚的电平
Serial.print("CLK:");
Serial.print(clkValue);
Serial.print("; DT:");
Serial.println(dtValue);
}

顺时针旋转一步:

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

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

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

 //定义引脚连接
int CLK = ;//CLK->D2
int DT = ;//DT->D3
int SW = ;//SW->D4
const int interrupt0 = ;// Interrupt 0 在 pin 2 上
int count = ;//计数值
int lastCLK = ;//CLK历史值 void setup()
{
pinMode(SW, INPUT);
digitalWrite(SW, HIGH);
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
attachInterrupt(interrupt0, ClockChanged, CHANGE);//设置中断0的处理函数,电平变化触发
Serial.begin();
} void loop()
{
if (!digitalRead(SW) && count != ) //读取到按钮按下并且计数值不为0时把计数器清零
{
count = ;
Serial.print("count:");
Serial.println(count);
}
} //中断处理函数
void ClockChanged()
{
int clkValue = digitalRead(CLK);//读取CLK引脚的电平
int dtValue = digitalRead(DT);//读取DT引脚的电平
if (lastCLK != clkValue)
{
lastCLK = clkValue;
count += (clkValue != dtValue ? : -);//CLK和DT不一致时+1,否则-1
Serial.print("count:");
Serial.println(count);
}
}

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

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

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

【Arduino】旋转编码器的Arduino使用方法的更多相关文章

  1. Arduino关于旋转编码器程序的介绍(Reading Rotary Encoders)--by Markdown

    介绍 旋转或编码器是一个角度測量装置. 他用作精确測量电机的旋转角度或者用来控制控制轮子(能够无限旋转,而电位器只能旋转到特定位置).其中有一些还安装了一个能够在轴上按的button,就像音乐播放器的 ...

  2. 「雕爷学编程」Arduino动手做(40)——旋转编码器模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  3. T12焊台控制器制作教程 | T12烙铁 | PID增量式算法恒温控制 | 运算放大器-热电偶电压采集 | OLED屏幕显示-SPI通信 | 旋转编码器EC11用户操作

    前言 购买T12烙铁的相关配件已经1年多了,期间也尝试了一些开源的T12控制器,但都没有成功,要么是配套资料少,要么是英文的,其中51和arduino的居多,STM32的较少.求人不如求己,索性自己开 ...

  4. STM32-增量式旋转编码器测量

    Development kit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6 一.增量式旋转编码器 1.简介 编码器(encoder)是将信号(如比特流)或数据进行编制.转换为可 ...

  5. AVR单片机教程——旋转编码器

    好久没写这个系列了.今天讲讲旋转编码器. 旋转编码器好像不是单片机玩家很常用的器件,但是我们的开发板上有,原因如下: 旋转编码器挺好用的.电位器能旋转的角度有限,旋转编码器可以无限圈旋转:旋转时不连续 ...

  6. FPGA旋转编码器的实现

    module pmodenc( clk, rst_n, A, B, BTN,// A_Debounce,// B_Debounce,// BTN_Debounce,// Rotary_right,// ...

  7. 屏幕旋转时调用PopupWindow update方法更新位置失效的问题及解决方案

       接到一个博友的反馈,在屏幕旋转时调用PopupWindow的update方法失效.使用场景如下:在一个Activity中监听屏幕旋转事件,在Activity主布局文件中有个按钮点击弹出一个Pop ...

  8. PCB 合拼遍历(全排序+旋转90度) 基本遍历方法

    分享一下PCB合拼的组合的遍历方法,在分享之前先纠正一下 PCB拼板之多款矩形排样算法实现--学习  时间复杂度计算错误  一.PCB 合拼(全排序+旋转90度)的时间复杂度是多少? 二.合拼遍历(全 ...

  9. Arduino学习笔记① 初识Arduino

    1.前言     近段时间,博主陆续更新了ESP8266学习笔记,主要开发平台是Arduino.但是,对于很多无基础的初学者来说,甚至不了解Arduino是什么.因此,博主决定加入一个Arduino学 ...

随机推荐

  1. jQuery实现全选效果【转】

    这是一段用jquery实现全选的代码,主要思路如下: 1.所有的复选框都有单击事件,所有效果都是在单击事件下实现的 2.全选复选框所实现的功能与其他复选选项实现的功能不同,所有在单击事件内做一个判断, ...

  2. Sublime Text 2配置文件详解

    Sublime Text 2是那种让人会一眼就爱上的编辑器,不仅GUI让人眼前一亮,功能更是没的说,拓展性目前来说也完全够用了,网上介绍软件的文章和推荐插件的文章也不少,而且很不错,大家可以去找找自己 ...

  3. Jingle 相关问题

    1. //page模板默认的相对位置,主要用于开发hybrid应用,实现page的自动装载 basePagePath : 'html/'. 所以所有的section 要放在html文件下面才行

  4. CentOS下设置默认JDK

    最近在弄Linux,用yum源安装opnjdk-devel版本后,用命令ll /etc/alternatives/java查看,发现指向的是jre目录,而不是jdk,在此设置指向jdk目录. 1. 设 ...

  5. (绝对官方好用,快速上手)针对grunt之前写的那篇有些乱,这次总结个清晰的

    安装 Grunt基于Node.js,安装之前要先安装Node.js,然后运行下面的命令. sudo npm install grunt-cli -g grunt-cli表示安装的是grunt的命令行界 ...

  6. hadoop意外之旅--巧合遇到一只大象

    公司面临转型,所有开发也难免面临转型,开始选择自己想要走的方向进行研究. 说来也巧合,最近正好说搭个hadoop环境玩玩,结果遇到转型还被选为大数据小组组长.(尴尬) 开始一场遇到大象之旅,希望能在这 ...

  7. yii2使用相关记录

    #Yii::$app->user 是指yii\web\User这个类 #yii2在命令行下执行 D: cd D:\wnmp\php5 php D:\wnmp\www\yii2\yii test/ ...

  8. 前端页面使用 Json对象与Json字符串之间的互相转换

    前言 在前端页面很多时候都会用到Json这种格式的数据,最近没有前端,后端的我也要什么都要搞,对于Json对象与Json字符串之间的转换终于摸清楚了几种方式,归纳如下! 一:Json对象转换为json ...

  9. 判断网站地址是否是http开头

    var url = ""; if(!string.IsNullOrEmpty(Model.WebsiteURL)){ url = Model.WebsiteURL.ToString ...

  10. GPS部标监控平台的架构设计(八)-基于WCF的平台数据通信设计

    总体来讲,GPS部标平台的软件开发是一个对网络通信和应用程序之间通信的技术应用密集型的开发工作,也是有一定设计技术含量的工作. 1.设计通信接口 在设计的时候,根据职责划分,拆分成不同的应用子系统,对 ...