You need to detect the changes in the signals, only reading them will not work.
You will get two timestamps, one for each transition from free to blocked on both measurement points.
This is your code (after pressing ctrl-T to auto.format it), small codes are better embedded in code tags,
so it is easy to copy and can be viewed from any platform.
//Bi-direction train speed indicator
//Attempt 1 date 17/06/2018
//S is Speed to be in mph
//T is Time measured in seconds
//L is Distance between sensors in feet
//G is scale of model (ie gauge)
//This attempt is for n gauge hence G = 148
#include<Wire.h>
#include<LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27); //lcd address
int error;
long int start = 0;
long int finish = 0;
float timetaken = 0.000;
int flag = 0;
float mph = 000.0;
float length = 1; //distance of probes in ft
float G = 148; //ngauge
int direction = 0; //direction of train
float realdistance = 0.000;
void setup() {
Wire.begin();
Wire.beginTransmission(0x27);
error = Wire.endTransmission();
Serial.begin(9600);
Serial.print("Error: ");
Serial.print(error);
if (error == 0) {
Serial.println("LCD found");
lcd.home(); lcd.clear();
lcd.print("Ready");
delay(1000);
} else {
Serial.println("LCD not found");
}
lcd.begin(16, 2); //initialise the lcd
lcd.setBacklight(200);
pinMode(3, INPUT);
pinMode(4, INPUT);
digitalWrite(3, HIGH); //sensors go low on detect
digitalWrite(4, HIGH);
} // End of setup
void loop() {
if (flag == 0); {
lcd.home(); lcd.clear();
lcd.print("Ready for train");
Serial.println("flag=");
Serial.print(flag);
delay(1000);
}
if (digitalRead(3) == LOW || (digitalRead(4) == LOW)) {
flag = 1;
Serial.println("flag=");
Serial.print(flag);
}
if (digitalRead(3) == LOW && (digitalRead(4) == HIGH) && (flag == 1)) {
direction = 0;
Serial.println("direction=");
Serial.print(direction);
}
if (digitalRead(3) == HIGH && (digitalRead(4) == LOW) && (flag == 1)) {
direction = 1;
Serial.println("direction");
Serial.print(direction);
}
if (flag == 1) {
lcd.home(); lcd.clear();
lcd.print("Checking speed");
start = millis();
if ((direction) == 0 && digitalRead(4) == LOW) {
finish = millis();
flag = 2;
}
if ((direction) == 1 && digitalRead(3) == LOW) {
finish = millis();
flag = 2;
}
delay (1000);
}
if (flag == 2) {
lcd.home(); lcd.clear();
realdistance = (length * G / 5280); // ft in a mile
mph = (3600 * realdistance); // now into hours
timetaken = (finish - start) * 1.000 / 1000.000;
lcd.setCursor(0, 0);
lcd.print("Time taken=");
lcd.print(timetaken);
delay (1000);
lcd.setCursor(0, 1);
lcd.print("Speed MPH=");
lcd.print(mph);
delay (1000);
flag = 0;
}
}
I bet you already noticed that the first if in loop does not seem to work?
if (flag == 0); {
lcd.home(); lcd.clear();
lcd.print("Ready for train");
Serial.println("flag=");
Serial.print(flag);
delay(1000);
}
Notice the '; behind the condition?
That renders the whole if meaningless as it represents the empty action.
BTW displaying "Ready for train" and going to sleep for a full second is ridiculous.
pinMode(3, INPUT);
pinMode(4, INPUT);
digitalWrite(3, HIGH); //sensors go low on detect
digitalWrite(4, HIGH);
I would write
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
No comment necessary, more obvious, less letters to type.