[ASK] Measuring Interval Between 2 Photodiode

Greetings, I am relatively new in programming world and would like to make physics experiment tool to make student easier while doing the experiment.

Basically, the tool need to measure time interval between two gate which I use photodiode as the sensor and infrared as the transmitter. The work principle is quite simple, the detail is a follows :

when the ball pass photodiode 1, the timer is started and will off when the ball pass photodiode 2.

here is the fritzing scheme :

Here is my code (If you dont mind, please give me the solution) :

const byte photoTransistor1 = 2;
const byte photoTransistor2 = 3;

unsigned long startTime;
unsigned long endTime;
volatile unsigned long elapsedTime;
volatile boolean done;

void ballPasses ()
{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor1) == LOW)
    {
    startTime = micros (); 
    }
  else
  {
    if (digitalRead (photoTransistor2) == LOW)
    {
    endTime = micros();
    elapsedTime = (endTime - startTime)/1000;      
    }
  }
    done = true;
    }



void setup ()
{
  Serial.begin (115200);
  Serial.println ("Timer sketch started.");  
  attachInterrupt (0, ballPasses, CHANGE);
}

void loop ()
  {
  if (!done)
  return;
  
  Serial.print ("Time taken = ");
  Serial.print (elapsedTime);
  Serial.println (" S");
  done = false;
  }

Any help would greatly appreciated :slight_smile:

A pull up resistor is needed when you use a photo diode in photoconductive mode.
That could be the internal pull up on the pin.

Add this to setup()...

pinMode(photoTransistor1, INPUT_PULLUP);
pinMode(photoTransistor2, INPUT_PULLUP);

Make sure the voltages on the photodiodes are over the switch thresholds of the digital pins (<1.5volt or >3volt) with/without light.
Measure voltages with a DMM. Ambient light could be a problem.
Leo..

You are only setting up one interrupt. I would expect you would set up BOTH interrupts for FALLING to catch the start and end times.

You divide the interval by 1000, throwing out three decimal digits of precision. Why measure in microseconds if you are only using whole milliseconds?

To get more precision and accuracy you could use the Input Capture Mode of Timer1 to get a time in 16ths of a microsecond.

thank you for the answer. I understand your suggestion but could not write it in the code. if you dont mind, could you please to fix the code...

makanbakso:
thank you for the answer. I understand your suggestion but could not write it in the code.

What part of " set up BOTH interrupts for FALLING to catch the start and end times." are you having trouble with?

Dear johnwasser, thank you for your reply

like this one?

const byte photoTransistor1 = 2;
const byte photoTransistor2 = 3;

unsigned long startTime;
unsigned long endTime;
volatile unsigned long elapsedTime;
volatile boolean done;

void ballPasses ()
{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor1) == LOW)
    {
    startTime = micros (); 
    }
  else
  {
    if (digitalRead (photoTransistor2) == LOW)
    {
    endTime = micros();
    elapsedTime = (endTime - startTime)/1000;      
    }
  }
    done = true;
    }



void setup ()
{

pinMode(photoTransistor1, INPUT_PULLUP);
pinMode(photoTransistor2, INPUT_PULLUP);

  Serial.begin (115200);
  Serial.println ("Timer sketch started.");  
  attachInterrupt (0, ballPasses, CHANGE);
  attachInterrupt (0, ballPasses, FALLING);
}

void loop ()
  {
  if (!done)
  return;
  
  Serial.print ("Time taken = ");
  Serial.print (elapsedTime);
  Serial.println (" S");
  done = false;
  }

Hopeless.

What has this got to do with amplitude shift keying?

sorry.. I really dont understand.. :sob:

  attachInterrupt (0, ballPasses, CHANGE);
  attachInterrupt (0, ballPasses, FALLING);

You're setting up the same interrupt (0 = Pin 2) twice. You need the interrupt for Pin 3, too. That is interrupt 1.

  attachInterrupt (0, ballPasses, CHANGE);
  attachInterrupt (1, ballPasses, FALLING);

But now you are calling the same function for both. You want to store the start time when the ball reaches the start and store the end time when the ball reaches the end. That should be two separate functions.

  attachInterrupt (0, ballPassesStart, CHANGE);
  attachInterrupt (1, ballPassesEnd, FALLING);

But now you still have the ballPassesStart both when the ball first blocks the light (FALLING) and when the light is no longer blocked (RISING). If you change CHANGE to FALLING you will get the interrupt when the ball first blocks the light, which is the time you want to record.

Does that help?

Dear Johnwasser, thank you for breaking the explanation

const byte photoTransistor1 = 2;
const byte photoTransistor2 = 3;

unsigned long startTime;
unsigned long endTime;
volatile unsigned long elapsedTime;

void setup ()
{

pinMode(photoTransistor1, INPUT_PULLUP);
pinMode(photoTransistor2, INPUT_PULLUP);

  Serial.begin (115200);
  Serial.println ("Timer sketch started.");  
  attachInterrupt (0, ballPassesStart, FALLING);
  attachInterrupt (1, ballPassesEnd, FALLING);
}


void ballPassesStart ()
{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor1) == LOW) {
    startTime = micros (); 
    }
}
  
void ballPassesEnd ()
{
  if (digitalRead (photoTransistor2) == LOW) {
    endTime = micros();
    elapsedTime = (endTime - startTime);      
   }
 }

void loop () {
  Serial.print ("Time taken = ");
  Serial.print (elapsedTime);
  Serial.println (" S");  
}

Like this one? I wonder, is it necessary to make void ballPassesEnd () ?
If yes, how to implement in the code?
I guest my code still wrong, especially in the logic started from void ballPassesStart ()

maybe somebody would help this...

void ballPassesStart ()
{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor1) == LOW) {

The only reason you got here was because you got an interrupt.
Why are you bothering to check what caused the interrupt?

TolpuddleSartre:

void ballPassesStart ()

{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor1) == LOW) {


The only reason you got here was because you got an interrupt.
Why are you bothering to check what caused the interrupt?

you mean that it is not necessary to write quoted code?
or like what?