in arduino, tutorial

How to build a distance sensor with Arduino

Share Button

You can safely say that when it comes to electronics, there are countless ways to measure distances. This tutorial will explain how to build an inexpensive IR distance sensor under $8, perfect for close measurements  and motion detectors.

You will need:

You can download the final Arduino code here.

altctrlThis post is part of a longer series of tutorial about alternative games controllers.

If you are going to create an alternative game controller yourself, you should definitely look into ALT.CTRL.GDC. It’s one of the most fresh and intriguing exhibitions at GDC, and is all dedicated to innovative ways to interact with games.

Step 0: The theory

dodefaceAt the heart of this sensor there are two IR LEDs. One emits light, the other receives it. When an object is close to the sensor, it will inevitably reflect some of the IR light. This is detected by the Arduino, and translated into a distance measurement. The Human eye does not pick up infrared light; this sensor will look invisible, even though it can be extremely bright in the IR spectrum. There are many things that can go wrong with this approach; IR light can be erroneously picked up from another source, or the objects is not reflective enough. This picture shows a face of the DodecaLEDron, an alternative game controller which is based on the same principle.

Step 1: The circuit

This circuit has three LEDs. The bottom ones are IR emitters; the top one is an IR photodiode receiver. It is important to use photodiodes, and not phototransistors. Both types are IR receiver which change their resistance according to how much light they sense. However, while the latter works like a digital switch: it either sense IR or it doesn’t. For this project we need a photodiode because we actually need to measure the quantity of light received.

ir distance_bb

To measure the amount of light sensed from the IR receiver, we measure the drop of voltage on its resistor. When the photodiode receives light, it allows current to flow from the 5V to the GND pin; little to no current then flows back to A0. On the other hand, when the diode is in darkness and doesn’t let current flow, A0 reads a high voltage. For this project you have to use an analog input (A0-A5).

For this circuit to work properly, you have to find the right resistors to use. I’ve used LED calculator for this. You need to know the forward current (V) and forward voltage (If) of your LEDs, which are always indicated in their datasheets.

Step 2: The calibration

The moist naive way you can read data from the circuit is the following:

Most of the tutorials I’ve found which explains how to do IR distance sensors stop here. As a software engineer, I believe we can do much, much more on the software side. First of all, the distance readings of this sensor are likely to be affected by the IR background noise in your room. Almost every artificial light source is visible in the IR spectrum, causing interferences with our sensor. A more sophisticated approach to solve this problem is to calibrate the light background in your environment. To do this, we can sample the input from the sensor when (1) no object is nearby and (2) an object is very close. This provides a baseline calibration which depends on the light in the room.

This new setup function is divided in two seconds, to calibrate the sensor for far and nearby objects, respectively. The variable duration determines how long each calibration phase lasts. This is important because single readings are prone to error, but averaging them over a longer time interval provides more reliable data. The result of the calibration is stored in calibrationZero and calibrationOne, which will be used later to correct our readings.

Step 3: The reading

Reading from the sensor works in a similar fashion. We repeat a certain numbers of readings over a long time interval, and average them out to make sure about their reliability.

Lines 8-13 use the function map to rescale the readings between 0 and 255. These two values corresponds to the amount of IR light received during the two calibration steps.

Finally, to use this code:

It’s worth noticing that your code can be quite jumpy and unreliable. An interesting approach to remove noise from your readings is by adopting a Kalman filter, which has been discussed in details in a previous post.


This post explored how to use IR light to sense short distances. I have used this technique to create an omni-direction controller called DodecaLEDron. It features 11 distance sensors, all fitting in a £10 budget. Since I required so many analog inputs, I had to use an Arduino Mega rather than an Arduino One.

Further projects…

There are many other techniques which are more reliable and fully Arduino-compatible.  If you only to detect motion, you can use a PIR sensor. For more advanced projects, my favourite component is the ultrasonic module which is, de-facto, a small sonar. By using the Doppler effect you can also calculate the speed of the object it detects. For large scale applications, such as localisation within a building, you should use Bluetooth iBeacons; I’ll explain how to use them in a future post.

Don't miss the next tutorial!

There's a new post every Wednesday: leave your email to be notified!

Ways to Support

In the past months I've been dedicating more and more of my time to the creation of quality tutorials, mainly about game development and machine learning. If you think these posts have either helped or inspired you, please consider supporting this blog.

PatreonBecome a Patron Oo4th_patreon_name
PaypalDonate on PayPal
Twitter_logoFollow on Twitter

Write a Comment


  1. Hi Alan.
    I wanna ask you, is the Arduino overheating? Couse I read, that the maximum current draw is about 500mA on Arduino Uno and 1500mA on Mega. If my calculations are right, one of your sensor draws 300mA, you are using Arduino Mega that can supply only 1500mA (I read it there if I understood it right ) and 1500/300=5 so you should be able to use safely only 5 sensors but you are using 11. How did you achieved this? The second thing I want to ask you is: Can I use Arduino Leonardo for this purpose? What do you thing? I know it has less analog pins than Mega, so I will be able to make less sensors. However iťs a lot cheaper.

    • Hey! Yes, that’s too much power for Arduino Uno! I powered the sensors and LEDs of the DodecaLEDron with an external 5V power supply! I never really had any problems with Arduino overhearting, also because it doesn’t provide really enough current by itself. Arduino Leonardo should be fine, as far as I know! 😀

  2. Hi Alan,
    Congratulations for your amazing works, and tutorials you share.
    I’m trying to make a video interactive with public and to make it, i need to activate animations on screen when people reach a specific distance with the screen hooked on the wall:
    – When people enters in a zone near the screen > activation new state.
    – When people leaves this zone > back to the original state.
    I begin my project with a PIR sensor but it unable to detect no-moving bodies, and I don’t know to calculate precisely the distance between people and PIR.
    I don’t want the detection stops before people leaves the entire zone.
    Maybe ultrasonic sensor is the sensor I need.
    I ask you, which the best way (easily way ) to make this project? ( full money ).
    Special condition: I want to get the sensor value in Unity 3D.
    Thanks Alan,

    • Hey!

      I think there are really a lot of ways in which this project can be built.
      If you have those kind of constraints, perhaps using a Kinect is the best way. It can detect people even when they are not moving, and it works with multiple people. The problem is that when it comes to counting people in a real environment, sensors can be tricked very easily.

  3. Hey ALAN,

    I like the way you guys make the program and use it for different purposes like games. It is really cool. Umm…I need to clear this doubt.

    You have declared “int sensorPin=A0”. But you have given the read part in the above program as “analogRead(pinSensor)”. It is actually “sensorPin” right?

    I just have doubt in this. Thanks for the code 😀

  4. Hey Alan. In your code, you did not declare the variable “sensorCalibrationZero” and “sensorCalibrationOne”. Should I amek these equal to zero?


  • I create custom controller "Project Notouch" - Petr Marek February 26, 2017

    Hey Alan. In your code, you did not declare the variable “sensorCalibrationZero” and “sensorCalibrationOne”. Should I amek these equal to zero?

  • Everything You Need to Know About LEDs - Alan Zucconi February 26, 2017

    Hey Alan. In your code, you did not declare the variable “sensorCalibrationZero” and “sensorCalibrationOne”. Should I amek these equal to zero?