pulseIn() not working as expected

I want to measure a breakbeam interval using a photodiode, display the time of the pulse, and return back to a ready state to repeat the measurement. I have measured the voltage at the indicated junction and it is about 40mv with ambient light, and a full 5v when illuminated. To rule out a hardware issue, I have also replaced the whole works with a momentary pushbutton to dump 5v right onto the pin (when I did this, however, I dispensed with the resistor, assuming that the arduino board or chip incorporates such a resistor and it's not necessary to drain the pin back to ground to get it to go low when the button is released).

It's not working. pulseIn() seems to return a value of 3000 +/- 300 regardless of whether I pulse it as fast as I can, or for about a half second. Pulses on the order of a second and longer do not return anything. I'm about to rewrite it using micros() or something because I don't see what the problem is. Perhaps someone else can spot it.

void loop () {

lcd.clear();
lcd.print("test ready");
delay(5);
dur=pulseIn(diode, HIGH);

if(dur>20) {   //read only if a reasonable pulse is measured
lcd.clear();
lcd.print(dur);
Serial.print(dur);
delay(500);
lcd.clear();

}
lcd.clear();

}

the rectangle represents the arduino board.

Correct me if I'm wrong but this is how I've interpreted your situation:

In the unbroken state the photodiode will result in 5v. In the broken state it results in 40mv.

So if you want to measure the "breakbeam" interval, you should start counting when the pin reads LOW and stop counting when it returns to HIGH.

If thats the case then dur=pulseIn(diode, HIGH); should be dur=pulseIn(diode, LOW);

I should clarify that I don't want to measure the time that the beam is broken, as I said, but I want to measure the time that the beam is established. Literally, how long the pulse of light lasts.

Your analysis would make sense because if I had the HIGH and the LOW flipped, it might be picking up the overshoot/backlash signal only and that would seem to account for my observations.

But I'm quite sure I have it the right way round. The photodiode is like a constant current source. In weak light, it only conducts a small amount of current and I measure 40mV on the high side of the resistor. When I shine my light on it, it breaks down and conducts a lot of current, and the voltage at the junction goes all the way to near 5v.

It's possible that I have misinterpreted the meaning of the HIGH parameter for pulseIn() or that the docs aren't clear, so I will check it now anyway.

I tried flipping the to pulseIn(x, LOW) and that doesnt't work at all, as expected, but it rules out the possibility that the docs are written backward.

I also tried explicity setting the pin low to start with, because I thought maybe it was outputing a digital 1 the whole time. It doesn't seem to have helped. By shining a light on the photodiode, I can get values of between 5000 and 35000 with most values being around 25000. I cannot get pulses of more than half a second or so regardless.

There must be something wrong with my code. I had thought that once it was running loop() continuously, that it would the vast majority of the time be sitting there ready to receive a high pulse, since the 1-second timeout of pulseIn() dominates the execution time of the whole loop. It's possible that I'm not understanding how pulseIn() works. I had assumed that when the pulseIn() line was executed it would sit there and wait for a high signal, time out if did not get one within 1 second (but nearly instantly wrap back around and start waiting again) and if it DID get one, it would pause the rest of the program while it listened for the pin to go back low.

this is the latest code.

void loop(){
  mode=0;   //for testing
  if (mode==0) {
    pinMode(trans,OUTPUT);
  digitalWrite(trans, LOW);
    pinMode(trans,INPUT);
  lcd.print("shuttertest mode");
  dur=pulseIn(trans,HIGH);  //read pulse duration

      if (dur>2) {               //only calculate a speed if a reasonable pulse was measured
        lcd.setCursor(0,1);        
        lcd.print(dur);
        dur=1;
        delay(500);
        }
   lcd.clear();      
   }

It's interesting that I also consistently get readings on the order of 3000 when I, having held the trans pin to ground by plugging it into the ground rail on the breadboard, yank it out of the breadboard to "floating".

2 suggestions here:

  1. Wire up a push button to a pin and use pulseIn to measure the pulses. See if this works properly. Im not too sure how you're going to do this with the switch bouncing though. So perhaps a hardware debouncer if you're pro. But try it atleast.

  2. Write your own pulseIn function

I have since tried two more things:

I changed the pulseIn() parameter to LOW to measure a low pulse, digitalWrote the input pin HIGH, then connected the photodiode between the pin and ground. With no light, the pinside of the photodiode is 5v, when illuminated, it drops to 2mV. I can perfectly reproduce the earlier behavior this way. It only returns values of less than 40 000 and usually somewhere in 20 000 - 30 000. I also added a delay in the loop() so that I can see the text on my LCD strobing as the loop executes over and over. When I illuminate the photodiode, the strobing stops, telling me that the loop is no longer executing over and over and pulseIn() is measuring my low pulse. However, I still cannot get accurate measurements of the pulse this way! If I leave the pin low for very long I get nothing, if I do a pulse of less than half a second I get a random value of 20 000 ish which would be 20ms which doesn't make sense anyway. This seems to prove that pulseIn is just not working for some reason. Does anyone ever use it, and can confirm that it works for them?

I would be more suspicious of your hardware interface then the pulse in library. You are using a vary unusually method to obtrain a digital value with no assurance of logic rise time through the transition region of the digital switching logic. Perhaps if there was a Schmidt trigger gate between the light sensor and the logic pin or a op amp configured as a analog comparator?

Just an opinion that you are mixing a fundamentally analog sensor to a digital input in a too simplistic manner. Perhaps some experienced EE types around here could comment on the interface being attempted here?

Lefty

You may be right. It gives me something else to try.

I replaced my code with a simple listener that lights up an LED when the photodiode is high. It appears to work perfectly and you can light up the LED for as short or as long as you want with no perceptable lag, so the circuit is working in a simplistic way, but there might be enough noise to fool pulseIn. Probably if I wrote my own function, it would fail in the same way without a lot of clever debouncing.