pulseIn() function for HC-SR04 sensor

I am using code similar to what’s shown above to measure the distance away that objects are as they pass by my sensor (HC-SR04 ultrasonic sensor). The code, sensor, and measurements are great so long as there is an object there to measure. If there is open space in front of the sensor it begins to throw random numbers of distance.

I believe the datasheet for this sensor claims to be good to approx. 16 ft. If I wanted to stop the pulseIn function after the distance surpassed say 14 ft, to be safe. How might I do that and return an out of range error or something similar, instead of random numbers that are misleading to my project?

I will say I am only two weeks into learning about the Particle Photon and have no other experience with Arduino’s or any of the likes.

Thanks for any guidance.

I wrote a custom pulseIn function some time ago that includes a timeout value. I haven’t tested this for a while, but I think this should work for you.

unsigned long rdPulseIn(int pin, int value, int timeout) { // the following comments assume that we're passing HIGH as value. timeout is in milliseconds
    
    unsigned long now = micros();
    while(pinReadFast(pin) == value) { // wait if pin is already HIGH when the function is called, but timeout if it never goes LOW
        if (micros() - now > (timeout*1000)) {
            return 0;
        }
    }
    
    now = micros(); // could delete this line if you want only one timeout period from the start until the actual pulse width timing starts
    while (pinReadFast(pin) != value) { // pin is LOW, wait for it to go HIGH befor we start timing, but timeout if it never goes HIGH within the timeout period
        if (micros() - now > (timeout*1000)) { 
            return 0;
        }
    }
    
    now = micros();
    while (pinReadFast(pin) == value) { // start timing the HIGH pulse width, but time out if over timeout milliseconds
        if (micros() - now > (timeout*1000)) {
            return 0;
        }
    }
    return micros() - now;
}

It would be called like so,

 distance = rdPulseIn(echoPin, HIGH, 37)/5.82; // distance in mm
1 Like

If you have an object that continuosly approaches or recedes that may be working.
But when you say random values and you still want to catch readings of objects that suddenly appear in range, you might need to take multiple readings over a “longer” periode and take the deviation between them as a measure of reliability.

2 Likes

This seems to be working! Thanks Ric. I simply wanted the sensor to trip with anything crossing the ‘beam’ <=14. Know, with the timeout, values that surpass that I just return a number greater than 14 and the rest of my code works.

Thanks for the reply ScruffR. You’re right, good point. I really don’t need much accuracy. My problem was that the sensor might measure, say 5 inches, even when nothing was in range. Anything after approximately 14 ft didn’t matter in my case. So using the timeout given by Ric I just return 999ft after reaching the timeout at 14ft. This way any value within 14 ft which I do need still trips the sensor to say some object has passed by and even then the exact number doesn’t matter so long as it was less than 14 ft.

But when you say you get random values as low as 5", doesn’t that still trip your sensor?

The reason for these extra readings are probably echoes of previous pulses arriving late due to the long travel.
Hence pulsing less often might also help getting rid of these stray echoes.