How to use an IR proximity detector attached to an Arduino: This beginners tutorial shows you how you CANNOT use a KY-032 proximity sensor! However I'll give you a solution that uses DIY parts and works much better!



This is a beginner's guide to using an IR proximity sensor with an Arduino Uno. The sensor allows you to detect objects in front of the sensor to a few centimeters without physical contact. That's what I hoped this page would be about - it's not - until you get to the diy bit!

Warning: This sensor is designed badly and works poorly (KY-0032).

Seriously: Do not buy/use/consider this module in any of your projects DO NOT USE.
Note: Use the Simpler Hardware described later on to get a better result.

Introduction

ky-032 is a rubbish module - annotatedIn this project you will (try to): I tried to use an IR proximity sensor module to detect when objects are close, and trigger outputs on an Arduino.

The one problem that the IR proximity detector has is that the distance detected will change depending on the reflections from the surface that it is pointed at.

The other problem is that the circuit used (KY-032) - is RUBBISH!

IR remote detector operation

The IR remote detector, here HS0038B, suppresses any continuous signals (all of these modules operate in a similar way). In the introduction for the datasheet the following is stated:

"Some  examples  for  such  disturbance  signals  which are suppressed by the HS0038B are:

Continuous   signal   at   38kHz   or   at   any   other frequency"
The built in AGC will suppress any continuous signal (including the one you want 38kHz). The intention of this feature is to allow an Arduino board to ignore any interfering IR signals continuously received by the proximity sensor e.g. 50/60Hz fluorescent lights etc. The problem is the that module will also ignore any continuous 38kHz signal - as the AGC circuit kicks in.

What is a KY-032 IR Proximity Sensor

The KY-032 is a basic infrared proximity sensor module commonly used with Arduino. It contains an IR LED which emits infrared light and an HS0038B photodiode module (this is basically an IR remoter receiver) which detects the presence of infrared light. This sensor outputs a digital signal when it detects modulated IR light.

Operating at 38kHz

For this proximity sensing application the sensor module is slightly problematic as the HS0038B (IR remote receiver) is designed to operate at a frequency of 38kHz. Meaning that the the IR light must be turned on and off at this frequency for it to register anything. This is why there is a chip on the KY-0032 module, and the chip is a 555 oscillator.

The idea is that the processor does not have to generate a high speed signal, so saving processing power. However, the module is so badly designed that this is a moot point i.e. the idea is good but the module is nearly useless in its implementation.

The jumper connector

Also on the board is a jumper pin which overrides the control signal 'EN', and when present turns on the oscillator permanently.

Why is this even present, surely you want the output to be always on?

ky-032 with IR LED slightly onNow, that begs the question, why is the unit usually used with the continuous active mode (jumper pin connector is present). The answer is that it is used a lot in a moving robot proximity detector. If the robot is moving, then the reflected light signal will be continuously changing. i.e. from a situation where the robot is in the middle of the room there will be no reflection while near a wall there will be maximum reflection. So the internal AGC will be continuously changing level - so it will detect walls/objects.

The module is so bad it is difficult to get it to do anything so the above, although technically, correct is meaningless for this module's operation.

KY-0032 Design Flaws

  1. The current limit potentiometer can allow zero ohms = infinite current (or what the power supply can output). This is offset by the flaw below.
  2. Inability of the 555 timer to output an even mark-to-space ratio. Results in only 10% power to IR LED when modulating. (this is actually a good design choice - see IR power control)
  3. Setting the power level potentiometer changes the M:S ratio which is bad anyway.
  4. The frequency setting potentiometer does not allow 38kHz operation.
  5. The burst mode (EN signal) turns on the IR LED permanently when it is supposed to be off - Don't use burst mode!
  6. Use of an NE555 - a timer chip - that is known to crowbar the supply.

Measurements

Potentiometer 1 - Frequency (left side)

This is located on the left side of the board with the connectors at the bottom.

Parameter measurements for the pot 1

One of the pots on the module allows you to set the frequency, output by that chip, to 38kHz accurately - of course you would need a frequency counter or oscilloscope to do that. If you don't have one just set it to the middle position.

Actual measured frequency was 47.47kHz. Even though that is a little way off 38kHz the sensor still works at detecting distance. The adjustment range is from 46.5kHz to 48.4kHz! That means the circuit is designed badly.

Potentiometer 2 - Power (right side)

This is located on the right side of the board with the connectors at the bottom.

The output time low of the signal controlling the IR led is 292ns (right pot fully clockwise) - min. power.

The output time low of the signal controlling the IR led is 1.84us (right pot fully anti-clockwise) - max. power.

KY-032 Problems examined - Enable and IR LED output

The oscilloscope screen shot below shows the enable signal in yellow, and the IR LED controlled pin in blue.

ky-0032 in burst mode IR LED output and control signal

The IR LED output is on when the control signal (blue) is low. Although it is at 47kHz, the output is low for ~10%  of the 47kHz period. Actual calculation is 2us / (1.0/47e3).

You can see that the IR LED is now permanently on when the control signal (yellow) is low (all the time that is outside the selected period above),  because during reset (active when pulled low), the output of the 555 is low. So during reset the IR LED is tuned on!!!

You could argue that this means there is no '38kHz' modulation signal, and since there is no activity - the IR sensor will not react.

During the 47kHz output the IR LED energy is reduced to 10%, and is 100% when you don't need it!

What a lot of absolute rubbish.

No wonder it is used with the enable pin attached. In this mode the module's operation at least makes some sense. There is no permanently 'ON' IR LED but you still get only 10% IR output level - an no, adjusting the power control does nothing much; that operation is also flawed.

Simple proximity detection

Although I was looking to create this action it almost happened by accident. The two keys to the method, presented below, are:

  1. Use of off-frequency operation to de-sensitize the receiver.
  2. The IR LED is turned continuously on and blipped low.

Now, for a normal design you would decide to only blip the LED high but I accidentally coded it the other way up (fortunately).

Let's recap on the design process.

Having seen the absolute garbage that is the KY-032, I decided to use the simplest circuit consisting of - an IR remote detector module and an IR emitting diode with, of course the current limiting resistor of 100 Ohms. That's 3 components!

Reduce receiver sensitivity

What are the fundamentals of trying to do this:

  1. The IR Remote detector is ultra sensitive so it can operate over meters of distance.
  2. Power control of the output IR LED is essential (it's the only way to reduce the sensitivity of the detector which has fixed gain sensitivity).

There are three ways to control sensitivity:

  1. Stick a bigger resistor (or pot.) in the output IR LED circuit.
  2. Change the operational frequency of the IR LED output.
  3. Change the mark-to-space ratio of the IR LED control (reduce power).

You can do number 1, but I chose to figure out a different way (using only 3 components). The idea is that the IR remote receiver operates at 38kHz, however that is only partially true. In fact the input is filtered by a notch filter so it is not:

    "This will work at 38kHZ and no other frequency."

The IR remote will, in fact, detect modulated IR signals even if they are of a different frequency, but at different frequency they will have less effect i.e. the sensitivity of the IR remote will be less at different frequencies other than 38kHz. The upshot is that you can make the IR detector less sensitive by increasing or reducing the modulation frequency around the center frequency! - making the period longer is easier for the microcontroller giving it more time to process.

    "You can de-sensitize the IR remote detector by NOT using 38kHz!"

This is what you need to do to reduce the range of the detector from meters to centimeters.

When I first coded this with an even mark to space ratio and at 38kHz the detector was so sensitive that it detected IR modulation which ever way it pointed! By re-coding for a higher frequency it began to work.

Change the mark-to-space ratio

Another way to reduce power generated is to only output IR LED light for a very small time - this reduces the available light energy that the IR remote detector can detect.

You can also control the frequency of the blips to set the frequency seen by the IR remote detector.

Accidental correct operation

The idea was to turn on the LED for a very short time compared to the off time to reduce light output. Fortunately, I go this the wrong way round and it works better to keep the IR LED on and only turn it off for a short time.

I accidentally turned the IR LED on and blipped it low. This works a lot better than the blip high method, probably because of the way the IR detector works:

  •  For blip high - range is ~2cm. Also uncontrollable for larger distances.
  •  For blip low - range is ~10cm. This works well.

Required Components

  • Arduino Uno
  • KY-032 IR Proximity Sensor
  • 220 ohm resistor
  • Breadboard
  • Jumper wires
  • LED
  • IR LED
  • 100 Ohm resistor
  • 1k~10k potentiometer (optional - I did not use one).
  • IR Sensor Module

Three Components

Arduino IR remote keys-22The circuit diagram shows how to connect the components on a breadboard. The IR sensor module is connected to a digital input pin on the Arduino. 

The sensor outputs a digital voltage which is low when IR modulated light is detected.


Arduino IR LEDAn IR LED and 220 ohm resistor are connected to digital pin 2, which we will control with our Arduino code.

Circuit Layout

Obviously point the LED and IR detector facing the same way - that can't be shown on the diagram!

arduino ir sensor circuit layout

Diagram using Fritzing software.

Schematic Diagram

arduino ir sensor schematic

Diagram using Fritzing software.

Libraries needed

The library you need to install is none. Its just clever control of the output signal and reading a digital input port.

Example Sketch

// Diy IR proximity detector. Forget KY-0032

const int OUTPUT_PIN = 9; // Output pin for the 38kHz signal use 100R in series
const int IR_SENSE = 10;  // IR remote receiver
const int LED_PIN = 5;

// From https://www.best-microcontroller-projects.com/arduino-digitalwrite.html
#define setPin(b) ( (b)<8 ? PORTD |=(1<<(b)) : PORTB |=(1<<(b-8)) )
#define clrPin(b) ( (b)<8 ? PORTD &=~(1<<(b)) : PORTB &=~(1<<(b-8)) )
#define tstPin(b) ( (b)<8 ? (PORTD &(1<<(b)))!=0 : (PORTB &(1<<(b-8)))!=0 )

#define IR_DIST_20CM 25  // approx
#define IR_DIST_10CM 50  // approx
#define IR_DIST_5CM  100 // approx
 
void setup() {
  pinMode(OUTPUT_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(IR_SENSE, INPUT);  
}

#define ONTIME 1
#define OFFTIME (IR_DIST_10CM-ONTIME) // <n>>us signal with uneven M:S for power control

void loop() {
     
  // Inverted
  byte val = gen_IR_pulses();

  delay(100); // Debounce the signal
  if (val==gen_IR_pulses())
    if (val==0)  digitalWrite(LED_PIN,HIGH); else digitalWrite(LED_PIN,LOW);
 
  delay(100);

}

// This is hand coded for timing
byte gen_IR_pulses(void) {
  setPin(OUTPUT_PIN);
  for (int i = 0; i < 10; i++) {    
    delayMicroseconds(OFFTIME); // Manual tuned using oscilloscope DW takes time!    
   
    clrPin(OUTPUT_PIN); // Output low pulse ~ 240ns
    clrPin(OUTPUT_PIN);    
    delayMicroseconds(ONTIME); // Does not output 1us when ONTIME is 1!
    setPin(OUTPUT_PIN);
  }
  return( digitalRead(IR_SENSE) );
}

Code explanation

Short Code Explanation:

  • The main loop generates the IR pulses and reads the sensor value twice, with a delay to debounce.
  • Based on the debounced readings, it turns the LED on or off.
  • IR pulse generation function uses fast macros to toggle the output pin 10 times.
  • Each pulse is defined by an OFFTIME delay followed by a very short low period using clrPin and setPin macros.
  • The function returns the reading of the IR sensor pin after pulsing to detect the reflected IR signal if present.

Detailed Code Explanation:

Constants

  • OUTPUT_PIN, IR_SENSE, & LED_PIN define the pins used.
  • IR_DIST_XXCM thresholds define approximate proximity distances in microseconds.

Macros

  • Fast digitalWrite macros are imported for faster pin toggling.
  • setPin(), clrPin(), tstPin() directly set/clear/test port bits.
  • The explanation for these macros is here:

Setup

  • Pins are configured - OUTPUT_PIN and LED_PIN as outputs, IR_SENSE as input.

Main loop

  • gen_IR_pulses() function generates IR pulses on OUTPUT_PIN
  • The IR sensor value is read twice with a delay in between.
  • This debounces the reading to avoid false triggers.
  • Based on the debounced readings, the LED is turned on or off.

gen_IR_pulses()

  • - Uses fast macros to toggle OUTPUT_PIN 10 times.

Each pulse is defined by

  • ONTIME (the pulse we want as output).
  • OFFTIME (the total period less an approximate delay ~ ONTIME).
  • Note On and OFF are inverted here see - happy accident that makes it work!
  • A very short low period by calling clrPin() twice.
  • Note The microsecond delay is not accurate at low values.

Uploading the Code

There are a few steps to uploading the code using the Arduino IDE:

  • Connect the Arduino Uno to the PC with a USB cable.
  • Select the Arduino Uno hardware.
  • Open a new sketch.
  • Paste the code above into the new page (overwrite everything).
  • Press the upload button (right arrow at top).

You can find a more detailed tutorial on the Arduino IDE page.

Testing the Circuit

To test the circuit, connect all components as shown in the diagram. Bring your hand close to the sensor module to see the LED turn on, showing detection. You can experiment with different distance thresholds in the code.

TIP: Change the frequency of the pulse output to change the sensitivity of the receiver i.e. change the definition of OFFTIME.

Conclusions

Simple IR proximity sensor for Arduino using 3 componentsIn this tutorial you learned how IR proximity sensors work and used the KY-032 module replaced the KY-032 with 3 simple components to create an IR proximity sensor using an Arduino - a circuit that is easy to use and actually works!

This was achieved by drastically reducing the average power pulse change generated by the IR LED, using a PWM signal and also relying on the fact that the IR remote will still decode IR signals when it is used in "out-of-specified-frequency" operation.

It works!

The circuit detected hand movements and triggered an LED at a useful range of about 10cm.

Surprisingly it works a lot better than the KY-032!

This demonstrated a basic example of using an IR sensor for non-contact detection and interactions.

With further code this concept could be expanded into a robot obstacle avoidance project, or other applications that require a non contact distance measuring method.

Range increase

There are two ways to increase the range - alter code to alter the frequency closer to the sweet spot of 38kHz or alter the code to generate more IR power change i.e. increase macro ONTIME.

If you want a "hands-on-adjustable" range do the above and add a potentiometer as described.


Written by John Main who has a degree in Electronic Engineering.

Note: Parts of this page were written using claude-instant as a research assistant.


Comments

Have your say about what you just read! Leave me a comment in the box below.

Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.



Privacy Policy | Contact | About Me

Site Map | Terms of Use