HCSR04 Timing Issues

Hi, I am using an HCSR04 Ultrasonic Sensor to get range values in conjuction with several other sensors for a personal project. At first I used an established library for the measurements but then I decided to write my own code. While doing this I realized that I need to use pulseIn to get the time of the pulse and that generated a problem: pulseIn stops all other code until the pulse ends. This is a problem if the sensor ends up pointed at nothing close as it yields sampling times of about 25 milliseconds and I need to run other sensors at frequencies smaller than that. Based on this I am wondering if there is any way to cut pulsein (there is no parameter for this in the function) off at a certain pulse length so that it stops holding everything up. Thanks!

Look at the function documentation. There is an optional maximum timeout parameter.

That parameter counts time before the pulse is recieved. I am looking to cut it off at a certain time during the pulse.

Or you could save the time in microseconds when you send the trigger pulse and connect the echo pin so you can get an interrupt when the echo is heard and set a flag in the interrupt code indicating you got an interrupt. Then in loop() if the flag is set, get a new microsecond value and subtract the first micro from it, and subtract the other time delays and there is your round trip time for the ultrasonic pulse. calibration will be necessary.
No blocking of your code.

You might want to look into using the capture timer function. You didn't specify which Arduino you are using. I think it is timer1 on the Pro Mini.

You will need to capture the sensor output rising edge (copy the timer reading) then set it up to capture the falling edge.

I'm using a Teensy 4.0

Not familiar with the Teensys, sorry I can't be of more help.

So I solved this problem by replacing pulseIn() with a boolean (triggered) and a while loop containing three conditions:
One if the specified timelimit had passed, in which the loop was broken. A second if the pulse went high and had not gone high before (triggered == false), in which triggered was set to true and micros() was recorded as the start time. A third if the pulse went low and had gone high before (triggered == true), in which micros() was recorded as the end time and the loop was broken.

Okay, but that sounds functionally identical to pulseIn() with a short timeout period. A real non-blocking solution is in reply #5.

It is not the pulse length that is measured - it's the delay until the leading edge of the pulse is received. The pulse length is determined by the transmitter.

The Teensy 4.0 seems fast enough to use an interrupt.

start the pulse
Read millis (immediately)

wait for interrupt
Read millis.

Except - use micros() for better accuracy. This is just the same as reply #4

I forgot about post #4 :frowning: So much time goes by and I don't reread the thread when it pops up again.

Sure, actually there are probably several ways to do this, which one just depends on the needs of the rest of your code. Some are more complicated than others. But it is too fast to use polling in loop(), so the usual millis() with cooperative multitasking isn't good enough.