极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12606|回复: 5

关于外部中断无法正确读取光码盘脉冲

[复制链接]
发表于 2015-3-23 11:39:00 | 显示全部楼层 |阅读模式
用一个光码盘计算电机转速,用示波器检测到输出的是40Hz的矩形波。

可是用外部中断计数然后串口输出(1s左右输出一次)的计数有400、700多的,各种离谱(正常1s接近一圈20个孔计数应该20~40)


中断相关的代码:
attachInterrupt(0, interruptR, RISING);  //在setup里

void interruptR()                        //right wheel interrupt function
{   countR += 1;   }

脉冲输出接到数字口2口(中断0),有共地。


一些实验:
1、用了Uno和Mega 2560 都测过,均不能准确计数,Mega的6个中断口都测过,每个口的计数不一样,有在400、500、100、700、1000等波动的,但都是不稳定却远远超出理论值。
2、用自带的pwm输出口给中断口计数,把128的pwm波输出,是能稳定计数的,每次计数显示490或491,十分稳定。两块板子都没问题。
3、光电码盘模块的输入电压是3.3V~5.0V,我用板上的3.3V和5.0V电压供电也是无法正常工作的(会改变矩形波的最大电压,记得分别是3.7和5.4V)。怕板子供电电流驱动能力不够,也用外部稳定5V电压供电过(共地),也是没用。
4、也试过防抖,没什么效果。。。
5、在51单片机上是能稳定准确计数的。

实在没辙了,求救!!!

完整代码:
  1. #define IN1 4      //IN1,2 control left motor
  2. #define IN2 5
  3. #define IN3 6      //IN3,4 control right motor
  4. #define IN4 7
  5. #define ENA 9     //pin with #
  6. #define ENB 10     //pin with #
  7. int pwmENA = 128, pwmENB = 128;
  8. volatile unsigned long countR = 0;                //count for keepline. right with ENB
  9. volatile unsigned long countL = 0;
  10. volatile unsigned long time1, time2,;

  11. void setup()
  12. {

  13.   Serial.begin(115200);
  14.   //motor
  15.   pinMode(IN1, OUTPUT);
  16.   pinMode(IN2, OUTPUT);
  17.   pinMode(IN3, OUTPUT);
  18.   pinMode(IN4, OUTPUT);
  19.   pinMode(ENA, OUTPUT);
  20.   pinMode(ENB, OUTPUT);
  21.   time1 = millis();
  22.   time2 = millis();

  23.   
  24.   //interrupt
  25.   attachInterrupt(0, interruptR, RISING);  
  26.   attachInterrupt(1, interruptL, RISING);  


  27. }

  28. void loop()
  29. {

  30.   if((millis() - time1) > 1000)
  31.   {
  32.     speedFeedback();
  33.     time1 = millis();
  34.   }
  35.   forward();
  36. }

  37. void forward()
  38. {
  39.   analogWrite(ENA, pwmENA);
  40.   analogWrite(ENB, pwmENB);
  41.   digitalWrite(IN1, HIGH);        // left motor forward
  42.   digitalWrite(IN2, LOW);
  43.   digitalWrite(IN3, HIGH);        //right motor forward
  44.   digitalWrite(IN4, LOW);
  45. }

  46. void interruptR()                        //right wheel interrupt function
  47. {
  48.           countR += 1;
  49. }
  50. void interruptL()
  51. {

  52. //  if((millis() - time2) > 3)        //之前加的防抖
  53. //  {
  54.           countL += 1;
  55. //        time2 = millis();
  56. //  }


  57. }
  58. void speedFeedback()
  59. {
  60.         Serial.print("right    ");
  61.         Serial.print("-----");
  62.         Serial.println(countR);
  63.         Serial.print("left    ");
  64.         Serial.print(pwmENA);
  65.         Serial.print("-----");
  66.         Serial.println(countL);
  67.         countL = 0;
  68.         countR = 0;
  69. }
复制代码
回复

使用道具 举报

 楼主| 发表于 2015-3-23 11:41:03 | 显示全部楼层


实验检测的时候都是USB连着电脑,然后外部电源给电机驱动模块和arduino供电。
回复 支持 反对

使用道具 举报

发表于 2015-4-20 19:47:17 | 显示全部楼层
楼主解决掉这个问题了么? 我貌似也遇到了。。不懂编码盘,读数各种乱跳。
回复 支持 反对

使用道具 举报

发表于 2015-4-20 23:29:26 | 显示全部楼层
有示波器是最好的了,可以看一下波形如何,上升沿是否有抖动,大概多长时间的抖动,再处理掉就可以了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-4 12:43:18 | 显示全部楼层
IambernMa 发表于 2015-4-20 19:47
楼主解决掉这个问题了么? 我貌似也遇到了。。不懂编码盘,读数各种乱跳。

我的解决了,是用一个光耦模块,把光码盘输出的脉冲接到光耦模块,再输出到arduino中。祝顺利!!
回复 支持 反对

使用道具 举报

发表于 2015-5-8 10:23:24 | 显示全部楼层
_卓小鱼 发表于 2015-5-4 12:43
我的解决了,是用一个光耦模块,把光码盘输出的脉冲接到光耦模块,再输出到arduino中。祝顺利!!

哦,我也是,自己做了个隔离才好了~ 多谢回复。
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 01:55 , Processed in 0.038457 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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