How To Detect Objects with HC-SR04 Ultrasonic Sensor, Arduino and millis()

Obstacle detection is applicable to any robot that moves from an initial position to a goal position avoiding any obstacle in its path. The process of detecting obstacles is applied for a variety of robots, including a mobile robot and a robot arm. In this tutorial, you will learn how to use the HC-SR04 sensor with an Arduino board and determine the detection range of the sensor in certain conditions.

Different projects may have different requirements. At the end of this tutorial, you will have a flexible structure that can be used in different robots and make it possible to add more sensors, or use only one sensor, or use another type of sensor (for example, infrared sensor).

If you plan to build advanced robots in a productive and professional manner, this is the point where you can start.

Before starting to connect the sensor and write the first line of code, let’s be sure that we have all the hardware parts. Here is the list of hardware that I use to write the tutorial:

  • 1 X Arduino UNO
  • 1 X USB cable
  • 1 X HC-SR04
  • 1 X Breadboard
  • female-to-female/male-to-male/female-to-male jumper wires

1. Read the HC-SR04 output with Arduino

In this part of the article, I will show you how to connect one HC-SR04 sensor to Arduino and write the Arduino sketch that reads and transforms the sensor’s output.

For the moment, I use a USB cable to power the Arduino UNO. The 5V USB port of a personal computer or laptop provides enough power to run a 5V Arduino and the three ultrasonic sensors.

The above set up is just for connecting and testing the ultrasonic sound detection system. When the sensor and the Arduino board will be mounted on a mobile robot, the entire detection system will run on batteries.

1.1 Connect the sensor to the Arduino

First, let’s have a look on the HC-SR04 specifications:

  • Operating Voltage: DC 5V
  • Operating Current: 15mA
  • Operating Frequency: 40KHz
  • Range: from 2cm to 4m
  • Ranging Accuracy: 3mm
  • Trigger Input Signal: 10µS TTL pulse

The operating voltage of the sensor is the same as the Arduino 5V output pin – DC 5V. The operating current for an ultrasonic sensor is 15mA, which can be supported by Arduino even if it is connected to a USB port of a computer. The 5V output pin of Arduino UNO is suitable for ~400 mA on USB, ~900 mA when using an external power adapter. At this step, we will take into consideration only these two specifications and start to connect the sensor to the board.

For connections, I use female-to-male jumper wires, a breadboard, one HC-SR04, and an Arduino UNO board.


  • Vcc -> breadboard -> 5V
  • Trig -> pin 3 (digital pin)
  • Echo -> pin 2 (digital pin)
  • GND -> breadboard -> GND

1.2 Write the code sample for the sensor

Once the sensor is connected to the Arduino board, we can start writing the sketch to read the output and transform the reading from the sensor. For writing the sketch, I use the Arduino IDE. I like to work with simple tools and don’t spend time on customizations and accessories. For the moment, the Arduino IDE satisfies my needs in terms of programming a microcontroller.

Before writing the first line of code, let’s recapitulate how an ultrasonic sensor works.

It pings a sound wave (for at least 10us according to specifications), which travels through the air, and if there is an object that reflects the sound wave, the sensor measures the time that ping took to return to the receiver. To calculate the distance between sensor and object detected, we consider the travel time and the speed of the sound.

Info: The sound moves through the air at different speeds depending on the temperature. Since we are using the speed of sound to measure the time that ping took to return to the receiver, the environmental temperature can affect the accuracy of an ultrasonic sensor. Temperature compensation is not part of this tutorial, but you can add it later in your code.

Let’s begin building our ultrasonic sensor measurement sketch:

Distance measured sketch result

Once the sensor is connected to Arduino and the output is transformed in centimeters, we can go on and do the tests to determine the range of the sensor.

2. Operating detection range of the HC-SR04

We aim to detect all objects in a particular area in front of the sensor regardless of the shape or size of the object. Because in the end, we plan to use this sensor for object detection, firstly we have to determine the operational detection range of one sensor. Next, we have to calculate how to position each sensor unit for maximum efficiency in the detection of the objects.

The size, shape, and orientation of the object target affect the maximum distance at which it can be detected. For example, round shape objects or sound-absorbing materials such as fabrics reflect less energy or nothing directly back to the sensor. The ultrasonic sensor is not affected by optical characteristics such as color, reflectivity, transparency, or opaqueness. Also, objects may be introduced into the detection zone from any direction.

Note: I did my tests in a noisy environment, and I use a ruler and a paper agenda, which is an object that can be easily detectable. I didn’t do tests on an object with round shapes which deflected in all directions the majority of the echo. Please don’t forget that this is just a test, and may have results that are not very accurate.

The first step in determining the range of an HC-SR04 ultrasonic sensor is to decide the range that you need for your robot. Let me explain what it means!

For example, I have a 2WD mobile chassis, and I want to use it to detect and avoid obstacles. I know from the specification that the HC-SR04 sensor’s range is between 2 and 400 centimeters.

I did a test with one sensor, and the result was that under 5 centimeters, the sensor performed no reliable measurements. 5cm is a minimum detection range starting from the sensor head. The zone area between 0cm and 5cm should be considered as a blind zone.

The next step was to determine the operating detection range that we need for our application. This is the range in which the sensor can do a detection or measurement during all times with high accuracy. If we search in the specifications, we can see a maximum detection range of 400 centimeters. This range couldn’t be taken into consideration in this case. These values are most probably taken when all conditions are very good to optimal. In a real-life application, we are using the sensor in a noisy environment with different temperatures and humidity.

Info: If the sensor is very close to an object, less than 3 centimeters, you will notice some strange values for distance returned by the sensor. This behavior is the situation when the sensor will not detect the first echo but may detect a second or third echo which is translated as a longer distance than the actual value.

The HC-SR04 is not a highly precise sensor but is good enough to use it for learning how to build robots. For this reason, I took into consideration an operating detection range of 100 centimeters – 1 meter in front of the sensor. This range is enough to learn how to build an autonomous mobile robot with DIY components and test it in a living room area.

HC-SR04 operating detection range

The ultrasonic beam angle for HC-SR04 is typically 10-15 degrees and conically shaped. I add in the above picture the optimal values when the sensor accuracy is high in the range of 5 to 100cm.

For the moment, we detect the objects and know the operating detection range. In the next part of the tutorial, I will show you how to write classes and build a flexible structure that can be used in different robots and make it possible to add more sensors.

3. Build classes in tabs

Each class will have a tab in the Arduino IDE. Using tabs allows us to keep things better organized. The classes will be written in files with extension .h.

Step 1: To create a new tab in Arduino IDE, go to the top right and press on button 1. Then select from menu 2 “New Tab“:

Create a new Tab to write a class

Step 2: In the lower part of the IDE should appear a new field. In this field, we write the name of the new file. For the first tab, type “Range.h” – the file where we will store the class for range detection sensors – and then press the OK button.


Step 3: At this point, you should see in your Arduino IDE a tab like this:

Tab Range.h

Follow steps 1 and 2 to create a new tab for class Timer. The tab name is Timer.h.

Tab Timer.h

From now on in this article, we will work on these three tabs.
The first tab with main and loop -“Ultrasonic_Sensors_to_Detect_Obstacles”. In the Range.h tab is written the class for ultrasonic sensor, and in Timer.h is the timer class.

Let’s us see the code in each of the three tabs:

3.1 Ultrasonic_Sensors_to_Detect_Obstacles


On Lines 11-12 we import our required classes.

Lines 15-16: We are using object-oriented programming, and we have to instantiate the Range and Timer classes to create an object and an instance of the class.

Line 19: we are in the setup function and the first thing we do is to open the serial port and set data rate to 9600 bps.

Lines 23 and 27: We check the time and publish every 50 milliseconds.

3.2 Range.h

Tab Range.h

Lines 1-2 and 68: prevent multiple includes of the header. It checks if a unique value of Range.h is defined. Then if it’s not defined, it defines Range.h and continues with the rest of the page.

Line 4: we import our Timer class.

Line 6: tm object is created from the class Timer.

Lines 9-14: Enumerate the states of the sensor. We start to deactivate the trigger pin, then activate the trigger, and in the end, we activate the echo pin to return the time duration of the impulse.

Lines 22-27: The constructor of the class Range. In constructor are defined the pins and the mode of the pins.

Lines 29-54: I use the switch statement to select one-by-one the states of the sensor. In the first case TRIG_LOW, ensure the trigger pin is low, then count two milliseconds until we switch to TRIG_HIGH – the second state of the sensor.

In the case of TRIG_HIGH, ensure that the trigger pin is high and count ten milliseconds until switching to the next state ECHO_HIGH.

In the case of ECHO_HIGH, ensure trigger pin is low, read the time duration of the pulse, set the next state as TRIG_LOW, and transform in centimeters the readings from the sensor.

Lines 57-65: In the private section of the class are added two functions. One function is to change the trigger state to low, and a second function to change the trigger state to high.

3.3 Timer.h

Tab Timer.h

Lines 1,2 and 21: prevent multiple includes of the header. It checks if a unique value of Timer.h is defined. Then if it’s not defined, it defines Timer.h and continues with the rest of the page.

Lines 4-5: In the private section of the class, define the time to start variable.

Lines 8-10: the function to start counting the time using millis(). I prefer to use millis() instead of delay() from two reasons: millis() is more accurate than delay(), and is a non-blocking alternative of delay().

Lines 12-18: Two functions that do the same thing, check if the time passed and return true. Depending on the situation, we call one of the two functions.

Compile and upload the sketch to Arduino.

After going through this tutorial, you learn how to use millis(), how to build classes, determine the detection range, and print the output of an ultrasonic sensor.


Related Posts

Don't Miss Out!

Get the latest news, tutorials, reviews and more direct to your inbox when you subscribe!