Measuring time between input pin 4 and pin 5

Hi folks,
As many other I new to the sketch software so I ask you for some help.

I have a Mega 2560 and 2 IR barriers. I use TSOP4838.
I am going to measure the time for a object to pass between barrier 1, digital pin 4 (goes HIGH) and barrier 2, digital pin 5(goes HIGH).

I want to know the time in uS on the LCD but think I am doing something wrong. I get numbers without a object passing.
I would be happy for some ideas how to solve this.

The sketch I have done so far:

#include <LiquidCrystal_I2C.h>

/* -------- Initiera LCD displayen --------/
LiquidCrystal_I2C lcd(0x27,16,2);
int nr1 = 4; // Digital port 4
int nr2 = 5; // Digital port 5
int val1 = 0;
int val2 = 0;
float start ;
float stopp ;
float tid;
unsigned long time;
/
-------- Deklarera konstanter, Portar --------/
void setup(){
lcd.init();
lcd.setCursor(0,0);
lcd.backlight();
Serial.begin(9600);
pinMode (nr1, INPUT);
pinMode (nr2, INPUT);
}
/
---------- Börja loopen --------*/
void loop()
{

if (digitalRead(nr1)==HIGH){
start = micros();
start=start/100000;
// lcd.print (start);
}
else if (digitalRead(nr2)==HIGH){
stopp = micros();
stopp=stopp/100000;
//lcd.print (stopp);
}
else
{
tid = (stopp - start);
// lcd.print (tid);
}

lcd.init();
lcd.backlight();
lcd.print(“Time:”);
lcd.setCursor (0,1);
lcd.print (start);
lcd.print (",");
lcd.print (stopp);
lcd.print (",");
lcd.print (tid);
delay (3000);
}

Regards
Bo

'start' and 'stopp' should be unsigned longs and not floats.

You use micros() but divide the result by 100000; so accouracy will not be better than 100ms (far from the required 5 us).

Can't help with te problem that it picks up stray signals.

Note
please edit your post and add code tags around the code so it looks like below

your code here

What's connected to pins 4 and 5? Got pull down resistors?

TSOP4838 as I understand it: as far as I could quickly see in the datasheet thry have internal pullups; might be misinterpreting it though. Hence I did not comment on it.

You are delaying 3 seconds (plus display time) EVERY TIME THROUGH loop()! Your 'stopp' time will, therefore, always be at least three seconds after (or before) 'start'.

Perhaps you could use the external interrupts on Pin 2 and Pin 3 to detect the rising edges. That is what I would do.

Maybe this will work:

#include <LiquidCrystal_I2C.h>

/* -------- Initiera LCD displayen --------*/
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int StartPin = 4;
const int StoppPin = 5;
unsigned long StartTime, StoppTime, TIDTime;

/*  -------- Deklarera konstanter, Portar --------*/
void setup() {
  lcd.init();
  lcd.setCursor(0, 0);
  lcd.backlight();
  Serial.begin(9600);
  pinMode (StartPin, INPUT);
  pinMode (StoppPin, INPUT);
}

/* ---------- Börja loopen --------*/
void loop() {
  if (StartTime == 0 && digitalRead(StartPin)) {
    StartTime = micros();
  }

  if (StartTime != 0 && StoppTime == 0 && digitalRead(StoppPin)) {
    StoppTime = micros();
  }

  if (StartTime != 0 && StoppTime != 0) {
    TIDTime = StoppTime - StartTime;

    lcd.init();
    lcd.backlight();
    lcd.print("Time:");
    lcd.setCursor (0, 1);
    lcd.print (StartTime);
    lcd.print (",");
    lcd.print (StoppTime);
    lcd.print (",");
    lcd.print (TIDTime);
    delay (3000);
    StartTime = 0;
    StoppTime = 0;
  }
}

Isn't the TSOP4838 meant for receiving serial data on a 38Khz carrier frequency? (see this IR serial Thread)

Can it be used as a simple detector for a beam-break signal?

...R

Delta_G:
What's connected to pins 4 and 5? Got pull down resistors?

I have a 38kHz transmitter that gives the IR diode high power.
I also have checked the outputsignal from the TSOP4838 with my oscilloscope and then input to pin 4 and 5 are HIGH as the object cuts the beams.

Hi Again,
I have used the sketch from johnwasser.
When I pass an object both StartTime and StoppTime write the same value on LCD. It seems to calculate the passing ok but i dont understand what I have missed.
The values stays and just adds up at the next passing. StartTime =0 and StoppTime=0 at the end. What have I missed?

#include <LiquidCrystal_I2C.h>
 
/* -------- Initiera LCD displayen --------*/
LiquidCrystal_I2C lcd(0x27,16,2);
const int StartPin = 4;
const int StoppPin = 5;
unsigned long StartTime, StoppTime, TIDTime;
/*  -------- Deklarera konstanter, Portar --------*/
void setup(){
 lcd.init();
  lcd.setCursor(0, 0);
  lcd.backlight();
  Serial.begin(9600);
  pinMode (StartPin, INPUT);
  pinMode (StoppPin, INPUT);
} 
/* ---------- Börja loopen --------*/
void loop(){

if (StartTime == 0 && digitalRead(StartPin)) {
    StartTime = micros();
    StartTime = StartTime/1000000;
  }

  if (StoppTime == 0 && digitalRead(StoppPin)) {
    StoppTime = micros();
    StoppTime = StoppTime/1000000;

  }

  if (StartTime != 0 && StoppTime != 0) {
    TIDTime = StoppTime - StartTime;

    lcd.init();
    lcd.backlight();
    lcd.print("Time:");
    lcd.setCursor (0, 1);
    lcd.print (StartTime);
    lcd.print ("mS, ");
    lcd.print (StoppTime);
    lcd.print ("mS, ");
    lcd.print (TIDTime);
    lcd.print ("mS");
    StartTime = 0;
    StoppTime = 0;
    TIDTime = 0;
    delay (3000);
  }
    StartTime = 0;
    StoppTime = 0;  
}

The IR receiver module would have a signal that is normally high. It is internally pulled high (very weakly) by a 30K resistor. If the receiver is not right next to the Arduino, I would strengthen the signal by using an external 2.2K to 4.7K resistor.

Since the signal normally sits at a high level and is actively driven low by an internal NPN transistor, it would be inherently better to detect a FALLING signal, that is the point the signals state changes from high to low.

Currently, you're detecting while a signal "is" high, not when it "becomes" high. If they're high at the same time, this would cause problems in your code.

Anyways, try adjusting your code so that it detects when the signal "becomes" low. This would require a variable (for each signal) to hold the previous state.

Here's some general timing waveforms to show what the signals could look like...

Short TIDTime:

Longer TIDTime:

Because you are measuring the time in seconds (microseconds divided by a million) you will get 0 for the TID as long as the TID is less than 1 second.

DO NOT DIVIDE THE TIMES BY A MILLION UNTIL YOU ARE DONE CALCULATING THE TID! THEN USE FLOATING POINT SO YOU ARE NOT THROWING AWAY 6 DECIMAL PLACES.

#include <LiquidCrystal_I2C.h>
 
/* -------- Initiera LCD displayen --------*/
LiquidCrystal_I2C lcd(0x27,16,2);
const int StartPin = 4;
const int StoppPin = 5;
unsigned long StartTime, StoppTime, TIDTime;
/*  -------- Deklarera konstanter, Portar --------*/
void setup(){
 lcd.init();
  lcd.setCursor(0, 0);
  lcd.backlight();
  Serial.begin(9600);
  pinMode (StartPin, INPUT);
  pinMode (StoppPin, INPUT);
} 
/* ---------- Börja loopen --------*/
void loop(){

if (StartTime == 0 && digitalRead(StartPin)) {
    StartTime = micros();
  }

  if (StoppTime == 0 && digitalRead(StoppPin)) {
    StoppTime = micros();
  }

  if (StartTime != 0 && StoppTime != 0) {
    TIDTime = StoppTime - StartTime;

    lcd.init();
    lcd.backlight();
    lcd.print("Time:");
    lcd.setCursor (0, 1);
    lcd.print (StartTime/1000000.0, 7);
    lcd.print (" S, ");
    lcd.print (StoppTime/1000000.0, 7);
    lcd.print (" S, ");
    lcd.print (TIDTime/1000000.0, 7);
    lcd.print (" S, ");
    StartTime = 0;
    StoppTime = 0;
    delay (3000);
  }
// DO NOT RESET THE START AND STOPP TIMES EVERY TIME THROUGH loop()!
    // StartTime = 0;
    // StoppTime = 0;  
}