Go Down

Topic: Photo Interrupter, high readings, low variation (Read 2949 times) previous topic - next topic


Jun 21, 2012, 06:34 pm Last Edit: Jun 22, 2012, 05:17 pm by Carsten53T Reason: 1
Hi All,
I want to check the steps of my stepper-motors and I have got hold of some GP1A57HRJ00F from SparkFun
specs: http://www.sparkfun.com/datasheets/Components/GP1A57HRJ00F.pdf
I found this post with a suggestion of how it should be wired:

Pin 1 will go to 5V.
Pin 2 will go to a resistor.
The other end of that resistor goes to ground.
From the table on page 4, you will see the forward voltage is about 1.14V at 7ma. That means the resistor need to be (5-1.14)/(.007) or 551 ohms. But since the LED can go up to as much as 50ma a standard 330 ohm resistor should do just fine.

Now the transistor side is even simpler.
Pin 3 goes to 5V
Pin 5 goes to ground
Pin 4 goes to a digital input pin on the Arduino.

This instruction is hard to cock up. [EDIT .. not entirely true ..]
When I test the setup, the blinded sensor do catch high values (1025), but starts quickly to fluctuate.
When stimulated by light, the sensorValues drops to the neighbourhood of 950.

I imagined that I would have a larger difference .. I'm pretty sure that there will be too many blunders for a trustworthy check on the motors. Can I improve the situation .. any suggestions?

I tried the setup on the specs page 6, but that was top-values on the sensor any way around. I did keep the capacitor, trusting that marking:
(whatever it means) is something that can substitute a 0.01uF cap.

// a bit off topic
When I go online and wait for the page to download .. the wait-cursor of my pc (a ring icon) slightly pulsates with a 1 hz pulse. When testing the interrupter I noticed that the static response would pulse with the same regular frequency. Maybe I should howl at my pc-trader.


Jun 22, 2012, 10:50 am Last Edit: Jun 22, 2012, 06:03 pm by Carsten53T Reason: 1
lessee .. a normal LED has the ground-side at the shorter leg.
The light-emitter on the interrupter has indeed a shorter leg .. but that's a marker for the positive side.
So I take a look at the specs page 2 at the outline-dimensions .. just to solve any confusion. Indeed, the picture leaves the question unsolved.
We've heard lately, that designers design things to break. I'm sorry on behalf of the trade.
(leaves information-search dumbfounded)

Seriously .. would it be possible to construct a circuit around the sensor-part of the interrupter that
1) pulls the sensor-output down (so that it provides a near 0 reading at analog-in-pin) when receiving no light.
2) leaves the output-values around 950 when emitter is on.

Or should I try to make the best out of what I've described above?

Without trying to understand the specs, this seems to be the reasonable way that the interrupter should work.

// Did misread initial circuit... problem solved


ehm i'm a beginner to arduino, but a handy programmer
you like the output to be down, and up once in a while ?

Hm besides that i think you would find this command interesting in Arduino
duration = pulseIn(pin, HIGH);  // minimal measurement time is about 30  ~ 50 micros = ..?. HZ = ..?. RPM

if would measure the microseconds of how long you have a high signal or the time of a rotation,
wich you might calculate as RPM and return to your computer over serial

another way to solve it might be

trigerval = 960;
val = digitalRead(inPin); //usualy a high value
if (val < trigerval){  dostuff() ;} else{ donothing() ;}

Notice however the speed of your arduino (16 mhz?) and the speed of your code, if your motor goes to fast, you might get strange reading
because the dostuff() takes longer then a cycle of your motor
i once made a program that used a timer delay value based on a LDR and then report it to my computer; in my case the arduino had no problem, however the serial connection of 9600 baud wasnt fast enough to keep up with my program loop and so the com3 connection got lost.
what i mean to say the things you measure should be in within working bounderies or you get strange readings


Sorry for not responding to your post. The original problem is actually solved and I've returned to pop a frustrated:
.. and your post seems to offer a not yet tried solution. I'm grateful.
I looked up pulseIn() in my references .. it's not there.
I've tried 10 different solutions .. one better than the other .. not wanting to realize that I won't get there as long as the sensor responds when I move my hand closer, but without touching anything. I look forward to try your suggestion.

I've added a dial (24 holes) on my stepper-axel and the photodiode to catch steps. The max stepper-speed uses 1500 micros pr step .. 200 steps pr circle. That should give ample time for the sensor. The idea (to check step-command count to actual steps performed) was consieved before I got a proper precision in stepping (using half-stepping).

The last attempt to ease down the sensitivity I wrote this (tried to average over 10 values too).

Code: [Select]

int maxVal = 800 ;// this is way too low!
int minVal = 10;

void loop() {
  sensorValue=0 ;
  for(int i=0 ; i<5 ; i++){
  sensorValue += analogRead(sensorPin);
  delayMicroseconds(10) ;

sensorValue/=5 ;

if( sensorValue < minVal  ){
    isHigh = false ;
    if(isHigh != isHighOld){
      digitalWrite(ledPin, LOW);
     // countMe();
    isHighOld = isHigh ;
  if( sensorValue > maxVal  ){ 
    isHigh = true ;
    if(isHigh != isHighOld){
      digitalWrite(ledPin, HIGH);
    isHighOld = isHigh ;

The in-between values that are not counted waves sinusoidal in a heart-beat rhythm [so does my pc, so it'll pass in it's intended setup].
Maybe I should focus on taking a proper series of measures say every 500 micros.


So your arduino doesnt respond to pulsin ?
Or do iget you wrong, PulseIn is part of the arduino language
Here is an example of pulsein    http://arduino.cc/en/Reference/PulseIn
Included with a samle

hmm its time for me to get some stepper motors too, putting a laptop on arduino wheels, and use the camera in combination with openvnc.
well its nothing new, it has been done before, but then i would have something fun to code.


PulseIn() responds. The problem is primarily the shape of  the pulse, and a suspicion that pulseIn() will wait (and thus block code-execution). The blocked state of the sensor seems to give a stabil signal .. so I'll try to detect those.


It stops here.
I've got a code that ... all things considered .. delivers a pretty clean signal, if not perfect.

Code: [Select]

int sensorPin = A0;    //
int ledPin = 13;      //
int sensorValue = 0;  //
int sensorValueOld = 0;
int sensorVeryOld=0;
int veryvery =0;
int very4 =0;
int very5=0;

int maxVal; //= 900 ;
int minVal; //= 5 ;
int counter=0;
int ct=0;
long time, oTime;
boolean wasVisited;
boolean isHigh, isHighOld ;

void setup() {
  pinMode(ledPin, OUTPUT); 

void loop() {

  sensorValue=0 ;

  for(int i = 0 ; i < 5 ; i++){
    sensorValue += analogRead(sensorPin);
  sensorValue /=5 ;
// it golps 250 micros in delays. This is a compromise. I read somewhere that arduino is 100 micros on a proper analog reading.
  maxVal= 400 ;
  minVal= 5 ;
// 5 consecutive readings must conform to the min/max requirements .. the max-test is reverted to inside the min-test as the min-values // are fluttering far less than the max-values
  if(sensorValue < minVal && sensorValueOld<minVal && sensorVeryOld<minVal && veryvery<minVal && very4<minVal&& very5<minVal ){
    isHigh = false ;
    if(sensorValue>maxVal && sensorValueOld>maxVal && sensorVeryOld>maxVal && veryvery>maxVal && very4>maxVal && very5>maxVal){
      isHigh = true ;

  very5 =very4 ;
  very4 = veryvery ;

// a state-change is registered:
    if(isHigh !=isHighOld && wasVisited==false){
// I don't think that this works as intended (skip small blips), but it seems to stabilize the signal, so I'll keep it.
  if(wasVisited  ){
    if(micros() - time > 300){

}// end loop

boolean tick;
void countMe(){
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin, LOW);

For those of you that works with equivalent challenges, I should mention a something that gives a little perspective to the 'magic' numbers I've chosen. The max-speed of the stepper uses 1500micros/step and it takes 200 steps for a full circle (300000 micros). The dial has 24 holes and can use 12000 micros from hole to hole, 6000 HIGH, 6000 LOW. The 250 micros on averaging gives an array of 24 values to detect a HIGH/LOW.
The 300 in " (micros() - time > 300" is intended to skip two close HIGH/LOW readings (it just exceeds the 250 micros a test takes)


Go Up