pulseIn always returns 0

Just spent the whole afternoon trying to get pulseIn to work grrrrrrrrrrr: it always returns 0 for me, even though I'm sure the pin I'm reading has been sent high for a while....

Here's what I tried to do: basically used the code in the reference, where it uses pulseIn to read pin 7. I have a push switch on that pin, pulled low thru a resistor when open, and pulled up to 5v when pushed.

First a question about how pulseIn actually works.... while it's waiting for the pulse and then timing it, or timing out, does the next line of code run? It seems it does, because when I switch on an led right after the pulsein, it goes on immediately, as if the program didn't pause while the pulsein did its thing.

That made we worry that the main loop was getting back to the pulsein on the next cycle, and restarting the clock....

So I put a 5 second delay at the bottom of the loop, to make sure that either my 2 second timeout will have completed (2000000 microseconds), or that my quick click of the button will have been read as a pulse.

But it ALWAYS returns 0, ie it always timesout.

Here's one version of the code.... I checked with my meter that the output from the switch is indeed going high

// trying to figure out how pulsein works
// going to pulse a high onto pin 7 thru a push switch
// pin 7 is pulled low thru 10k when switch open
// so a press/release is a low-high-low

int pin = 7;
unsigned long duration; //how long a press

void setup()
{
  pinMode(pin, INPUT); //going to be reading it
  pinMode(13, OUTPUT); //use the led as a marker
  digitalWrite(13, LOW);
  Serial.begin(9600); //going to output duration to monitor
}

void loop()
{
 // two quick flashes on 13 to show we at top of loop
 digitalWrite(13, HIGH);
  delay(500);
 digitalWrite(13, LOW);
  delay(500);
 digitalWrite(13, HIGH);
  delay(500);
 digitalWrite(13, LOW);
// now measure a high pulse on our pin, with a 2sec timeout
 duration = pulseIn(pin, HIGH, 2000000); //2000000microsec = 2 sec
// should the program stop? or should code here get run?
//
 delay(5000); //give ample time for switch press or timeout
//if no delay, worried that it runs thru the loop again
//.... and restarts the pulsein "loop"
 Serial.println(duration);
 // always returns a 0....

}

I'm missing something I think... anyone got an idea where I'm going wrong?

You can easily test pulseIn by jumpering the pin you want the measurement on to one of the PWM pins, trying different duty cycles.

does the next line of code run? I

No.

which version of the IDE are you using?

There was a bug that caused the pulsIn() code to premature timeout, see - http://arduino.cc/forum/index.php/topic,74813.0.html - it should be fixed in the 1.0.1. version.

@AWOL- thanks- the PWM thing is a good idea, and your "No" on my question about the next line of code running seems clear enough!

@Rob, funny you should ask that... I coincidentally downloaded 1.0.1 before I started this saga, but couldn't install it because it said the zip file had no content (even though it was about 60MB). I didn't worry about it, and carried on, so I'm on 1.0.0. I'll try again to download 1.0.1

Thanks guys....

EDIT....

@AWOL, just did the PWM thing and it works fine, so thanks for that. I tried different duty values in analogWrite and at 490Hz (as explained in the reference) the pulse times come out about right. No idea why the one with the switch didn't work though...

@Rob, just downloaded 101. If I have the energy on a Sunday evening to put the breadboard back together, I'll try it again. But at least I know from the PWM experiment that pulseIn does actually work.

Thanks again....

If you have a pulseIn() set to look for a HIGH, and the pin is already high when pulseIn() is called, does it time the balance of the current high, or wait until a low and start timing on the next high?

if problems remain just ask

you can see the code...

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 = timeout * clockCyclesPerMicrosecond() / 16; 
        //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); 
    // patched 
    return (width * 21 + 16)/clockCyclesPerMicrosecond(); 
}

Hi,

If your upto it, you can find the source code directory on your computer and find out, it’s what I would have to do to answer your question.

It’s probably in wiring.c

Duane B

rcarduino.blogspot.com

A photo finish!

Let's keep the questions about pulsein, started on the same day, by the same person, together huh? Less confusing.

JimboZA: If you have a pulseIn() set to look for a HIGH, and the pin is already high when pulseIn() is called, does it time the balance of the current high, or wait until a low and start timing on the next high?

It waits for a LOW and times the next HIGH. If the pin doesn't got LOW, HIGH, and LOW within the timeout period a timeout occurs.

This solved my problem:

//dauer = pulseIn(echo, HIGH); ← after increasing the distance to HC-SR04 started to report zeros only…

while ((dauer = pulseIn(echo, HIGH)) == 0) {
// wait for result… zero result bug fix!
}