Issues with IR detection

Hello Everyone, I am currently working on trying to code 3 IR sensors to detect objects in front of them. The output is the same for them but they each have a different input. I want to be able to write a simple code that gets the IR sensors to detect when something is in front of them so that I can program motors to react accordingly.

I have attempted this code but it doesn't seem to do anything. It either says there an obstacle or the path is clear no matter what I do.

int LED = 13; // This is my output pin 
int obstaclePin = 3;  // This is one of my input pins
int hasObstacle = HIGH;  // HIGH MEANS NO OBSTACLE

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(obstaclePin, INPUT);
  Serial.begin(9600);  
}
void loop() {
  hasObstacle = digitalRead(obstaclePin); //Reads the output of the obstacle sensor from the 3th PIN of the Digital section of the arduino
  if (hasObstacle == LOW) //LOW means something is ahead
  {
    Serial.println("Stop something is ahead!!");
  }
  else
  {
    Serial.println("Path is clear");
  }
  delay(200);
}

The odd thing is I have my A-Star 32U4 Prime SV with a motor driver and a 15V battery. When I plug in my battery it changes from obstacle detected to path is clear or if it says my path is clear then plugging in the battery makes it say obstacle detected. I am just confused and I've been trying for a few weeks to figure this out so any help would be appreciated.

What sort of IR sensor are you using?

How is it wired up to pin 3 of your Arduino?

A simple sketch of your circuit would help us understand what is going on.

Ian

Is there a good place to do an online sketch?

I have added a simple diagram I made. A few notes, I've changed output pin on diagram as 11 just for simplicity. As you can see in the first box I have 3 pairs of receivers/senders. My receivers each have their own inputs, in, while all the transmitters are connected to 1 pin, out. Then each input is connected to a digital pin(3, 5, 7, 11) along with my out. the power and gnd are connected to my motor driver in there respective places.

So would something like this work?

void setup()                                 // Built-in initialization block
{
  pinMode(10, INPUT);  pinMode(9, OUTPUT);   // Left IR LED & Receiver
  pinMode(3, INPUT);  pinMode(2, OUTPUT);    // Right IR LED & Receiver

  tone(4, 3000, 1000);                       // Play tone for 1 second
  delay(1000);                               // Delay to finish tone

  servoLeft.attach(13);                      // Attach left signal to pin 13
  servoRight.attach(12);                     // Attach right signal to pin 12
}  
 
void loop()                                  // Main loop auto-repeats
{
  int irLeft = irDetect(9, 10, 38000);       // Check for object on left
  int irRight = irDetect(2, 3, 38000);       // Check for object on right

  if((irLeft == 0) && (irRight == 0))        // If both sides detect
  {
    backward(1000);                          // Back up 1 second
    turnLeft(800);                           // Turn left about 120 degrees
  }
  else if(irLeft == 0)                       // If only left side detects
  {
    backward(1000);                          // Back up 1 second
    turnRight(400);                          // Turn right about 60 degrees
  }
  else if(irRight == 0)                      // If only right side detects
  {
    backward(1000);                          // Back up 1 second
    turnLeft(400);                           // Turn left about 60 degrees
  }
  else                                       // Otherwise, no IR detected
  {
    forward(20);                             // Forward 1/50 of a second
  }
}

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency, 8);              // IRLED 38 kHz for at least 1 ms
  delay(1);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  delay(1);                                  // Down time before recheck
  return ir;                                 // Return 1 no detect, 0 detect
}  

void forward(int time)                       // Forward function
{
  servoLeft.writeMicroseconds(1700);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                               // Maneuver for time ms
}

void turnLeft(int time)                      // Left turn function
{
  servoLeft.writeMicroseconds(1300);         // Left wheel clockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                               // Maneuver for time ms
}

void turnRight(int time)                     // Right turn function
{
  servoLeft.writeMicroseconds(1700);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
}

void backward(int time)                      // Backward function
{
  servoLeft.writeMicroseconds(1300);         // Left wheel clockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
}

[\Code]

Jlawler:
So would something like this work?

void setup()                                 // Built-in initialization block

{
  pinMode(10, INPUT);  pinMode(9, OUTPUT);  // Left IR LED & Receiver
  pinMode(3, INPUT);  pinMode(2, OUTPUT);    // Right IR LED & Receiver

tone(4, 3000, 1000);                      // Play tone for 1 second
  delay(1000);                              // Delay to finish tone

servoLeft.attach(13);                      // Attach left signal to pin 13
  servoRight.attach(12);                    // Attach right signal to pin 12
}

void loop()                                  // Main loop auto-repeats
{
  int irLeft = irDetect(9, 10, 38000);      // Check for object on left
  int irRight = irDetect(2, 3, 38000);      // Check for object on right

if((irLeft == 0) && (irRight == 0))        // If both sides detect
  {
    backward(1000);                          // Back up 1 second
    turnLeft(800);                          // Turn left about 120 degrees
  }
  else if(irLeft == 0)                      // If only left side detects
  {
    backward(1000);                          // Back up 1 second
    turnRight(400);                          // Turn right about 60 degrees
  }
  else if(irRight == 0)                      // If only right side detects
  {
    backward(1000);                          // Back up 1 second
    turnLeft(400);                          // Turn left about 60 degrees
  }
  else                                      // Otherwise, no IR detected
  {
    forward(20);                            // Forward 1/50 of a second
  }
}

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency, 8);              // IRLED 38 kHz for at least 1 ms
  delay(1);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);      // IR receiver -> ir variable
  delay(1);                                  // Down time before recheck
  return ir;                                // Return 1 no detect, 0 detect
}

void forward(int time)                      // Forward function
{
  servoLeft.writeMicroseconds(1700);        // Left wheel counterclockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                              // Maneuver for time ms
}

void turnLeft(int time)                      // Left turn function
{
  servoLeft.writeMicroseconds(1300);        // Left wheel clockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                              // Maneuver for time ms
}

void turnRight(int time)                    // Right turn function
{
  servoLeft.writeMicroseconds(1700);        // Left wheel counterclockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                              // Maneuver for time ms
}

void backward(int time)                      // Backward function
{
  servoLeft.writeMicroseconds(1300);        // Left wheel clockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                              // Maneuver for time ms
}

[\Code]

It might do. I can't tell without more details of your infra-red sensors they seem to have an LED pin and receive pin. You are driving the LED pin at 38kHz and expecting to see a signal on the sensor receive pin. Is that correct?

Are you using standard 38kHz IR receivers e.g. The VS1838B? If so how are you powering the device?

The information about how you are connecting to the sensor seems to change every time you post.

First it was pins 13 and 3. Then it was pins 3,5,7 and 11 and now it is 2, 3, 9 and 10. All very confusing.

As I said in my previous post we need details about the sensors and how they are connected.

Try hand drawing the circuit on a blank piece of paper, photographing it with your phone and posting the jpeg.

Ian

I'm sorry I have been confusing, I have just been tired and stressed trying to figure this out and only have about a day to do this. Here is the code I have been working on, no matter what I do it just tells me that there an obstacle in the way. These are my actual pins. I'll pot more info if I can later.

void setup()                                 // Built-in initialization block
{
  pinMode(3, INPUT);  
  pinMode(5, INPUT); 
  pinMode(11, INPUT);  
  pinMode(13, OUTPUT);   
}  
 
void loop()                                  // Main loop auto-repeats
{
  int irLeft = irDetect(13, 3, 38000);       // Check for object on left
  int irRight = irDetect(13, 5, 38000);       // Check for object on right

  if((irLeft == 0) && (irRight == 0))        // If both sides detect
  {
     Serial.println("Stop something is ahead!!");             
  }
  else                                       // Otherwise, no IR detected
  {
     Serial.println("Clear!!");      
  }
delay(100);  
}

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency, 8);              // IRLED 38 kHz for at least 1 ms
  delay(1);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  delay(1);                                  // Down time before recheck
  return ir;                                 // Return 1 no detect, 0 detect
}

Ok. All change with the pins again :frowning:

The only thing I can suggest at the moment, without detailed information about the sensors, is that you ensure there is no direct optical path between the LED and the pick-up device. Ensure that the light from the LED can only get to the pick-up device by reflection from an external object. If necessary create a small hood from card to go over the pick-up device to limit the direction it can receive light from.

Ian

I am using standard 38 kHz receivers as you put earlier. All the LED's have covers over them. I've linked a photo of one of the pairs so that you can hopefully get a better clue of what I'm discussing. Sorry again for the confusion, I'm trying to explain it simply and I think I made it more confusing.

No matter what I do the sensor reads low and won't read there not being an object in front. Any help would be appreciated, especially since I need this working in like a day.

Jlawler:
I am using standard 38 kHz receivers as you put earlier. All the LED's have covers over them. I've linked a photo of one of the pairs so that you can hopefully get a better clue of what I'm discussing. Sorry again for the confusion, I'm trying to explain it simply and I think I made it more confusing.

Which one? Are you supplying power to the device? All the 38kHz sensors require Vcc and GND to produce a signal.

The datasheet for the VS1838B indicates it needs a 20k ohm pullup resistor. You might try changing your input pin pinMode() statements from this:-

  pinMode(3, INPUT);  
  pinMode(5, INPUT);
  pinMode(11, INPUT);

to this:-

  pinMode(3, INPUT_PULLUP);  
  pinMode(5, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);

Which may help if you are using the VS1838B.

Ian

You may still want to look at putting a hood on the receiver. If you read this article:-

You'll see that at least the VS1838B receivers are sensitive to strong external lighting which might be your problem.

Also the heat shrink used to shroud the diodes may not be as opaque to IR light as it looks.

Ian

It appears I am using the TSOP34838.

Jlawler:
It appears I am using the TSOP34838.

First thing to use a multimeter in conjunction with this datasheet:-

and ensure that the correct voltages/signals are applied to the correct pins. If the output pin is stuck low then that implies that power is not getting to device or is the wrong way round.

Note there are four version of the 38kHz device TSOP34838 and TSOP34438 which are wired one way and TSOP32238 and TSOP32438. If the board was designed for 322 series parts but 328 series parts were fitted then I would expect to see exactly what you are getting (output stuck low..

Have you tried connecting an oscilloscope to the output pin of the TSOP34838 to see if it ever goes high?

Ian

Hey guys so just one more question, I have gotten my IR sensors to work, kind of. I can get the sensor to detect something but once my sensors detect something it returns to reading clear even when an object is in front of it. So for example if I wave my hand in front of it, it will say something is there and then immediately return to saying clear even while my hand is still there, to get it to say it see's something again I have to pull my hand away and return it but when I return it it will only say it saw an obstacle once. Is there a simple fix or a bigger issue?

void setup()                                 // Built-in initialization block
{
  pinMode(3, OUTPUT);  
  pinMode(5, OUTPUT); 
  pinMode(11, OUTPUT);  
digitalWrite(3, HIGH);
digitalWrite(5, HIGH);
digitalWrite(11, HIGH);
  
  pinMode(13, INPUT);   
}  
 
void loop()                                  // Main loop auto-repeats
{
  int irLeft = irDetect(3, 13, 38500);       // Check for object on left
  int irRight = irDetect(5, 13, 38500);       // Check for object on right
  
  if((irLeft == 0) || (irRight == 0))        // If both sides detect
  {
     Serial.println("Stop something is ahead!!");             
  }
  else                                       // Otherwise, no IR detected
  {
     Serial.println("Clear!!");      
  }
delay(100);  
} 

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency) ;              // IRLED 38 kHz for at least 1 ms
  delay(2);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  delay(2);                                  // Down time before recheck
  return ir;                                 // Return 1 no detect, 0 detect
}

Here my code and I added a picture to try and show what is happening.

Jlawler:
Hey guys so just one more question, I have gotten my IR sensors to work, kind of. I can get the sensor to detect something but once my sensors detect something it returns to reading clear even when an object is in front of it. So for example if I wave my hand in front of it, it will say something is there and then immediately return to saying clear even while my hand is still there, to get it to say it see's something again I have to pull my hand away and return it but when I return it it will only say it saw an obstacle once. Is there a simple fix or a bigger issue?

First off, well done on getting as far as you have. I think your issue will be simple to fix.
These TSOP sensor have automatic gain control for dealing with noisy environments. Try changing this:

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency) ;              // IRLED 38 kHz for at least 1 ms
  delay(2);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  delay(2);                                  // Down time before recheck
  return ir;                                 // Return 1 no detect, 0 detect
}

to this:

int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency) ;              // IRLED 38 kHz for at least 1 ms
  delay(2);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  noTone(irLedPin);
  delay(2);                                  // Down time before recheck
  return ir;                                 // Return 1 no detect, 0 detect
}

and see how it goes.

Thanks so much!, It works perfectly. If I may ask, why did noTone fix it?

Jlawler:
Thanks so much!, It works perfectly. If I may ask, why did noTone fix it?

Awesome, that is great to hear :slight_smile:
As for it works: without getting too technical, if the sensor is exposed to the correct IR radiation for too long it automatically cuts off. This is to stop it from responding to high levels of background IR. Adding the noTone() shuts off the IR LEDs for a bit and allows the sensor to 'reset' for the next time you check it.