IR range/proximity detector not working as expected

I am trying to build an IR range/proximity detector. It sort of works, but there seems to be an issue with external light sources and what appears to be noise and I am unsure how to proceed.

The circuit looks like this:

2 IR LEDs in series connected to each pin 10, 11 and 12.

12 ----|>|--|>|--+
11 ----|>|--|>|--+
10 ----|>|--|>|--+
                _|_
                 -
                 '

A voltage divider with a 40k? resistor on one side, and what appears to be a IR photodiode (value of A1 changes 
significantly if I reverse this element, I originally thought that this was a IR photo-resistor and is the reason why
I wired it in this way.  It still appears to work as I expected anyway. :D).

             +----- A1
             |
+5V -+-./\/'-+-|>|--+
     |             _|_
     +- AREF        -
                    '

Now please be gentle, I'm a programmer dammit, not an engineer! :smiley:

I know that I do not have a current limiter resistor on the LEDs, but from what I've gleaned from the web, this can work (and does). However, this may (most likely will) reduce the life of the LEDs. I'm thinking about using a transistor to switch them all on and off by going through the main supply.

But that is not my main concern at the moment (though if you want to comment on it, please feel free). My main concern is that I'm getting extra values when an external IR source hits the receiver. I've tried to compensate by reading in values when the LED source is off, turn them on, read more values and do this repeatedly, averaging them out and subtracting the on values from the off values.

Here's the code:

template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
static char const endl = '\n';

template<int I>
void pinMode(int const (&pins)[I], int state)
{
  for(int i = 0; i < I; ++i)
    pinMode(pins[i], state);
}

template<int I>
void digitalWrite(int const (&pins)[I], int state)
{
  for(int i = 0; i < I; ++i)
    digitalWrite(pins[i], state);
}


void setup()
{
  Serial.begin(115200); //start serial communications for test purposes
  pinMode(transPins, OUTPUT);
  digitalWrite(transPins, LOW);
  pinMode(displayRefPin, OUTPUT);
  digitalWrite(displayRefPin, HIGH);
  //analogReference(DEFAULT);
  analogReference(EXTERNAL);
  pinMode(transmitPin, OUTPUT);
  Serial << "START" << endl;
}
// offavg = (off0+off1+...off19)/20
// onavg = (on0-offavg+on1-offavg+...+on19-offavg)/20
//       = (on0+on1+...+on19)/20 - offavg

void loop()
{
  static int const innerLoopMax = 20, outerLoopMax = 20;
  long onValue = 0, offValue = 0, sample;
  int register value, samples = 0;
  for (int i=0; i < outerLoopMax; ++i)
  {
    for (int o=0; o < (sample = random(10,30)); ++o)
    {
      offValue += 1023-analogRead(recvrPin);
    }
    digitalWrite(transPins, HIGH);
    samples += sample;
    analogRead(recvrPin); // reset recvrPin
    for (int o=0; o < (sample = random(10,30)); ++o)
    {
      onValue += value = 1023-analogRead(recvrPin);
    }
    digitalWrite(transPins, LOW);
    samples += sample;
  }
  Serial << value << " - " << (double)onValue/samples << ", " << (double)offValue/samples << ", " << ((double)onValue - offValue)/samples << endl;
}

As I've stated, this does work, I can actually get about a foot range detection doing this, but I seem not to be able to subtract the on value from the off value which is a problem in varying light conditions. I'm thinking that the photo-diode receiver is not giving a linear value based on the amount of received IR light? If so, I'm not sure how I can characterize this function. The other alternative is that my driving the LEDs in this manner are causing noise in the system.

Any suggestions?

Thanks,

Adrian

EDIT: FYI, I'm using an UNO.

I know that I do not have a current limiter resistor on the LEDs, but from what I've gleaned from the web, this can work (and does). However, this may (most likely will) reduce the life of the LEDs.

No the LED are fine it is the arduino that you are killing. The current limit of 40mA is where damage starts to be done. My tests show that this can generate a current in excess of 250mA. Some people have an odd idea of what "work" means.
http://www.thebox.myzen.co.uk/Tutorial/LEDs.html

My main concern is that I'm getting extra values when an external IR source hits the receiver.

Yes it will. That is why people use modulated IR light and a tuned amplifier, that is an amplifier that will only respond to the frequency of the modulator. You still have problems with ambient light saturating the reciever but it is not as bad.

I'm thinking that the photo-diode receiver is not giving a linear value based on the amount of received IR light?

Yes again.

The other alternative is that my driving the LEDs in this manner are causing noise in the system.

No.

Grumpy_Mike:

I know that I do not have a current limiter resistor on the LEDs, but from what I've gleaned from the web, this can work (and does). However, this may (most likely will) reduce the life of the LEDs.

No the LED are fine it is the arduino that you are killing. The current limit of 40mA is where damage starts to be done. My tests show that this can generate a current in excess of 250mA. Some people have an odd idea of what "work" means.
LEDs

:slight_smile: Ok, I'll take another look at this then. Thanks for the link.

Grumpy_Mike:

My main concern is that I'm getting extra values when an external IR source hits the receiver.

Yes it will. That is why people use modulated IR light and a tuned amplifier, that is an amplifier that will only respond to the frequency of the modulator. You still have problems with ambient light saturating the reciever but it is not as bad.

That's why I'm modulating my signal. In the code, it shows that it is modulating randomly, but I've also tried statically. I figured that random may remove fast flickering light problems like that from a CFL.

Grumpy_Mike:

I'm thinking that the photo-diode receiver is not giving a linear value based on the amount of received IR light?

Yes again.

Hrm, this doesn't have a datasheet. Any idea how I can characterize it? Using PWM output to drive an LED to very its intensity will result in odd values I'm sure.

That's why I'm modulating my signal.

I think you are missing the point.
The only reason to modulate the light is so that the receiver can be a tuned narrow bandwidth amplifier. If it is just a detector then there is no advantage at all in modulating the light. In fact all it does is make it less bright and so weaker.

It is the amplifier on the receiver that will be rejecting the ambient light because it is not modulated. If you have no tuned amplifier then modulation makes no difference.

Grumpy_Mike:

That's why I'm modulating my signal.

I think you are missing the point.
The only reason to modulate the light is so that the receiver can be a tuned narrow bandwidth amplifier. If it is just a detector then there is no advantage at all in modulating the light. In fact all it does is make it less bright and so weaker.

Hmmmm, for the time that the light is on, it is just as bright as if it were on continuously, is that not correct? If so, ignoring ambient light for now, I would be using less power to still detect something that is in close proximity. It doesn't matter that on average, it is less light. It matters that I get the same amount of light while it is on.

Grumpy_Mike:
It is the amplifier on the receiver that will be rejecting the ambient light because it is not modulated. If you have no tuned amplifier then modulation makes no difference.

Now my idea is to modulate the LED so that I can detect what the voltage is when it is off and compare it to when the voltage is on. Then by determining a base line voltage when the LED is not on and then comparing it to when the LED is on, one can possibly infer the size or distance of the object against ambient light. That's the idea anyway allowing me to make a somewhat less expensive range finder that can do other things too.

If it is working to about a foot then that is all I would expect. Without an amplifier on the receiver it is hard to get enough signal for any more.
I am not sure what you mean when you say you can't subtract the on value from the off value, I am assuming that you can but it is not the result you expect.
You need install need to drive the LEDs through a transistor, then you could drive them to their full power and get more light.
You can try things like putting the sensors in a tube to narrow the angle but basically you need a more sensitive sensor.
Try a delay after you turn the light off to allow the sensors to setle.

Grumpy_Mike:
If it is working to about a foot then that is all I would expect. Without an amplifier on the receiver it is hard to get enough signal for any more.
I am not sure what you mean when you say you can't subtract the on value from the off value, I am assuming that you can but it is not the result you expect.
You need install need to drive the LEDs through a transistor, then you could drive them to their full power and get more light.
You can try things like putting the sensors in a tube to narrow the angle but basically you need a more sensitive sensor.
Try a delay after you turn the light off to allow the sensors to setle.

Yeah, almost 2 feet. So, if I create an amplifier circuit, I would get better range? Would it have to be photo transistor or could I just use a photo diode?

As for subtracting, it would not be just a simple subtraction. Looking around, I see that it's a logarithmic relation, it might be able to determine where on the graph it is if I can generate some known values allowing a proper subtraction to cancel out ambient light.

Also, I'm thinking that I need to light up the sensor a little to push it to its threshold value so that I can determine if there is just a little bit of ambient light. Otherwise I may not detect any ambient light, as it may not trip the sensor, but still cause a large voltage change in the signal.

If I can't get the subtraction working, I would still be able to use this as a proximity sensor, even if I can't guesstimate the range.

Ok, I'm not getting something that I'm trying to make sense of.

1st, I'm having some issues with making the LEDs blast bright enough as yet using a transistor. I used the schematic from here: SparkFun Max Power IR LED Kit - KIT-10732 - SparkFun Electronics but as I was running out of space on my breadboard and I didn't have enough of the 2N3904 transistors so instead, I used a P2N2222A and put the 6 IR LEDs in parallel. However, I think that I need to change the resistance of R2 from 56 to something much less to increase the current back to 40mA. Needless to say, I'm still really shaky on transistors and how to calculate this value.

So I went back to the original wiring to test something else out that was bugging me. I modified code slightly to output the following data I'm going to present:

void loop()
{
  static int const innerLoopMax = 20, outerLoopMax = 20;
  long onValue = 0, offValue = 0, sample;
  int register valueOff, valueOn, samples = 0;
  for (int i=0; i < outerLoopMax; ++i)
  {
    for (int o=0; o < (sample = 50); ++o)
    {
      offValue += valueOff = 1023-analogRead(recvrPin);
    }
    digitalWrite(transPins, HIGH);
    samples += sample;
    analogRead(recvrPin); // reset recvrPin
    for (int o=0; o < (sample = random(20,40)); ++o)
    {
      onValue += valueOn = 1023-analogRead(recvrPin);
    }
    digitalWrite(transPins, LOW);
    samples += sample;
  }
  Serial << "Sgl = " << valueOn << ", " << valueOff << ", Sum = " << onValue << ", " << offValue
    << ", Avg = " << (double)onValue/samples << ", " << (double)offValue/samples
    << ", Dif = " << ((double)onValue - offValue)/samples << endl;
}

I'm only showing the loop() function for brevity as everything else remains the same.

  • Sgl means a single value (last value read in) which is followed by the tuple last analog value on, last analog value off.
  • Sum means sum of all values which is followed by a tuple sum of analog values on, sum of analog values off.
  • Avg means the average of sums which is followed by a tuple of average of analog values on, averages of analog values off.
  • Dif means the differences between the average of average of analog values on and the average of analog values off which is followed by that value.
    Note that what I call the analog value is actually 1023 minus that value and by on and off, I mean the LEDs on and off.

Anyway, here is the data outputted:

  1. No light on photo diode (this is expected):
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00
    Sgl = 0, 0, Sum = 0, 0, Avg = 0.00, 0.00, Dif = 0.00

  2. Hand within range of photo diode (this is expected):
    Sgl = 3, 0, Sum = 498, 0, Avg = 0.34, 0.00, Dif = 0.34
    Sgl = 3, 0, Sum = 1497, 0, Avg = 1.03, 0.00, Dif = 1.03
    Sgl = 3, 0, Sum = 1549, 0, Avg = 1.07, 0.00, Dif = 1.07
    Sgl = 3, 0, Sum = 1525, 0, Avg = 1.05, 0.00, Dif = 1.05
    Sgl = 3, 0, Sum = 1661, 0, Avg = 1.15, 0.00, Dif = 1.15
    Sgl = 4, 0, Sum = 1659, 0, Avg = 1.14, 0.00, Dif = 1.14
    Sgl = 4, 0, Sum = 1742, 0, Avg = 1.21, 0.00, Dif = 1.21
    Sgl = 4, 0, Sum = 1737, 0, Avg = 1.21, 0.00, Dif = 1.21

  3. Flashlight on IR photo diode (this is NOT expected):
    Sgl = 1, 0, Sum = 304, 0, Avg = 0.21, 0.00, Dif = 0.21
    Sgl = 1, 0, Sum = 310, 0, Avg = 0.21, 0.00, Dif = 0.21
    Sgl = 0, 0, Sum = 271, 0, Avg = 0.19, 0.00, Dif = 0.19
    Sgl = 1, 0, Sum = 272, 0, Avg = 0.19, 0.00, Dif = 0.19
    Sgl = 1, 0, Sum = 274, 0, Avg = 0.19, 0.00, Dif = 0.19

  4. Flashlight more directly on IR photo diode (this is NOT expected):
    Sgl = 2, 1, Sum = 980, 1005, Avg = 0.67, 0.69, Dif = -0.02
    Sgl = 2, 1, Sum = 989, 1002, Avg = 0.69, 0.69, Dif = -0.01
    Sgl = 2, 1, Sum = 987, 1005, Avg = 0.68, 0.69, Dif = -0.01
    Sgl = 2, 1, Sum = 952, 1007, Avg = 0.67, 0.71, Dif = -0.04
    Sgl = 2, 1, Sum = 943, 1002, Avg = 0.66, 0.70, Dif = -0.04
    Sgl = 2, 1, Sum = 953, 1008, Avg = 0.66, 0.70, Dif = -0.04
    Sgl = 2, 1, Sum = 980, 1014, Avg = 0.68, 0.70, Dif = -0.02

Ok, so now I'll explain why these are expected and not expected values:

1. Expected because there is no light shining on the IR photo diode.
2. Expected because my hand is there and is reflecting the IR back at IR photo diode.
3. NOT expected because if there is no obstruction (i.e. my hand) so the on and off readings should be the same value, but off has a 0 value.
4. NOT expected because if there is no obstruction (i.e. my hand) so the on and off readings should be the same value, but off has a larger value then on.

If someone could tell me how to calculate the R2 resistor, that would be great, as too if someone could tell me why these unexpected results are appearing.

Thanks!

Each IR diode needs its own resistor because otherwise they will not shair the current.
Take the forward volts drop of the LED and subtract it from the supply voltage
5 - Vf = Vr to get the voltage across the resistor. Then divide that by the current you want to get the resistor value.
R = Vf / I
When you say get it back to 40mA, what makes you think that it was 40mA without a resistor. The 40mA limit is not what an arduino pin will supply it is what it should supply. You pull more out of it than this and it will be damaged. A lot more and it will be damaged enough to break it.
Look up the current limit on the IR LED you are using.

Grumpy_Mike:
Each IR diode needs its own resistor because otherwise they will not shair the current.

Do you mean share current evenly? That would be because each would have a slightly different resistance? Or I guess more precisely, stabilize at its own voltage?

Grumpy_Mike:
Take the forward volts drop of the LED and subtract it from the supply voltage
5 - Vf = Vr to get the voltage across the resistor. Then divide that by the current you want to get the resistor value.
R = Vf / I

Ok, so the transistor doesn't take anything out of the circuit like the LEDs? Thanks.

Grumpy_Mike:
When you say get it back to 40mA, what makes you think that it was 40mA without a resistor. The 40mA limit is not what an arduino pin will supply it is what it should supply. You pull more out of it than this and it will be damaged. A lot more and it will be damaged enough to break it.
Look up the current limit on the IR LED you are using.

No datasheet. :frowning: Will have to buy a multimeter tomorrow. Mine is nowhere to be found. :frowning:

So, you have no idea as to why I'm getting that output data?

Thanks.

So, you have no idea as to why I'm getting that output data?

No.

It is a bit hard to understand what you are doing and what the difference between 3 and 4 are. Remember that IR will not bounce off glass and an IR sensor will also show some sensitivity to viable light.

Grumpy_Mike:

So, you have no idea as to why I'm getting that output data?

No.

It is a bit hard to understand what you are doing and what the difference between 3 and 4 are. Remember that IR will not bounce off glass and an IR sensor will also show some sensitivity to viable light.

The difference between 3 and 4 is that the LED flashlight in 3 is not directly being directed directly at the IR sensor,but is focused directly on the IR sensor in 4. All 4 tests were done in the same space with the same ambient light (a dark room).

In which case why the mistery? If the torch ( that is what we say for flash light ) is just in the room the reflected light will not be enough to trigger the sensor, but when turned at the sensor it is intens enough to show something.

The mystery is why isn't the values of the IR sensor the same when the IR LEDs are on and off? There is nothing in front to reflect the IR light back to the sensor, and even if there were, the value should be higher when the IR LEDs are on, not lower.

You get leakage from the emitter to the sensor unless you colomated the two, like putting it down long tubes.

Thanks, but I have taken that into account. I even removed the sensor circuit and connected A1 directly to the ground and I get this:

Sgl = 835, 1023, Sum = 403312, 1022992, Avg = 280.47, 711.40, Dif = -430.93

and when I connect it to Vcc:

Sgl = 0, 0, Sum = 29, 109, Avg = 0.02, 0.08, Dif = -0.06

Notice that the on value is lower than that of the off value?

This makes no sense.

Yeah, I think I have found the problem. The LEDs are pulling too much current and are causing other things (i.e. the ADC) to fail. I'm going to have to have a separate current source to get them to be as bright as I want them (between 100-200mA if not more). Thing is, how do I wire one up using a transistor as a switch who's base is controlled by the Arduino and uses an external battery as a current source? They would require a common ground right? Would I just connect the negative terminal of the battery to a ground pin of the Arduino while using the USB as the primary power source? And then when I eventually make this a self contained unit, can I draw off the battery directly?

Yes that sounds like the way to proceed.

LED's don't really have "resistance". They have a quite non-linear voltage vs current characteristic.

To run them in parallel, you need a separate means of current regulation ( a constant current source, or a resistor )
for each one.

You can also connect them in series if you have a high enough voltage source, and then you only need one
means of current control.

michinyon:
LED's don't really have "resistance". They have a quite non-linear voltage vs current characteristic.

To run them in parallel, you need a separate means of current regulation ( a constant current source, or a resistor )
for each one.

You can also connect them in series if you have a high enough voltage source, and then you only need one
means of current control.

Yeah, I sorta understand that they are non-linear. But if you know the Vin and the voltage that each diode will stabilize at, what happens if you use only one resistor? Can you not calc the current flow? Or is this not a good idea as the stabilized voltage will drift over the life of the LED causing the current to shift as well?