Photo Interrupter Problems

We are working on a project that is using a photo interrupter. We are receiving an analog signal ranging from 0 to 1023. 1023 is the reading when it is a closed loop (when there is nothing in the gate). However, when the loop is open (something in the gate) the signal is oscillating and periodically returns to 1023. How can we obtain a steady value from the photo interrupter?

UPDATE
We are using the wiring that PieterP commented

Here is out code below.
We're trying to find velocity from posts that pass through the photo interrupter
setting is the number that the photo interrupter gives us
readingNumber is the index of the timeReadings array
couint1023 is the amount of 1023 in a row.
buf_number isthe amount of 1023 it takes for it to recognize there is nothing in the gate
we were attempting to cancel out the error of the oscillating value

const int POSTWIDTH = 0.05,
          DISTBTWN = 0.05;

int pIInPin = A1,
    ledPin = 7,
    setting,
    count1023 = 1,
    timer = 0,
    readingNumber = 0,
    buf_number = 10;
    
boolean isPost = false,
        runAgain = true;

long  timeReadings[10];
int  positionReadings[10];


void setup() 
{
  pinMode(pIInPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() 
{
  setting = analogRead(pIInPin);
  Serial.println(setting);
  if(setting != 1023)
  {
    if (count1023 > buf_number)
    {
      //Take Readings
      Serial.print("TOOK READING 1 : ");
      Serial.println(readingNumber);
      timeReadings[readingNumber] = millis();
      readingNumber++;
    }
    digitalWrite(ledPin, HIGH);
    count1023 = 0;
  }
  else
  {
    if(count1023 == 2) // BIG 
    {
      //Take Reading
      Serial.print("TOOK READING 2 : ");
      Serial.println(readingNumber);
      timeReadings[readingNumber] = millis();
      readingNumber++;
    }
    count1023++;
    if (count1023 > buf_number)
    {
      Serial.println("NO OBJECT");
    }
    digitalWrite(ledPin, LOW);
  }


  //Calculate Velocity
  if(readingNumber == 8)
  {
    double time12 = timeReadings[2] - timeReadings[1],
           time34 = timeReadings[4] - timeReadings[3],
           time56 = timeReadings[6] - timeReadings[5],
           time78 = timeReadings[8] - timeReadings[7];

    double velocity12 = POSTWIDTH/time12,
           velocity34 = POSTWIDTH/time34,
           velocity56 = POSTWIDTH/time56,
           velocity78 = POSTWIDTH/time78;

    for (double i : timeReadings) Serial.println(i);
    
  }
  
  timer++;
  //delay(50);
}

You could post code and your schematic

Hi,
Welcome to the Forum

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html
then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :slight_smile:

There's probably something wrong with your wiring. Most photo interrupters have an NPN open collector output. This means that it can only sink current (let current flow to ground). The Arduino will read this as a digital low. To read a high, however, you have to source current (have 5V on the sensor output). This can be achieved by using a pull-up resistor, either a discrete one, or the internal pull-up resistor of the Arduino pin.
To enable this internal pull-up, use:

pinMode(photoPin, INPUT_PULLUP);

It's strange that you get a high reading when there's nothing in the gate, please post your code and schematic, read the guidelines first, as Tom suggested.

This is the easiest way to connect it:
Opto-interrupter.png

Hope this helps!
Pieter

SChiccarine:
We are working on a project that is using a photo interrupter. We are receiving an analog signal ranging from 0 to 1023.

I suspect you should be connecting to a digital I/O pin - possibly one of the external interrupt pins.

In addition to the questions already asked ...

What is the photo-interrupter being used for?

...R

@PieterP
(This is my first time using the forum so I hope I'm doing this right)

Used the INPUT_PULLUP for my pinMode
The values are much more precise.
Now when the gate has something in it, it reads an oscillating value of 990-999
When it's open it reads an oscillating value of 1000-1007

Is this supposed to happen? Thank you very much

Is this supposed to happen? Thank you very much

No. Have you followed Robin2's advice and tried a digitalRead() instead of an analogRead() for the sensor?

SChiccarine:
Now when the gate has something in it, it reads an oscillating value of 990-999
When it's open it reads an oscillating value of 1000-1007

Is this supposed to happen? Thank you very much

No, you should get ~0 when there's nothing in the gate, and ~1023 when the beam is obstructed. It's basically a digital signal.
Please post the part number of the interrupter.

Pieter

Back up a bit....

Let's assume you get the analog vs digital reading thing sorted, high and low as expected.

But you say you're trying to measure velocity, with one gate? Hence the notion of counting how many 1023s (or now with a digital approach, lows.) I didn't yet unravel your thinking.

To me it seems reasonable to figure out the time the post was in the gate from taking time the instant the signal changed, then take the time the instant it changed back; the difference is how long the post blocked the gate. Then divide that duration by the post's width.

Look at the state change detection example in the IDE, at File > Examples > 2.Digital, which will show you how to use the comparison of the previous state to the current state, and then you can use that to see when the post went in, and when it came out again.

Our part number is Rb-See-190

So I editted our code. Most of it is commented out so the only thing is does is output the reading of the Photo gate which is the setting varible, onto the Serial Monitor
Our schematic is the one that PieterP responded with earlier.

Right now we have the Photo gate plugged into pin A4 and a digitalRead.
We tried plugging the photogate into pin 4 and using digital but we only got values of 1 nothing else.

thank you so much for the help

const int POSTWIDTH = 0.05,
          DISTBTWN = 0.05;

int pIInPin = A4,
    ledPin = 7,
    setting,
    timer = 0,
    readingNumber = 0;
    
boolean isPost = false,
        runAgain = true;

long  timeReadings[10];
int  positionReadings[10];


void setup() 
{
  pinMode(pIInPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() 
{
  setting = digitalRead(pIInPin);
  Serial.println(setting);
  if(setting != 1023)
  {
    
      //Take Readings
      //Serial.print("TOOK READING 1 : ");
     // Serial.println(readingNumber);
      //timeReadings[readingNumber] = millis();
      //readingNumber++;
    
    //digitalWrite(ledPin, HIGH);

  }
  else
  {

      //Take Reading
      //Serial.print("TOOK READING 2 : ");
      //Serial.println(readingNumber);
      //timeReadings[readingNumber] = millis();
     // readingNumber++;
   

    //digitalWrite(ledPin, LOW);
  }


  //Calculate Velocity
  if(readingNumber == 8)
  {
    /*double time12 = timeReadings[2] - timeReadings[1],
           time34 = timeReadings[4] - timeReadings[3],
           time56 = timeReadings[6] - timeReadings[5],
           time78 = timeReadings[8] - timeReadings[7];

    double velocity12 = POSTWIDTH/time12,
           velocity34 = POSTWIDTH/time34,
           velocity56 = POSTWIDTH/time56,
           velocity78 = POSTWIDTH/time78; */

    //for (double i : timeReadings) Serial.println(i);
    
  }
  
  timer++;
  //delay(50);
}

Hi,
What is the value of R1?
Opto-interrupter.png
Please can you post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Opto spec.
http://www.robotshop.com/media/files/pdf/photo-interrupter-sen129a3b.pdf

Can you please post a picture of your project?

Thanks.. Tom.. :slight_smile:

Ahh, TomGeorge beat me to it.

I was thinking to try

R1 = 220Ω
R2 = 10K
Add 0.1µF from Arduino input to GND.

Your photo interrupter has a wide gap. You're detecting posts (cylindrical objects?) ... as they pass through the slot, the IRLED gradually gets blocked then exposed. During this gradual process, there would normally be noise or false triggers.

The capacitor is for hardware debouncing. Could do software debouncing instead if desired.

EDIT: What's the maximum speed the posts pass through the slot?

p.s. input_pullup will not work if you are reading an analog inout (no need as stated above)

Use a digital input with input_pullup.

Technically no need for external resistor with short wire runs.
(except to drive the LED from 5V)
Opto sinks between input pin and ground/0V
Light blocked = LOW
Light open = HIGH

That's all there is to it.

This is crazy

setting = digitalRead(pIInPin);
  Serial.println(setting);
  if(setting != 1023)

The variable setting will have a value of 0 or 1. Why are you comparing it to 1023?

And I do NOT mean that you should change it to analogRead()

...R

lastchancename:
Use a digital input with input_pullup.

Check reply #6. Noise when blocked or open. Signal not reaching 1023. Stronger external pullup seems necessary (stronger signal, less noise).

Are you sure that the IR LED is working? Did you use a series resistor? If not, it may be broken. That would explain a lot.
You could try to point a camera at the LED to see if it lights up purple on the screen. (Our eyes don't pick up IR, but cameras do.)
And are you sure that you connected the emitter to ground and the collector to the input, and not the other way around?

dlloyd:
Check reply #6. Noise when blocked or open. Signal not reaching 1023. Stronger external pullup seems necessary (stronger signal, less noise).

The internal pullups should be strong enough (whatever that means), I've used them with photo interrupters numerous times, so it would really surprise me if that's the problem ... But hey, who knows?

Pieter

OMG, We are talking about a single pin digital input!
How much more complicated can it be made to sound?

One digital input pin.
Internal or external pull-UP (say 4K7) to 5V on the opto-NPN
External current limit from 5V to the opto-LED (say 220R) Anode (+ pin)

pinmode(thePin, INPUT_PULLUP);
if (digitalRead(thePin)) 
    Serial.print("opto blocked");
else
    Serial.print("opto open");

So I have simplified the code so that it only displays the setting and nothing else. I'm still unsure whether or not I should be using analog pins and analog reads or digital pins and digital reads, so i put both in the program with one option being commented, the other not.

I added my schematics too. R1 is 560 ohms and R2 is 56K ohms.

Thank you so much for all this help

int setting;
//int pIInPin = A0;
int pIInPin = 4;

void setup() 
{
  //pinMode(pIInPin, INPUT_PULLUP);
  pinMode(pIInPin, INPUT);
  Serial.begin(9600);
}

void loop() 
{
  //setting = analogRead(pIInPin);
  setting = digitalRead(pIInPin);
  Serial.println(setting);
}

Schematics

So I realize that the image didn't attach properly so I tried attaching it from my google drive.

Thank you so much

This is the image. See this Image Guide

You have the Arduino connection to GND - that won't work. It must be attached between the resistor and the photo-transistor so that when there is no light the resistor hold the signal HIGH and when the photo-transistor detects light and conducts it pulls the signal LOW.

...R