极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 144807|回复: 29

也谈Arduino与旋转编码器的两种连接方式(中断方式,普通D口)

  [复制链接]
发表于 2012-3-4 14:59:34 | 显示全部楼层 |阅读模式
本帖最后由 supercctv 于 2012-3-4 15:03 编辑

翻出去年在北京中发买的旋转编码器,测试了下与arduino的连接。

原理图就不画了,旋转编码器 A,B端分别接10K上拉至VCC,A、B端分别与Arduino主板连接。有时环境存在干扰,会反跳的话,A、B端再通过0.1uf的电容接地即可。

分别测试了两种的连接方式,均成功。

1.采用中断方式。参照czad先前的帖子。我把程序简化了下,意图仅在于说明旋转编码器的正反计数即可。
  1. #define PinA 2  //中断0
  2. #define PinB 3  //中断1

  3. unsigned long time = 0;
  4. long count = 0; //计数值
  5. long num = 0;

  6. //初始化
  7. void setup()
  8. {
  9.   Serial.begin(9600); //窗口初始化

  10.   pinMode(PinA,INPUT); //D2脚为输入
  11.   pinMode(PinB,INPUT); //D3脚为输入

  12.   attachInterrupt(0, blinkA, LOW);  //注册中断0调用函数blinkA
  13.   attachInterrupt(1, blinkB, LOW);  //注册中断1调用函数blinkB

  14.   time = millis(); //时间初值
  15. }

  16. //主体程序
  17. void loop()
  18. {
  19.   while (num != count)
  20.   {
  21.     num = count;
  22.     Serial.println(num);
  23.   }
  24. }

  25. //中断0调用函数
  26. void blinkA()
  27. {
  28.   if ((millis() - time) > 3) //防抖动处理
  29.         count ++;
  30.   time = millis();
  31. }

  32. //中断1调用函数
  33. void blinkB()
  34. {
  35.   if ((millis() - time) > 3)  //防抖动处理
  36.         count --;
  37.   time = millis();
  38. }
复制代码
有图有真相:


2.采用普通Digital口的方式,这里用D4与D5。第一种方法要用掉两个中断,有点浪费,有时中断端口要留着其他用处。参考Arduino Cookbook第二版。PS:第一版中,那个图是错误。
  1. const int encoderPinA = 4;
  2. const int encoderPinB = 5;

  3. boolean encoderALast = LOW;  // remembers the previous pin state

  4. void setup()
  5. {
  6.   pinMode(encoderPinA, INPUT);
  7.   pinMode(encoderPinB, INPUT);
  8.   digitalWrite(encoderPinA, HIGH);
  9.   digitalWrite(encoderPinB, HIGH);
  10.   Serial.begin (9600);
  11. }

  12. void loop()
  13. {
  14.   boolean encoderA = digitalRead(encoderPinA);
  15.   if ((encoderALast == HIGH) && (encoderA == LOW))
  16.   {
  17.     if (digitalRead(encoderPinB) == LOW)
  18.     {
  19.       encoderPos--;
  20.     }
  21.     else
  22.     {
  23.       encoderPos++;
  24.     }
  25.     Serial.print (encoderPos);
  26.   }
  27.   encoderALast = encoderA;
  28. }
复制代码
有图有真相:




旋转编码器的问题该完结了吧,哈哈~

我在极客的第一帖,特此留念~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2012-7-5 00:10:29 | 显示全部楼层
收藏,关于ARDUINO 与编码器的 应用 资料实在太少了,就找到SIMON MONK 的那个实例,还没试
回复 支持 反对

使用道具 举报

发表于 2012-7-27 18:09:04 | 显示全部楼层
有没有计数的中断啊  (我也不知道啊 )  我看着上面写的那个中断太频繁了   
回复 支持 反对

使用道具 举报

发表于 2012-7-27 20:46:05 | 显示全部楼层
本帖最后由 pww999 于 2012-7-27 20:48 编辑

学习了,

中断就系停止当前,执行其它,完后,最回来执行当前未完的?   

请问实际用途在那?

在什么时候设置用中断?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-7-29 22:40:36 | 显示全部楼层
pww999 发表于 2012-7-27 20:46
学习了,

中断就系停止当前,执行其它,完后,最回来执行当前未完的?   

个人认为,和你需要控制的外设的时序有关。
如果旋转编码使用普通IO进行驱动的话,就要写在你的主程序里面。响应的时间,需要考虑主程序其他操作的。
如果在中断里面,那自然主程序遇到中断会停止,然后执行中断操作,当然也许评估中断对主程序的影响。
至于用于什么场合,需要具体情况,具体分析
回复 支持 反对

使用道具 举报

发表于 2012-7-30 03:22:25 | 显示全部楼层
pww999 发表于 2012-7-27 20:46
学习了,

中断就系停止当前,执行其它,完后,最回来执行当前未完的?   

用在同时执行的时候    比如你在写作业顺便烧了一壶水     水开了   就是中断     你得处理一下   然后继续写你的作业   OK??
回复 支持 反对

使用道具 举报

发表于 2012-7-30 07:51:53 | 显示全部楼层
小黑 发表于 2012-7-30 03:22
用在同时执行的时候    比如你在写作业顺便烧了一壶水     水开了   就是中断     你得处理一下   然后继 ...

单片机都是单线程的吧?
程序都是由上往下执行?
往往用IF 判断 是否继续写作业 还是水开了要处理一下?
只是不太明白
回复 支持 反对

使用道具 举报

发表于 2012-8-5 19:51:39 | 显示全部楼层
试了一下

中断计数时有时会数值突变成好几百,或者几千,不准确

而用普通IF 计算很准确?
回复 支持 反对

使用道具 举报

发表于 2012-8-9 13:33:47 | 显示全部楼层
好段子,先MARK一下备用~~
回复 支持 反对

使用道具 举报

发表于 2013-3-31 16:05:12 | 显示全部楼层
楼主的方法在电机低速情况下可用,电机转速一高则无法识别。因为楼主判正转,反转的方法是用延时来识别的,若要做到高速情况下可用,应外加D触发器,从而实现正转触发中断0,翻转触发中断1
回复 支持 反对

使用道具 举报

发表于 2013-4-13 12:44:02 | 显示全部楼层
勤奋工作 发表于 2013-3-31 16:05
楼主的方法在电机低速情况下可用,电机转速一高则无法识别。因为楼主判正转,反转的方法是用延时来识别的, ...

同意,而且手册里说attachinterrupt调用函数mills时,返回值是不会发生变化的。
Note
Inside the attached function, delay() won't work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function.
回复 支持 反对

使用道具 举报

发表于 2013-4-13 15:49:52 | 显示全部楼层
我看数据手册说在中断函数中,millis()会失效,测试也的确如此,另外中断中不能直接调用普通变量,如果变量要在中断中访问,要使用volatile进行申明,测试也是的确如此。你的这段代码能正常运行吗?
回复 支持 反对

使用道具 举报

发表于 2013-6-22 16:30:48 | 显示全部楼层
这两种哪个准确些?高速时
回复 支持 反对

使用道具 举报

发表于 2013-7-5 10:00:58 | 显示全部楼层
{:soso_e179:}两种方法都很好,学习了
回复 支持 反对

使用道具 举报

发表于 2013-7-7 22:24:41 | 显示全部楼层
http://playground.arduino.cc/Main/RotaryEncoders   这个可以看看 挺好的
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-27 00:28 , Processed in 0.052899 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表