Fads to Obsessions and Beyond...




Free domain for life, exceptional technical support, website transfer

HC-SR04 Ultrasonic Ranging

A HC-SR04 Ultrasonic Ranging module is interfaced with a PIC18F248 microcontroller. The HC-SR04 is tested in a variety of situations, including being used as a water level detector.

Ultrasonic ranging has a number of applications and advantages compared to alternatives such as infrared. Two specific applications of current interest include being used as a 'trip wire' for security alarm scenario and for measuring the height of water within a tank.

The output 'beam' from ultrasonic transmitters is generally restricted to a relatively narrow beam (the specification for the HC-SR04 is 15o). In comparison passive infrared sensors (by which I mean the PIR detector with a suitable lens etc) have detection angles of 90o or more. This enables an ultrasonic beam to be used analagous to a 'trip wire' in an alarm system. This would be advantageous in a situation such as a doorway or walking path, with the sensor set ~1m above and parallel to the ground, which would be 'tripped' by a person walking through the beam, but not be set off by pet dogs/cats for example.

Another situation potentially advantageous for ultrasonic ranging is determining the height of water within a tank or other container. The ultrasonic sound waves are reflected from a water surface, so this enables a non-contact method of measuring a water level. This avoids the necessity of having a probe in contact with the water and the resultant corrosion.

Ultrasonic transducers can be purchased relatively cheaply, but then require the necessary circuitry for excitation of the transmission, and a receiver with the necessary amplification and discrimination. Alternatively the HC-SR04 provides within a single breakout board a ultrasonic transmitter, receiver and control circuit, all for the cost of a few dollars (via ebay).

A number of HC-SR04 were purchased to evaluate against the publicised specifications and to test applicability for use as a water level measuring device and 'trip wire' in a potential security alarm. Some bench testing was performed to determine the performance of the HC-SR04 in terms of range, measuring angle, sensitivity and accuracy.


The schematic for the HC-SR04 ultrasonic ranging module with connections to the PIC18F248 is given in the Schematics Section below. The ancillary circuitry for the PIC18F248 also includes connection via RS232 to a PC (enables PC control of the HC-SR04).

Power Supply

A typical "wall-wart" power-supply is used (a surplus laptop charger in this case) in conjunction with a voltage regulator (LM317T) to provide the regulated 5V required by the PIC microcontroller.

The HC-SR04 ultrasonic ranging module also requires 5V which was taken from the microcontroller supply. During testing it was found that initiating a ultrasonic measurement on the HC-SR04 caused sufficient current spike to reset the microcontroller (brown-out). A 10uF decoupling capacitor adjacent to the HC-SR04 ultrasonic ranging module power pins solved this.

Firmware/Software

The HC-SR04 ultrasonic ranging module requires a pulse on the 'trigger pin' to initiate an ultrasonic ranging measurement, with the actual range data being supplied in the form of a pulse width duration on the 'echo pin'.

Initiating a measurement simply involves pulsing the trigger pin high (5V) for 10us. This will cause the HC-SR04 to transmit a series of ultrasonic pulses, after which the echo pin will be held high corresponding to the length of time that was required for the ultrasonic echo to be received. Therefore, interfacing with the HC-SR04 simply requires determining the length of the 'echo' pulse, which is readily done using a suitable timer onboard a PIC microcontroller. Once the length of the echo pulse is determined, in conjunction with the known value for the speed of sound, the distance can be calculated.

Code snippet 1 below shows the basic firmware required (coded using CSS C). Timer1 of the PIC18F248 is used as this a 16-bit timer. Once the ultrasonic measurement is inititated (pulse the trigger pin high for 10us), the code waits for the echo pin to go high and then starts the PIC Timer1. The value of Timer1 is read when the echo pin again goes low.

The HC-SR04 datasheet takes the speed of sound in air as 340m/s. Since the time measurement of the ultrasonic pulse is of the returned ECHO (i.e., the distance measured is actually to the object in question AND then back again) the value needs to be divided by two (2). The value provided by Timer1 is a number of 'counts' or 'increments' of the clock which needs to be converted to a time. This depends upon the PIC oscillator frequency and value of the Timer1 prescaler used. Therefore the equation becomes:

D =
4/Fosc
* Prescaler * Timer1 * C * 100
cm/m
*
1/1,000,000
s/us
* 1/2

where: (note the units)

  • D = distance (cm)
  • Fosc = PIC oscillator frequency (MHz)
  • C = speed of sound in air (m/s)
  • Prescaler = Timer1 prescalar value, either 1,2,4 or 8
  • Timer1 = value from Timer1 (0 to 65535)

Simplifying the above equation by combining the 'constants' on the right then gives (for C=340m/s, Fosc=10MHz, prescaler=2):

D (cm) = 0.0136 * Timer1

A issue with the code in Snippet 1 below is that WHILE statements polling the input status of the HC-SR04 echo pin can hang the code if the echo pin does not change status for some reason. This can be addressed by using interrupts (e.g. the 'interrupt on change' available on PORT B of the PIC18F248) or by incorporating additional logical check of the value of Timer1, which if exceeds a specific value, indicates no echo pulse has been received. Code Snippet 2 below incorporates this additional logic check to avoid the possibility of hanging the code if the HC-SR04 echo pin does not change state.

The HC-SR04 datasheet, at least the one I managed to find, does not actually specify what happens if no ultrasonic echo is received by the HC-SR04. The only specification is a minimum distance of 2cm and a maximum distance of 4m (400cm). Assuming a speed of sound of 340m/s this distance range equates to a minimum 'echo' of approximately 117us and a maximum of approximately 23.5ms (remembering a distance of 2cm means a 'round trip' from the HC-SR04 transmitter to the receiver, i.e. 4cm).

One reference (1) indicates that the HC-SR04 has a 38ms response that indicates 'infinity' (i.e. no echo return). However, I found the HC-SR04 modules I used 'timed out' after 200ms (I blocked the ultrasonic receiver and used Timer1 on the PIC to measure the HC-SR04 maximum 'echo' pulse width). In actual operation (see the Testing/Experimental Results Section) the 200ms 'no echo return' is not actually observed, but due to spurious multiple reflections and other interferences, 'random' pulse widths are returned if no suitable target is in range of the HC-SR04.

Code Snippet 2 incorporates including checking the current value of Timer1 when polling the status of the HC-SR04 echo pin. This then allows setting the maximum distance (i.e. time) that the HC-SR04 is expected to reliably detect in the particular situation in which it is installed. Consequently, this also prevents the code from 'hanging' if the HC-SR04 echo pin does not change state.

Since the example code avoids using interrupts, the polling of the state of the HC-SR04 echo pin to mark the start of the echo pulse width could also result in the code 'hanging' if the HC-SR04 fails at this stage for some reason. Another reference (2) indicated that instead of measuring the width of the echo pulse, the time from triggering the HC-SR04 to the start of the echo pulse could be used instead. This with the incorporation of a suitable 'time out' check would then avoid the possibility of the code hanging while polling the HC-SR04 echo pin, and also be quicker (as the code would not need to wait for the echo pulse to finish).

However, I found that the time from initiating a reading on the HC-SR04 (10us pulse on the trigger pin) to the start of the echo pulse was fixed at 450us. I don't think this is a pecularity of the units I used for testing. Reference (2) refers to the datasheet which states two formula's indicating the alternate methods of operation. However, the two formula's are actually equivalent (the "uS/58 = centimeters" is just a re-arrangement and simplification assuming the speed of sound is 340m/s) and the confusion is just the poorly phrased English (and or poor translation) in the datasheet.

Therefore, the code in Snippet 2 below incorporates a further check of Timer1 when polling the state of the HC-SR04 echo pin waiting for the start of the echo pulse.

The values used in the code Snippet 2 for checking Timer1 while polling the HC-SR04 echo pin state will depend upon the PIC oscillator frequency and Timer1 prescaler value. This also shows why a 16-bit timer is required. An oscillator frequency of 10MHz with prescaler 1 equates to 0.4us/timer increment, therefore for a 8-bit timer gives a maximum of 256*0.4us = 102.4us, which at a speed of sound of 340m/s equates to ~1.74cm (below the minimum range of the HC-SR04). Although a 8-bit timer perhaps could be used if a prescaler of suitable value is available (e.g the PIC18F248 Timer0, which can be used as 8 or 16 bit, allows a prescaler value up to 256).

Speed of Sound

The HC-SR04 datasheet assumes a speed of sound in air of 340m/s. The speed of sound in air actually depends upon air temperature, a 'little' with humidity but not with atmospheric pressure (3).

The approximate speed of sound in dry (0% humidity) air, in meters per second, at temperatures near 0oC, can be calculated by (4):

Cair = 331.3 + (0.606 * T) m/s

where:

  • Cair = speed of sound in air
  • T = air temperature degrees Celsius

This formula shows the 340m/s is approximately the speed of sound in air at a temperature of ~15oC. A value of 346m/s at 25o is better for use at my locality. Correcting for air temperature (via the use of a suitable sensor for example) is probably not warranted, as even at a distance of 1m the error introduced is in the order of a few millimeters. If such accuracy and or precision is required, the HC-SR04 is likely not suitable in any case.

PIC Microcontroller Interface Code

The following code example shows the simple interface required to control the HC-SR04 ultrasonic ranging module. The code enables control of the HC-SR04 ultrasonic ranging module via a connected PC (RS232 connection).

Code Snippet 1:


#include 

#define HCSR04_echo  PIN_C1
#define HCSR04_trig  PIN_C0

unsigned int16 timerCount; //raw count from Timer1
float distance;            //calculated distance in cm

void main() {
   char recChar;  //received character from serial port

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2); //start timer1, 10Mhz Fosc = 0.8us/timer inc. 
   output_low(HCSR04_trig); //initialise trigger pin
   
   do {
      if (kbhit()) {
        printf("start\r\n");
        //trigger measurement
        output_high(HCSR04_trig);
        delay_us(10);
        output_low(HCSR04_trig);
        while (input(HCSR04_echo)==0); //wait for return echo pulse to start
        set_timer1(0); 				   //reset timer1 register to 0
        while (input(HCSR04_echo)==1); //wait for return echo pulse to finish
        timerCount = get_timer1();
        // range (m) = pulse high time (sec) * speed sound (m/s)/2
        distance = timerCount * 0.0136f; // 0.0136 = 0.8/1000000*(340*100/2)
        printf("raw count = %Lu, distance= %3.1g cm\r\n",timerCount,distance);
        delay_ms(100);
      }
   } while (TRUE);   
}
			

Code Snippet 2:


#include 

#define HCSR04_echo  PIN_C1
#define HCSR04_trig  PIN_C0

unsigned int16 timerCount; //raw count from Timer1
float distance;            //calculated distance in cm

void main() {
   char recChar;  //received character from serial port

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2); //start timer1, 10Mhz Fosc = 0.8us/timer inc. 
   output_low(HCSR04_trig); //initialise trigger pin

   do {
      if (kbhit()) {
        printf("start\r\n");  
        output_high(HCSR04_trig);
        delay_us(10);
        output_low(HCSR04_trig);
        set_timer1(0); //reset timer1 register to 0
        while (input(HCSR04_echo)==0 && (get_timer1() < 565)); //wait for return echo pulse to start, 450uS/0.8uS per timer inc = 563 
        if (input(HCSR04_echo)==0) {
           printf("error: echo pulse not detected\n\r");
        } else {
           set_timer1(0); //reset timer1 register to 0
           // range (m) = pulse high time (sec) * speed sound (m/s)/2  speed sound 345m/s @ 22.5 celsius
           while (input(HCSR04_echo)==1 && ((timerCount[readingCounter] = get_timer1()) < 1450)); //wait for return echo pulse to finish
           timerCount[readingCounter] = get_timer1();                                              
           if (timerCount[readingCounter]<1450) {                                     //1450 * 0.8/1000000*17250 = 20cm
              distance[readingCounter] = (float)timerCount[readingCounter] * 0.0138f; // 0.0138 = 0.8/1000000*17250
              printf("raw count = %Lu, distance= %3.1g\r\n",timerCount[readingCounter],distance[readingCounter]); 
           } else {
              //out of range
              printf("Out of range - greater 20cm\r\n");                          
           }                                                  
        }   
        delay_ms(100);
      }
   } while (TRUE);   
}               
			


Note: Image loading can be slow depending on server load.

  • HC-SR04 Basic SchematicHC-SR04 Basic Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    HC-SR04 Basic Schematic

This project did not require a PCB.

The construction was done using prototyping board. See the photographs and schematic diagram sections.

Qty Schematic Part-Reference Value Notes/Datasheet
Resistors
3R110K1/4W, 10% 
Diodes
1D11N4002
Integrated Circuits
1U1PIC18F248PIC microcontroller datasheet
1U27805Linear Voltage Regulator  datasheet
1U4MAX232ERS232 Driver/Receiver datasheet
Capacitors
2C1,C222pFceramic disk
1C30.33uFaluminium or tantalum electrolytic
1C40.1uFaluminium or tantalum electrolytic
5C5-C91uFaluminium or tantalum electrolytic
2C1010uFaluminium or tantalum electrolytic
Miscellaneous
1J1CONN-H55-pin connector for ICSP
1P1CONN9-pin connector for RS232
1SW1SW-SPDT 
1X110MHzCrystal Oscillator
1Z1HC-SR04Ultrasonic Ranging Module datasheet
Description Downloads
A4988 - Bill of Materials Text File Download

Connection of the HC-SR04 is straightforward with pins for power supply (5V and Gnd), a 'trigger' pin to inititate a measurement and a 'echo' pin to retrieve the measured distance (see the Schematics and Photographs Sections for more detail).

Initial testing simply involved measuring the distance of a target (a cardboard sheet) from the HC-SR04 on the test bench (see Photographs Section) as measured with a tape measure. It was found that the HC-SR04 did indeed give distance measurements accurate to within a few millimeters (within the limit of my tape measure) and similarily, precision (reproducibility) of a couple millimeters, up to at least 1.2 meters. The distance from the end of the transducer cones was used as the 'start' (rather than from the PCB board etc).

The ~1.2m distance tested on the bench is a factor of the measurement angle, or 'beam width' of the ultrasonic transducers on the HC-SR04 (the datasheet states 15o). At the height the HC-SR04 was mounted on the breadboard (~5cm) with a ultrasonic beam width of 15o the bench itself would start to reflect the ultrasonic pulse at a linear distance of ~1.2 meters.

Graph 1 shows the results of moving the cardboard target at various distances 'perpendicular' to the distance from the centreline of hte HC-SR04. When the resultant distance measurement from the HC-SR04 was greater than 2% of the centreline value (i.e. the reading was from the bench surface instead of the target) this was taken as the maximum width of the useful range of the ultrasonic pulse. This shows that indeed the measurement angle of the HC-SR04 is approximately 10-15o. This needs to be taken into account when mounting the sensor.

  • Graph 1: HC-SR04 ultrasonic beam width testing

    HC-SR04 ultrasonic beam width testingHC-SR04 ultrasonic beam width testing

    Silver Membership registration gives access to full resolution schematic diagrams.

    HC-SR04 ultrasonic beam width testing

Graph 2 shows the results of testing the maximum linear distance the HC-SR04 can accurately measure. The sensor was mounted ~90cm from the floor with a target mounted on a tripod at distances set by a measuring tape (see Photographs Section). Two sizes of target (small ~10x10cm, and large ~50x50cm) were used made from cardboard.

At distances to approximately 1.4 meters, the HC-SR04 recorded reproducible, accurate distance measurements. Distances to the maximum available within the office setting (3 meters) could be read by the HC-SR04, although reproducibility was poor. Reproducibility (i.e. the 'correct' reading) improved with the larger surface area target. This shows the ultrasonic distance measurement can be restricted due to the physical setting in which the measurement is being conducted.

  • Graph 2: HC-SR04 distance measurement testing

    HC-SR04 distance measurement testingHC-SR04 distance measurement testing

    Silver Membership registration gives access to full resolution schematic diagrams.

    HC-SR04 distance measurement testing

The longer the distance (and smaller the desired target) the more likely multiple reflections of the ultrasonic pulse from various surfaces in the vicinity will confound the reading. Further, as stated in the datasheet, hard flat surfaces perpendicular to the ultrasonic beam path will be easier to detect (i.e. at longer distances) compared to absorptive surfaces or those reflecting at differing angles.

Measuring Water Level

The HC-SR04 enabled measurement of water level with a reservior/tank (see Photographs Section). The actual sensor needs to be mounted sufficiently far away from the reservior/tank wall, so that the ultrasonic beam reflects from the water surface, rather the container wall.

When the water level was only a couple of centimeters deep, it was found to be difficult to get reproducible readings. Possibly this was due to a significant portion of the ultrasonic beam being reflected from both the water surface and the bottom of the container, when the container was nearly empty, confounding the sensor.

However, at water depths of greater than two centimeters,the HC-SR04 appears to be entirely suitable for water level measurement (with the obvious advantage of not needing to be mounted within the water, eliminating corrosion and fouling problems).


Downloads

Description Downloads
HC-SR04 header file: CCS C Source Code Download
Example PIC code with PIC18F248/PC serial interface: CCS C Source Code Download

The use of the HC-SR04 ultrasonic ranging module board is relatively straight forward. The HC-SR04 requires 5V which can be taken from the supply used to power the microprocessor. Obviously, check polarity of power supply before connecting to the HC-SR04.

As mentioned in the Circuit Details Section, during testing it was found that initiating a ultrasonic measurement on the HC-SR04 caused sufficient current spike to reset the microcontroller (brown-out). A 10uF decoupling capacitor adjacent to the HC-SR04 ultrasonic ranging module power pins solved this.

The only other potential 'gotcha' is to ensure that the HC-SR04 is mounted so that reflections of nearby surfaces are not confused with the desired target (beam width of the HC-SR04 is ~15o.

Similarily, as pointed out in the datasheet, the ability to get reproducible readings, particularly at distant ranges, will depend upon what the target is made from (hard surfaces reflect better than soft surfaces), the angle of the target in relation to the ultrasonic transducers, and likelihood of multiple reflections from confounding surfaces etc.

Comments/Questions

No comments yet.

Add Comment/Question

Only Logged-In Members can add comments

"If we could sell our experiences for what they cost us, we'd all be millionaires".

Please donate any amount to help with hosting this web site.

If you subscribe (only $2/annum) you can view the site without advertisements and get emails abouts updates etc.

X

Sorry!

Only logged-in users with correct Membership Level can download.


Membership starts at only $2, so join now!