Pages: [1] 2 3   Go Down
Author Topic: pulseIn Bug  (Read 5145 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've found a pretty bad bug with pulseIn, it made an appearance sometime between 0018 and 1.0.  With 0018 pulseIn ends as soon as the pulse being monitored ends, in 1.0 there appears to be about a 40-50 uS "dead time" where pulseIn waits, after the pulse being monitored has ended.  This causes the sketch to miss subsequent pulses if they start during this "dead time."

I found the problem when modifying a project that had been written using 0018 to run on a MEGA2560, which required a newer IDE.

A bigger problem is that I can't find any mention in the changelog of work being done on pulseIn that may have affected the function in this way.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8966
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is no obvious cause for a 40-50 microsecond delay.  It doesn't look like the code has been touched since 2007.  Perhaps something in your code between calls to pulseIn() is introducing  a delay.

wiring_pulse.c:
Code:
#include "wiring_private.h"
#include "pins_arduino.h"

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
 * or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
 * to 3 minutes in length, but must be called at least a few dozen microseconds
 * before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution.  calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long width = 0; // keep initialization out of time critical area

// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 16 clock cycles per iteration.
unsigned long numloops = 0;
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask)
if (numloops++ == maxloops)
return 0;

// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask)
if (numloops++ == maxloops)
return 0;

// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
if (numloops++ == maxloops)
return 0;
width++;
}

// convert the reading to microseconds. The loop has been determined
// to be 20 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
return clockCyclesToMicroseconds(width * 21 + 16);
}
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is why I'm confused, as I've checked the code myself and can't figure out what it is.

See this topic I started for more information: http://arduino.cc/forum/index.php/topic,86039.0.html

All I can tell you is if I use Arduino 1.0 to program my Arduino I get this error.  If I use Arduino 0018 I do not get this error.  Results are quite consistent.  I urge you (or anyone else, really) to try this out and confirm (or refute) that this is a bug, because I'm pretty well stumped.

For extra frustration, I don't think my Arduino MEGA2560 is supported by 0018, which means I need to use an older Duemilanove which has a few issues when I try to program it.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A quick update.

I just started marching backwards through the Arduino IDEs, starting at 1.0.  I noticed this error in everything newer than 0021.  However, 0021, with a quick test, appears to work as intended.

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13855
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the length of the pulse you are trying to measure?  

I'm asking this as few months I reported a bug in pulseIn() regarding overflow in the math under some conditions.
See - http://code.google.com/p/arduino/issues/detail?id=675 - for the details.

COuld you please post the code - or better a minimized version that still produces this side-effect aka bug ?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the length of the pulse you are trying to measure?

They're between 40 - 150 uS.  You can see in the plot I've posted, though I apologize it's not great resolution, I just posted it to illustrate working results.
COuld you please post the code - or better a minimized version that still produces this side-effect aka bug ?

If you look in the link I posted above, I have another thread I started before I realized this appears to be a bug.  Here's what's running to capture that plot above.

Code:
  noInterrupts();
  digitalWrite(Y, HIGH);
  P = pulseIn(X, LOW, usLong);
  digitalWrite(Y, LOW);
  a = pulseIn(X, LOW, usLong);
  digitalWrite(Y, HIGH);
  b = pulseIn(X, LOW, usLong);
  digitalWrite(Y, LOW);
  c = pulseIn(X, LOW, usLong);
  digitalWrite(Y, HIGH);
  d = pulseIn(X, LOW, usLong);
  digitalWrite(Y, LOW);

  interrupts();

The BLUE trace is X, the RED trace is Y.  I was using Y as a simple method to show when exactly pulseIn starts and stops.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13855
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


From the picture (more than good enough) I see the following:  correct me if I'm wrong

- The blue signal looks like it really takes time to get up to its max => looks like a "big capacitor effect". Are you using long/thick cables?
- The blue signal is 3V. IIRC this is in the undefined range of TTL levels. It just could be that the HIGH level is not seen as HIGH


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


From the picture (more than good enough) I see the following:  correct me if I'm wrong

- The blue signal looks like it really takes time to get up to its max => looks like a "big capacitor effect". Are you using long/thick cables?
- The blue signal is 3V. IIRC this is in the undefined range of TTL levels. It just could be that the HIGH level is not seen as HIGH

1) You can ignore the ramp up effects...that's a hardware issue in my custom shield that I'm aware of.

2) Yep, I'm playing with a "black box" that uses 3V logic.  I've checked the datasheet for the MEGA2560 (Page 267), and anything over .6*Vcc (3V) is HIGH, so it should be fine, though it is pretty close to the edge.  I've got a hardware fix I'm working on to do proper level shifting (would also fix issue in #1), but I haven't bothered with that yet because I've seen this hardware work.

So yes, you are correct on both, but neither actually matter.  I've proven, to myself at least, that going from Arduino 1.0 to 0021 fixes the problem, at least at a quick glance.  I encourage you to try a similar setup, at 5V.  I'd like to try that, but I don't have time to do that right now.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8594
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Does that trace show working or non-working code?

The behavior shown there looks correct to me.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does that trace show working or non-working code?

The behavior shown there looks correct to me.

That image shows it working, when using Arduino 0021.  If you clicked on the link above, you would see the original post (before I thought this was a bug) that shows the following image of it not working.



The code is the same.  The only difference is what compiler I'm using.  The bug does not appear to be in the pulseIn function itself, though there are some slight modifications between versions.  I suspect the problem lies in interrupt handlers, perhaps for Serial communications, but I don't have the time, or experience, to dig in and find the solution myself.

I hope that the developers responsible for the Arduino IDE see this (or, tell me where their bug tracker is, because I couldn't find one linked on this website), because this seems like a pretty clear bug to me.  Behavior should not change depending on the compiler used, especially without giant warnings to let users know of possible issues.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13855
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I suspect the problem lies in interrupt handlers,
An interrupt at the wrong moment can indeed "ruin" measurements, but is your code receiveing bytes while measuring? If no then there are no interrupts...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I suspect the problem lies in interrupt handlers,
An interrupt at the wrong moment can indeed "ruin" measurements, but is your code receiveing bytes while measuring? If no then there are no interrupts...


Nothing else is happening when I am trying to take these measurements, but there is an open serial port (using the Serial commands).

For all intents and purposes, this appears to be resolved on my part by moving to an older Arduino IDE.  I do apologize for being a "this isn't my problem" type of person, but I simply don't have time to troubleshoot this.  All I can say is I've found what appears to be a regression bug, and I want to make sure the right people know.
Logged

Guildford, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 218
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For all intents and purposes, this appears to be resolved on my part by moving to an older Arduino IDE.  I do apologize for being a "this isn't my problem" type of person, but I simply don't have time to troubleshoot this.  All I can say is I've found what appears to be a regression bug, and I want to make sure the right people know.
But until someone else can reproduce the issue you have reported, nothing will happen.

Iain
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For all intents and purposes, this appears to be resolved on my part by moving to an older Arduino IDE.  I do apologize for being a "this isn't my problem" type of person, but I simply don't have time to troubleshoot this.  All I can say is I've found what appears to be a regression bug, and I want to make sure the right people know.
But until someone else can reproduce the issue you have reported, nothing will happen.

Iain

I've encouraged others to do so.  I believe it should be easy enough to do, though you may need two Arduinos (or a function generator) since you won't be able to read a pulse while triggering another one, though you might be able to do something with interrupts, but that might have unintended results.  Voltage shouldn't matter, so long as your LOW is under 0.1Vcc (500 mV) and your HIGH is over 0.6Vcc (3 V).  I suspect it won't take long to do a quick test, but it would take some effort to properly regression test this.  I've already done my "quick" testing, and I don't have the time, or knowledge of the Arduino IDE's guts, to do proper regression testing.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8966
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just started marching backwards through the Arduino IDEs, starting at 1.0.  I noticed this error in everything newer than 0021.

From the Release Notes:
ARDUINO 0022 - 2010.12.24
* Applying the timeout parameter of pulseIn() during measurement of the pulse, not just while waiting for it.

What value is your timeout (usLong)?  Perhaps you are encountering timeout errors.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Pages: [1] 2 3   Go Up
Jump to: