Need help with Ultrasonic Sensor SRF05 - using Arduino function PulseIn()

Hello, guys. I’ve studied the Ultrasonic Sensor SRF05 recently. It works fine for now, but i need some explainations about how it actually works.

Here is the code for this Sensor :

int echoPin = 2;
int trigPin = 3;

void setup(){    
     pinMode(trigPin, OUTPUT);
     pinMode(echoPin, INPUT);
     Serial.begin(9600);
}

void loop(){
     digitalWrite(trigPin, LOW);
     delayMicroseconds(2);
     digitalWrite(trigPin, HIGH);
     delayMicroseconds(10);
     digitalWrite(trigPin, LOW);
     
     int time = pulseIn(echoPin, HIGH);
     int distance = time / 58;
     Serial.print("Distance (cm) : ");
     Serial.println(distance);
     delay(100);
}

I still confused about the pulseIn() function. For now i have two ways of thinking about how it works :

  • The pulseIn() function only wait for the “echoPin” goes HIGH, then start counting and end when “echoPin” goes LOW, return the time ( microseconds). The UltrasonicSensor Module automatically set the “echoPin” to HIGH right after the “trigPin” went LOW.
  • The pulseIn() function do all the works : set the “echoPin” to HIGH, start counting and ended when “echoPin” goes LOW, return the time ( microseconds).

Which way is the corrected one ? Or maybe all of those is wrong. Hope to see any help asap here, i’m very thankful.

from the 1.0.4 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 = 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); 
}

Tks you guy for the quick reply. And I need to say sorry first cause i'm a bad coder there lol. Already read the function definition but still don't truly understand it. Could you mind explain it for the dumb me , plz ?

Besides, i need to ask why the function return : (width * 21 + 16) , why number 21 here :frowning:

// 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);

this is the measurement loop, it counts the number of iterations of the loop in the variable width.

The formula - width * 21 + 16 - is called a heuristic,
it is derived from the fact that one loop uses 21 clock cycles - although the comment says 20 -
The 16 is a correction factor to measure start/stop. The shortest pulse to be measured is 1 usec.

hope this helps.

So at

Hi All,
Why make it so complicated!! I always find this works:

long scanner(long cm)
{
	const int pingPin=7, EchoPin=8;
	long duration;

	// The SRF005/HCS04 is triggered by a HIGH pulse of 2 or more microseconds.
	// Give a short LOW pulse before to ensure a clean HIGH pulse:
	pinMode(pingPin, OUTPUT);
	pinMode(EchoPin, INPUT);  

	digitalWrite(pingPin, LOW);
	delayMicroseconds(2);
	digitalWrite(pingPin, HIGH);
	delayMicroseconds(2);
	digitalWrite(pingPin, LOW); 
	duration = pulseIn(EchoPin, HIGH);
	delay(100);

	// convert the time into a distance
	// inches = microsecondsToInches(duration);
	cm = microsecondsToCentimeters(duration);
	return (cm); //Return with distance in CMs
}
}
//------------------------------------------------------------------
long microsecondsToCentimeters(long microseconds)
{
	// The speed of sound is 340 m/s or 29 microseconds per centimeter.
	// The ping travels out and back, so to find the distance of the
	// object we take half of the distance travelled.
	return microseconds / 29 / 2;
}
//------------------------------------------------------------------

Hope it helps.
Regards

Mel.

Here's probably the most simple explanation of how it works. You probably already know this but heck maybe somebody reading this doesn't and benefits from it.:

By sending a digital HIGH to the trigger pin, you command the sensor to send out an 10ms long ultrasonic sound wave.

Then your program listens to the echo pin. The pin will read an input when the sensor 'hears' the echo of the sound wave you sent out.

pulseIn() is fantastic.
It first waits to make sure the previous echo has dissipated, before it begins.
It will wait for the current echo to be detected.
Once the current echo is detected, it will measure its duration/length.
If the echo exceeds the maximum length (like if there is another source confusing your sensor) it will break the loop, so that your program does not freeze.

It doesnt use digitalRead because it requires a high level of precision, hence all the stuff about 'caching the port'
It counts the duration by literally counting the amount of times a loop was run, and calculate the time based on how many clock cycles it would have taken. All of this complication is just for higher accuracy.

Hope that helps,
Stef

I got what i need here. Thanks all guys, you're the best !