Do you want to know how to use cheap infrared receiver sensors to detect objects? How to build a Single or Dual proximity sensor and determine fast if you have objects or a clear path ahead or on the sides? Then read on, my friends, read on!
When I started to build hobby robots, I wanted to start from the basics and go up to the fancy stuff. I never got good enough at the fancy stuff (I lack advanced programming skills), but I learned the basics (took me some years to do it, as there was not too much info on how to do it with AVR micros). There are good books to learn robotics, but almost all of them are for PIC microcontrollers. Because at the time the hardware programmer was expensive (about $100) and I was supposed to buy the PIC Basic Pro ($100) to be able to do the projects in the books, I wasn't too eager to start using PICs. One of the books I read that helped me A LOT in understanding the basics of robot functioning was the text from Parallax.com called "Robotics with the BOE-Bot". I never owned a BOE-Bot or a BasicStamp for that matter, but the book is written for students to learn robotics and the principles are true for any robot. After I was introduced to AVR microcontrollers and Bascom-AVR I wrote the code in Bascom for almost every experiment in that text book. Then I found Arduino, and imediately I could adapt the code to work with the new board.
Nowadays almost nobody is using one of the cheapest methods to detect objects, avoid obstacles or find the range to the detected objects. Why? Perhaps because you need more than one pin from the microcontroller and a few more lines of code than needed when you use a Sharp IR (infrared) or Ping US (ultrasonic) sensor. And it bugs me because you almost never use the full potential of the Sharp sensor, you always set a treshold and you treat objects that are further away as non existent and detect only objects that are closer. Basically you are using it as a digital On/Off sensor with the treshold adjustable in the code. The more experienced builders are using the Sharp sensors or the Ping sensors, so that example is followed by the beginners, who are not aware that there are other methods for object detection.
So I decided to make this tutorial about using the regular IR modulated receiver sensor mostly found in TVs and VCRs. I will use some information from the text book mentioned above (read Chapter 7: Navigating with IR headlights) with Arduino code for exemplification.
Ok, so what is that sensor? How does it work? How can we use it for our purpose? Let's see:
The most popular sensor found in the US is made by Panasonic and the part number is PNA4601M. It may come with or without a metal shield that you need to connect to the ground. You will find even a cheaper sensor made by Vishay, the TSOP4838 sensor. I prefer this sensor over the Panasonic one because I can use it with low voltage systems (3.3V) directly. The sensor is an infrared remote control signal demodulator and it is sensitive only to infrared light that is modulated in the 38kHz frequency. What does that mean? It means that the light is turned on and off 38000 times per second. The sensor filters out any other frequency or straight IR light. You can find sensors that are sensitive to other frequencies, from 36 up to 56kHz. But we'll talk about that later. The sensor will output a High signal unless it detects a proper modulated light when it will output a Low signal as long as the light is on.
If the sensor only detects IR light modulated in the 38kHz frequency, how can we give it to it? Well, we will use an IR LED that we will turn on and off 38000 times per second. We will aim the LED towards the front of the robot and expect that the modulated light will go out and bounce off an object and come back to be detected by the sensor (also facing forward). Easy.
How do we connect the sensor and the LED to Arduino (or any other mocrocontroller)? The sensor looks like a rectangular capsule with a little dome on one face and 3 leads. If you hold the sensor with the dome towards you and the leads down, the first lead from the left is Signal, the middle lead is Ground, the right lead is Positive. You need to connect the Signal lead to any digital pin on the Arduino board, the Ground to the GND pin and the Positive to the 5V pin. The LED has a long lead that is the anode which you will connect to a series resistor of 220 ohm then the resistor to a digital pin on Arduino. The short lead is the cathode, which you will connect to the ground on Arduino. That's it.
Now how do we code it? First, we need to declare the pins where we connected the sensor and the LED, before the setup() function. While we are at it, let's also declare the Digital 13 LED:
#define IRsensorPin 9
#define IRledPin 10
#define D13ledPin 13
We need to create a function that will modulate the LED 38000 times per second for about 10 miliseconds. To find out the time for the LED to be On and Off we divide 1 second by 38000 and we get 0.000026 seconds, or 0.026 miliseconds, or 26 microseconds. We will turn the LED On for half that and Off for the other half of the time, resulting a 50% duty cycle. Further, we will divide 10 miliseconds by 0.026 miliseconds to find out how many times we need to repeat flickering the LED and we get 384.
void IR38Write() {
for(int i = 0; i <= 384; i++) {
digitalWrite(IRledPin, HIGH);
delayMicroseconds(13);
digitalWrite(IRledPin, LOW);
delayMicroseconds(13);
}
}
Nice. Now we write our setup() function where we set the pin mode for the LED to be output, since all Arduino pins are set to input by default. We set the pin Low so the LED does not output any light until needed. We also set the Digital13 LED to output so we can see when an object was detected.
In the loop() function we flicker the IR LED and check the sensor for any reflection. If a reflection was detected, we turn on the D13 LED, if not, we turn it off. Instead of turning on and off the D13 LED you can drive or stop your robot.
That's it. Now we can play with our hand in front of the sensor and see how far the sensor detects it. But what do we do if the distance is too far? Or too close? How do we adjust the detection range (by range I mean the interval of distances starting from close to the sensor and all the way to where the sensor stops detecting the object)? There are 2 methods: a hardware method and a software method. Let's talk about each.
The hardware method of adjusting the detection distance. Remember we used a resistor in series with the IR LED? We add a 5 kilo-ohms potentiometer in series with them. We can then adjust the pot until the sensor detects the object at the distance we want. If we need a closer range, we replace the resistor with a smaller value, like 100 ohms and adjust the pot until we get the desired distance.
The software method. Remember we split those 26 microseconds in 2 equal values to get a 50% on/off duty cycle? We can decrease the On time and increase the Off time to keep the same 26 microseconds, resulting a duty cycle of less than 50%. The LED will shine with a smaller power, thus reducing the detection distance. If we need to increase the distance, we increase the On time.
Getting more advanced. With a sigle sensor, we can detect any object in front of the robot in a 20-45 degree cone, depending on the LEDs lense (see the data sheet for your particular LED). The sensor has a very large detection cone that covers about 120 degrees all around the sensor. If we want to reduce the detection cone we need to place a tube in front of the sensor so it detects only the light that comes directly in front of it. We can mount the sensor and the LED on a servo and look left and right when we detect an object in front of the robot, to see where we can safely turn the robot and continue driving. With this method we get a whole 180 degrees range in front of the robot where we can detect objects.
Here is the code for a scanning IR Proximity sensor:
byte ObjectDetected=0;
Servo PanServo;
void loop(){
You need of course to add your code for driving and turning the robot instead of the comments.
Another method is to use 2 sensors or 2 IR LEDs, one for detecting objects on the Left, one for the Right. This method is fast, but it doesn't cover the whole 180 degrees range like the sensor on the servo. But most of the times is good enough, asuming you can find a pair of LEDs with a wide emiting cone (45 or even 60 degrees). You can get the entire 180 degrees by using 2 sensors mounted on the left and right side, angled outwards (like this: / \ but aim for about 30 degrees, the slashes look like about 60 degrees) and use 5-6 LEDs in parallel spread around to send the light in all directions. You flicker all the LEDs at the same time, then you check the Left sensor, flicker the LEDs again and check the Right sensor. If you detect on the left, turn right, if you detect on the right, turn left, if you detect in both directions, that means there is an object in the front of the robot. If you decide to use 2 LEDs, mount one on the Left, and one on the Right, with the sensor in the center facing forward. Flicker the Left LED, check the sensor, flicker the Right LED, check the sensor again. This is called a Dual IR Proximity Sensor.
Here is the code for a Dual proximity sensor:
#define IRsensorPin 9
#define LeftIRledPin 10
#define RightIRledPin 11
#define D13ledPin 13
byte ObjectDetected=0;
void IR38Write(byte IRledPin) {
for(int i = 0; i <= 384; i++) {
digitalWrite(IRledPin, HIGH);
delayMicroseconds(13);
digitalWrite(IRledPin, LOW);
delayMicroseconds(13);
}
}
One more thing, the text book explains that if we change the frequency from 38kHz to several higher values, (40, 42, 44kHz) by making the delayMicroseconds(13) smaller (both of them!), we make the sensor less sensitive and thus determine the distance range where the object is at that moment. For example, if at 38kHz the object is detected at 20 inches, at 40kHz it will be detected say at 16 inches, at 42kHz at 10 inches, at 44kHz at 4 inches. You need to actually determine what are the exact values for your setup, but you can determine if the object is far, close, closer or right in front of your robot.
Oh yeah, let's not forget that the IR light gets reflected differently by different colored objects, for instance white reflects more than black, so the actual distance to the object greatly depends on the color of the object.
That's about it, I think I mentioned everything that was important. I will add pictures with the schematic another day, now I'm toasted. Let me know if I need to explain anything in more detail.
Update:
I forgot to mention something very important: you have to make sure no IR light escapes the LED sideways and backwards. Use a shrink tube and make sure you squeze it at the leads. Even with a shrink tube on my LED, the IR sensor still picked up some light. I had to add another larger shrink tube over it to completely block sideways light.
You can use the same sensor for remote control or object detection, or, you can choose 2 sensors that work at a different frequency, say 38kHz for the remote and 56kHz for the object detection. You can have 2 or more robots use the object detection sensor to talk to each other, exchange commands or other info. Detect the lenght of the IR signal to switch between obstacle detection and communication. The communication protocol has a start bit that is about 2.4~2.5 miliseconds. In the examples above, the IR signal is 10 miliseconds. Make it 2 miliseconds, then look for signals that are greater than 2.2 miliseconds to switch to receiving communication bits.
Thanks for taking the time to read this!
Cheers!