极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 34179|回复: 9

如何准确读取 pulseIn 的数值

[复制链接]
发表于 2014-9-27 22:13:51 | 显示全部楼层 |阅读模式
之前一直都没有用过 PulseIn 的, 最近看到一个 post 中提及 analogRead 及 analogWrite 的问题.
http://www.geek-workshop.com/thread-11126-1-1.html

我尝试用 pulseIn 去还原 PWM 的数值.  做了一个简单的程式回应了问题, 但发觉有一定的偏差.

初时以为是一点波动做成, 加入了不同的滤波方法, 好像都没有效果.
後来细想, 电脑的输出, 怎可能出现 +/- 1 的偏差, 而且间中会出现 +/- 2, 有点不正常.

细心再看看 pulseIn 的说明, 开始明白原因了.

Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out.

当你要求 pulseIn(3, HIGH), 系统会等待 HIGH, 再计算由 HIGH 转 LOW 前的时间.
如果你的切入点是 LOW, 那就可以真正量度出 HIGH 的准确时间.
问题时, 如果切入点本身已是 HIGH, 结果会如果?  就是只计算了 当前 HIGH 转 LOW 的时间.

如下图:



如果执行 pulseIn(3, HIGH) 时在 A 点, 刚好是 HIGH 的状态, 就会开始计时, 在 B 点完结, 只计算了一部份的时间 (红线).

如果执行 pulseIn(3, HIGH) 时在 C 点, 刚好是 LOW 的状态, 就会等到 D 点才开始计时, 在 E 点完结, 可以得到完整的时间 (绿线).

由於 pulseIn 并没有提供选项, 让系统先等待最少一次转变才开始计算, 量度出来的时间, 只会比真实的数值少了.

为了证明自己的推算, 把程式修改一下, 分别找出 pulseIn HIGH / LOW 最大的值去推算, 结果真的可以 100% 还原出来.

换句话说, 如果要准确读取 pulseIn 的数值, 必须要多次读取後, 取最大值才可以.

以下测试程序, 大家有兴趣可以试试, 最後的一个值是用 max 值还原的结果.
有可能头几次会因为未遇上真确值而出错, 经过几次读取後, 应该可以百分百还原的.

  1. void setup() {

  2.   Serial.begin(57600);
  3.   // put your setup code here, to run once:
  4.   pinMode(3, OUTPUT);
  5.   pinMode(8, INPUT);

  6.   analogWrite(3, 155);

  7. }

  8. int max_ph, max_pl;

  9. void loop() {
  10.   // put your main code here, to run repeatedly:
  11.   int ph, pl, val, max_est;
  12.   ph = pulseIn(8, HIGH);
  13.   pl = pulseIn(8, LOW);
  14.   if (ph > max_ph) max_ph = ph;
  15.   if (pl > max_pl) max_pl = pl;
  16.   val = 256.0 * ph / (ph + pl);
  17.   max_est = 256.0 * max_ph / (max_ph + max_pl);
  18.   Serial.print(pl);
  19.   Serial.print("  ");
  20.   Serial.print(ph);
  21.   Serial.print("  ");
  22.   Serial.print(val);
  23.   Serial.print("  |  ");
  24.   Serial.print(max_pl);
  25.   Serial.print("  ");
  26.   Serial.print(max_ph);
  27.   Serial.print("  ");
  28.   Serial.print(max_est);
  29.   Serial.println();
  30.   delay(1000);
  31. }
复制代码

本帖子中包含更多资源

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

x
回复

使用道具 举报

 楼主| 发表于 2014-9-27 22:31:08 | 显示全部楼层
用 max 的值去量度, 应该是最准确没错了.
但经过一段较长时间的数据收集後, 又发现了另一怪事.
根据以上的理论, 进入点可以是任何位置, 那出现的数值应该可以是任何比真实值细的数值.
但现实并非这样, 并没有出现较大的变动, 结果都是很接近最大值的 (见下图), 难道系统本身就会先等一次转换?  只是量度时出了少少偏差, 才会导致数据不准确?

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-27 22:36:29 | 显示全部楼层
难道是内部计时器的偏差, 从数字上看, 跟最大值的差距, 都是 6 左右 (700 -694) 或 (1079-1073).
由於 pulseIn 的结果是 microseconds 为单位, 6 microseconds 的误差对 16MHz 的系统而言, 大約是 96 次 clock tick, 是否可接受呢?
回复 支持 反对

使用道具 举报

发表于 2014-9-27 23:34:25 | 显示全部楼层
写的很清楚了“系统会等待 HIGH, 再计算由 HIGH 转 LOW 前的时间” 否则这个函数没什么意义了。1%的偏差是可以接受的吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-28 01:56:36 | 显示全部楼层
yyy_zc 发表于 2014-9-27 23:34
写的很清楚了“系统会等待 HIGH, 再计算由 HIGH 转 LOW 前的时间” 否则这个函数没什么意义了。1%的偏差是可 ...
For example, if value is HIGH, pulseIn() waits for the pin to go HIGH,


這句說話, 有點不清楚, 說是 "waits for the pint to go HIGH", 但如果一開始就是 HIGH, 是否算是已 go HIGH 呢?
可能是我誤會了吧. "go HIGH" 就已經包括了 由 LOW 轉 HIGH 的意思.

因為之前想要還原 PWM 輸出 0-255 的數值, 1% 的誤差已經是很大了.
電腦之間的通訊, 把 155 變成 154, 如果要測試  if (val = 155) 就已經是 true 變成 false 了.
那 1% 的偏差, 後果可以很大的.
回复 支持 反对

使用道具 举报

发表于 2014-9-28 12:37:13 | 显示全部楼层
Super169 发表于 2014-9-28 01:56
這句說話, 有點不清楚, 說是 "waits for the pint to go HIGH", 但如果一開始就是 HIGH, 是否算是已  ...

更具体的可看一下源码,估计能提供函数给使用,应该是合理的既是标准的可重现的.
另外不回用模拟量来传递数据吧,及时用模拟来编码,也要考虑误差\干扰 时间延迟等,既不能表现为8 bit (256)

if( x > 100 ) &&( x<128)
回复 支持 反对

使用道具 举报

发表于 2014-9-28 14:11:48 | 显示全部楼层
科学研究就需要深入研究。
回复 支持 反对

使用道具 举报

发表于 2014-9-28 20:39:29 | 显示全部楼层
赞同6L说的
回复 支持 反对

使用道具 举报

发表于 2014-9-29 11:48:22 | 显示全部楼层
学习了。我遇到问题想的是怎么绕过去,而LZ却研究上啦。惭愧!
回复 支持 反对

使用道具 举报

发表于 2015-4-22 21:43:32 | 显示全部楼层
看了瞬间茅厕蹲开,哈哈哈,秒懂啊,解释很形象到位。学习了。
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 18:21 , Processed in 0.041816 second(s), 24 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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