|
|
之前一直都没有用过 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 值还原的结果.
有可能头几次会因为未遇上真确值而出错, 经过几次读取後, 应该可以百分百还原的.
- void setup() {
-
- Serial.begin(57600);
- // put your setup code here, to run once:
- pinMode(3, OUTPUT);
- pinMode(8, INPUT);
-
- analogWrite(3, 155);
-
- }
-
- int max_ph, max_pl;
-
- void loop() {
- // put your main code here, to run repeatedly:
- int ph, pl, val, max_est;
- ph = pulseIn(8, HIGH);
- pl = pulseIn(8, LOW);
- if (ph > max_ph) max_ph = ph;
- if (pl > max_pl) max_pl = pl;
- val = 256.0 * ph / (ph + pl);
- max_est = 256.0 * max_ph / (max_ph + max_pl);
- Serial.print(pl);
- Serial.print(" ");
- Serial.print(ph);
- Serial.print(" ");
- Serial.print(val);
- Serial.print(" | ");
- Serial.print(max_pl);
- Serial.print(" ");
- Serial.print(max_ph);
- Serial.print(" ");
- Serial.print(max_est);
- Serial.println();
- delay(1000);
- }
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|