极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: 急速未来

求助检测继电器开合时间

[复制链接]
发表于 2017-11-16 10:23:13 | 显示全部楼层 |阅读模式
想要实现如下功能:继电器不断的得电失电,然后检测它通断之的时间
我写了代码,用外部中断检测,但测得的时间太大了,有49900微秒,
现在想问大神,我怎么才能测得准确的时间

  1. #include <Wire.h>
  2. #include <LiquidCrystal_I2C.h>
  3. LiquidCrystal_I2C lcd(0x3F,16,2);
  4. unsigned long start, finished, elapsed;
  5. long int i=0;
  6. int pinInterrupt = 2; //接中断信号的脚  
  7.    
  8. void setup()
  9. {
  10.   lcd.init();
  11.   lcd.backlight();
  12.   lcd.print("Ready Test!!!");
  13.   Serial.begin(9600);
  14.   pinMode(4, OUTPUT);
  15.   pinMode( pinInterrupt, INPUT);//设置管脚为输入
  16.   //Enable中断管脚, 中断服务程序为onChange(), 监视引脚变化  
  17.   attachInterrupt( digitalPinToInterrupt(pinInterrupt), onChange, CHANGE);

  18. }
  19. void onChange()  
  20. {  
  21.    if ( digitalRead(pinInterrupt) ==HIGH )  
  22.        start=micros();   
  23.    else  
  24.        finished=micros();   
  25. }
  26. void  relay_go()
  27.   { int p = digitalRead(pinInterrupt);
  28.     digitalWrite(4, HIGH);
  29.     delay(50);
  30.     digitalWrite(4, LOW);
  31.     delay(50);}

  32. void loop()
  33. {   
  34.        relay_go();
  35.        delay(50);
  36.    elapsed=finished-start;
  37.    Serial.print("Elapsed time= ");
  38.    Serial.print(elapsed);
  39.    Serial.println("us");
  40.   lcd.clear();
  41.   lcd.print("Elapsed time= ");
  42.   lcd.setCursor(0, 1);
  43.   lcd.print( elapsed);
  44.   lcd.print("us , ");
  45.   lcd.print(elapsed/1000);
  46.   lcd.print("ms");            
  47. }
复制代码
回复

使用道具 举报

发表于 2017-11-16 13:08:45 | 显示全部楼层
先用笨办法看看真实的数据。

void onChange()  
{  
   if ( digitalRead(pinInterrupt) ==HIGH )  
       start=micros();   
   else  
       finished=micros();
//把   micros() 的值加到全局数组aTimes[]。
}

想得到时间差,用 aTimes[i] - aTimes[i-1] 不就出来了。

串口输出数组内容看看,是不是跟你预期的一样,时间差是否还是49900us
回复 支持 反对

使用道具 举报

发表于 2017-11-16 20:47:57 | 显示全部楼层
49900uS=49.9mS

你在程式中將繼電器 ON 後  DELAY 50mS=50000uS
再 OFF,所測得的時間差 < 50000uS 我猜是接點彈跳
讓 start 值被刷新的關係?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-17 09:55:51 | 显示全部楼层
Stormer 发表于 2017-11-16 13:08
先用笨办法看看真实的数据。

void onChange()  

全局数组这里不是很懂,能具体讲解一下吗?我在代码里应该怎么修改
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-17 09:58:28 | 显示全部楼层
shouzama 发表于 2017-11-16 20:47
49900uS=49.9mS

你在程式中將繼電器 ON 後  DELAY 50mS=50000uS

这个问题怎么解决?还望指教
回复 支持 反对

使用道具 举报

发表于 2017-11-18 07:23:40 | 显示全部楼层
本帖最后由 shouzama 于 2017-11-18 07:44 编辑
急速未来 发表于 2017-11-17 09:58
这个问题怎么解决?还望指教

不過我又想到了,RELAY 並不像電子元件有很高的
反應速度,如果不 DELAY ,有可能接點還沒導通線圈
就又斷電了...

是不是應該把 RELAY 線圈的控制放在中斷程式中,
那麼 RELAY 作動、接點導通觸發中斷控制,記錄 start
時間後,將 PIN4 設為 LOW 切斷 RELAY 電力,接點放開
後再次觸發中斷記錄 finished ,像這樣:

void onChange()  
{  
   if ( digitalRead(pinInterrupt) ==HIGH )  
       start=micros();   
       digitalWrite(4, LOW);    //追加這行切斷 RELAY
   else  
       finished=micros();

先試試看,如果時間每次都差很多,有可能就是接點彈跳
的問題了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-18 11:42:47 | 显示全部楼层
shouzama 发表于 2017-11-18 07:23
不過我又想到了,RELAY 並不像電子元件有很高的
反應速度,如果不 DELAY ,有可能接點還沒導通線圈
就又斷 ...

感谢,我试试,看怎么样
回复 支持 反对

使用道具 举报

发表于 2017-11-19 11:48:25 | 显示全部楼层
应该是计时然后触发继电器,等到继电器另一端的接口检测到高电平,再计时,两个时间相减、。、、得到继电器的响应时间。。  连续测100次,求最大最小和平均值
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-19 15:08:59 | 显示全部楼层
shouzama 发表于 2017-11-18 07:23
不過我又想到了,RELAY 並不像電子元件有很高的
反應速度,如果不 DELAY ,有可能接點還沒導通線圈
就又斷 ...

现在测得的时间又很小,是100us左右,还是不对
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-19 15:30:23 | 显示全部楼层
迷你强 发表于 2017-11-19 11:48
应该是计时然后触发继电器,等到继电器另一端的接口检测到高电平,再计时,两个时间相减、。、、得到继 ...

之前就是这么测的,但是上电只能测一次,
在这是代码,麻烦你看下怎么改成多次测量

  1. #include <Wire.h>
  2. #include <LiquidCrystal_I2C.h>
  3. LiquidCrystal_I2C lcd(0x3F,16,2);
  4. unsigned long start, finished, elapsed;
  5. boolean D7_flag;
  6. boolean D8_flag;
  7. long int i=0;

  8. void setup()
  9. {
  10.   lcd.begin();
  11.   lcd.backlight();
  12.   lcd.print("Ready Test!!!");
  13.   Serial.begin(9600);
  14.   pinMode(4, OUTPUT); // Coil action output signal
  15.   pinMode(7, INPUT); // start ,Coil input signal
  16.   pinMode(8, INPUT); // stop ,Contact input signal
  17.   D7_flag = false;
  18.   D8_flag = false;
  19.   
  20.   for(i=1;i<=100;i++)
  21.   {
  22.   digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  23.   delay(50);               // wait for a second
  24.   digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
  25.   delay(50);  
  26.   lcd.setCursor(0, 1);
  27.   lcd.print("CountDown=");
  28.   lcd.print(100-i);
  29.   if(i==1||i==90)
  30.   {
  31.   lcd.clear();
  32.   lcd.print("Ready Test!!!");
  33.   }
  34.   }  
  35. }

  36. void loop()
  37. {
  38. digitalWrite(4, HIGH);

  39. {
  40. if ((digitalRead(7) == HIGH) && (!D7_flag))
  41. {
  42.    //start=millis();
  43. start=micros();
  44. D7_flag = true;
  45. //Serial.println("Started...");
  46. }

  47. if ((digitalRead(8) == HIGH) && (!D8_flag))
  48.   {
  49.     // finished=millis();
  50.   finished=micros();
  51.   D8_flag = true;
  52.   //Serial.println("Stop...");
  53.   Serial.print("Elapsed time= ");
  54.   elapsed=finished-start-8;
  55.   Serial.print(elapsed);
  56.   Serial.println("us");
  57.   lcd.clear();
  58.   lcd.print("Elapsed time= ");
  59.   lcd.setCursor(0, 1);
  60.   lcd.print( elapsed);
  61.   lcd.print("us , ");
  62.   lcd.print(  elapsed/1000);
  63.   lcd.print("ms");
  64.   }
  65. }
  66. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2017-11-19 16:09:37 | 显示全部楼层
急速未来 发表于 2017-11-19 15:08
现在测得的时间又很小,是100us左右,还是不对

果然,您測到的應該是接點閉合時,瞬間第一次彈跳的時間差 -_-"

回歸問題本身,是像 8 樓網友說的,是要測繼電器線圈 ON~接點ON 的
時間差(ON作動反應時間)? 還是要試接點 ON 立即斷電使接點 OFF,
測量接點 ON~OFF 的時間差?

好像是前一種會比較有意義,那麼就像 8 樓網友說的做法囉,
您貼的程式碼是另一位網友的耶...(同一位?)
那問題依邏輯來看只差在旗號沒復歸、繼電器沒斷電重來,
所以不會跑第二次,您說修改後也不行...那我就幫不上忙了
回复 支持 反对

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 20:57 , Processed in 0.048228 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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