External Links

Creative Science Centre



Measuring Distance

Updated September 2016

This is a popular low cost device for measuring distance. The PCB says it is a HC-SR04. Its good from about 100mm to arms length and more and is quite sensitive so ideal for obstacle avoidance.


They only have two control pins. A pulse is applied to one pin and then a measurement is taken from the other pin.

A small pulse is sent to the device and some time later the echo pin (marked as input on the timing diagram) will go high (A), when the pulse is received back from a reflecting object the pin goes low. The distance is the width of the positive pulse (B) which is about 0.5 to 2ms.

The data sheet has the trigger as a positive pulse but the above timing diagram was an actual oscilloscope output, so it is possible that different devices may have different pulse polarities. On this particular device, until the first pulse was sent, the echo pin was high.

The device operates at 5V and so for the input we use a 5V tolerant pin (B6 in this case)


Pin RB13 -- Trig pin on HR04
Pin RB6  -- Echo pin on HR04

The PIC32 has input capture hardware that is ideal for this purpose, before going into it the output from the software looks like this:

The values are in mm approximately.

There are 2 functions

  • init() to initialise the hardware
  • dist_test() This returns two values, the first value is not the echo but the reception of the pulse direct and the second value is the echo
  • dist() Here the first value is thrown away and a constant is applied to make the value into mm.



Input Capture

The PIC32 input capture is used for 1) detecting the edge of the echo and then 2) timing the return edge. For this application we are detecting two edges, the first rising edge and any edge after that, which will of course be the falling edge at (B). This is all set with the library function icap_init().

The input capture has 4 buffers (first in first out) for each input capture pin. So when an event occurs the timer value is loaded into the buffer, if another event occurs then that is loaded into the next buffer an so on. Reading the buffer removes the value form the buffer.

How it works

1) The initialisation starts timer 2 and sets up input capture to capture the first rising edge and then any edge after that.

2) A pulse is sent to the trigger pin and the timer is reset to 0

3) The distance is measured.

This requires a bit more explanation. The dist_test() function sends a pulse and then waits 15mS. The icap_in?() indicates if there is any data in the buffer:

This is the reason for the while statement, if so the contents of the buffer are printed out.

The go() function will print out a constant stream on distances, approximately in mm using the constant just above the dist() function.