slot car timer/counter code trouble

I am currently in the process of working on a code for the arduino capable of counting laps as well as keeping time for a slot car track with two lanes. Other than the simple projects followed in my “getting started with arduino” book, this is the first project I have tried to accomplish. For this project I have used multiple sources as reference but this is the first time I have went to the forum for help.

The hardware I am using is an arduino uno wired to a 16x2 lcd screen with two pushbuttons used to simulate the inputs from the track.

Before I display the code I would like to note the following; I have written two programs, one which counts the laps and one which keeps the time. Each works as expected when used alone. It is when I merge the two that I recieve unexpected results.

The errors recieved are 1.) when I place the timing portion of the code within the lap counting code for lane one only, it will keep time of each lap, but will decrement every two laps (or button presses). 2.) when I place the timing portion of the code into both lanes, the time kept will alternate between the press of each button and the lap counter will only decrement on random occasions.

The code is as follows;

//Sketch designed to use IR sensor and emitter for slotcar lap detection.

//Note: tinted diode is IR emitter. Clear diode ir IR detector.
//An LED will be used for IR status indication.

int PBPin1 = 8;    // PB for lane 1 simulation
int PBPin2 = 9;    // PB for lane 2 simulation
int val_1 = 0; // lane 1 changes
int val_2 = 0; // lane 2 changes
int old_val_1 = 0; // previous state of lane 1
int old_val_2 = 0; // previous state of lane 2
int state_1 = 99; // current state of lane 1
int state_2 = 99; // current state of lane 2

float starttime;
float duration;

// The setup() method runs once, when the sketch starts

// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);



void setup()   {                
  // initialize the digital pin as an input:
  pinMode(PBPin1, INPUT); 
  pinMode(PBPin2, INPUT);

  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  //CONSTANTS
  // set the cursor to column 0, line 0
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 0);
    // print text:
  lcd.print("LN1");
 lcd.setCursor(4, 0);
    // print text:
  lcd.print("LAP");
   lcd.setCursor(10, 0);
    // print text:
  lcd.print("T");  
  lcd.setCursor(0, 1);
    // print text:
  lcd.print("LN2");
    lcd.setCursor(4, 1);
    // print text:
  lcd.print("LAP");
      lcd.setCursor(10, 1);
    // print text:
  lcd.print("T");
  
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop(){
  //LANE1
  val_1 = digitalRead(PBPin1);  //read value from PB1
  if ((val_1 == HIGH) && (old_val_1 ==LOW)){    //compare new state of PB1 to old state
    state_1 = state_1 - 1;    //if a change has occured subtract 1
    delay(100);    //debounce
  }
    if(digitalRead(PBPin1) == LOW)    //once PB1 is set to low begin counting
  {
    starttime = millis();
    while(digitalRead(PBPin1) == LOW)
    ;
    float duration = millis() - starttime;
    lcd.setCursor(11,0);
    lcd.print(duration/1000);    //display time between button press for lane 1
  }
  
  old_val_1 = val_1;    //reset value
  
  lcd.setCursor(7,0);
  lcd.print(state_1);    //display lap for lane 1
  
  
  //LANE2
  val_2 = digitalRead(PBPin2);  //read value from PB2
  if ((val_2 == HIGH) && (old_val_2 ==LOW)){    //compare new state of PB2 to old state
    state_2 = state_2 - 1;    //if a change has occured subtract 1
    delay(100);    //debounce
  }
  
   if(digitalRead(PBPin2) == LOW)    //once PB1 is set to low begin counting
  {
    starttime = millis();
    while(digitalRead(PBPin2) == LOW)
    ;
    float duration = millis() - starttime;
    lcd.setCursor(11,1);
    lcd.print(duration/1000);    //display time between button press for lane 2
  }
  
  old_val_2 = val_2;    //reset value
  
  lcd.setCursor(7,1);
  lcd.print(state_2);    //display lap for lane 2

}

I am fairly new to this so if any of the information is unclear please verify. Any help would be greately apprecieated.

Thank you.

I haven't looked at the whole code, but I think this is where you measure the lap time:

    while(digitalRead(PBPin1) == LOW)
    ;

This is blocking code which means your sketch can't do anything else until this loop ends. In particular, it means it can't time the other lap.

I guess that 'state_1' is your lap counter - that's not a very helpful choice of name.

To handle two lanes you need to restructure your sketch to be non-blocking. You already have a starting point for this at the very start of your loop:

val_1 = digitalRead(PBPin1);  //read value from PB1
  if ((val_1 == HIGH) && (old_val_1 ==LOW)){    //compare new state of PB1 to old state
    state_1 = state_1 - 1;    //if a change has occured subtract 1
    delay(100);    //debounce
  }

The approach would be to read the input state looking for transitions. Each high-to-low transition makes the end of the old lap and the start of the new one, so calculate the duration of the old lap and then note the start time of the new lap.

Obviously you would be doing the same thing for both lanes. I suggest you use common code for both lanes. You can do that by holding the variables associated with each lane in arrays, and use the lane number (i.e. zero and one) as an index into each array. Then in loop() you would use a FOR loop to process both lanes.

I don't know whether you need to debounce your inputs but you might do. In that case you should use a non-blocking method to debounce them. I'm pretty sure there's a library to do that to save you reinventing the wheel.