Advice for Hot Wheels Race Stopwatch Timer Drag Race

Hi currently im working on project for making Hot Wheels Start and Finish gate with timer,
i'm use MAX7219 seven segment 8 Digit for my project.

this is my setup for my project :

  • 4 IR Sensor for start and finish 2 Lane
  • Time display MAX7219 seven segment 8 digit (first 4 digit for Lane 1,and the other for Lane2)

this is my goal for my project :

  • timer trigger when cars cross the start sensor
  • timer stop when cars cross finish sensor
  • after race is finish the timer reset to zero

what i already accomplish :

  • timer triggered when cars cross the start sensor
  • timer stopped when cars cross finish sensor

my question is :

  • when the first cars cross the start sensor,then the other cars on the other lane cross the start sensor,the timer "copy" the sensor on who cross the sensor first, is it possible to make individually millis timing?

-i read on some topic here that is impossible to reset millis back to zero at loop, how to manipulate millis back to zero?, currently im just use reset button so after race is finish i press the reset button, is there any side effect doing this on and on?

i heard about RTC is it necessary for my project?,i.e 555 timer.

im really sorry im learning by doing with no coding background before.

here it is my code i copy from multiple example and try to understand line by lines

any help would be appreciated many thanks!

#include <LedControl.h>
#include <Bounce2.h>
LedControl lc = LedControl(10, 12, 11, 1);

long tn, deltaT;
int a, b, c, d;
int a1, b1, c1, d1;

int starttimer = 6;        // Start Timer Pin
int starttimer1 = 9;
int finishtimer = 7;            // Finish Timer Pin
int finishtimer1 = 8;

bool statusSwitch1 = false;
bool statusSwitch2 = false;
bool statusSwitch3 = false;
bool statusSwitch4 = false;

Bounce SW1 = Bounce();        // Define Bounce to read StartStop switch
Bounce SW2 = Bounce();        // Define Bounce to read Lapse switch
Bounce SW3 = Bounce();
Bounce SW4 = Bounce();

void setup() {


  pinMode (starttimer, INPUT_PULLUP);
  pinMode (starttimer1, INPUT_PULLUP);
  pinMode (finishtimer, INPUT_PULLUP);
  pinMode (finishtimer1, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance
  SW1.attach(starttimer);   // Sets the pin (Internal Pull-Up)and matches the internal state to that of the pin
  SW1.interval(4);            // Sets the debounce time in milliseconds
  SW2.attach(finishtimer);
  SW2.interval(4);
  SW3.attach(starttimer1);
  SW3.interval(4);
  SW4.attach(finishtimer1);
  SW.interval(4);

  lc.shutdown(0, false);      // The MAX72XX is in power-saving mode on startup, we have to do a wakeup call
  lc.setIntensity(0, 7);      // Set the brightness of display between 0 and 15
  lc.clearDisplay(0);         // Clear the display

  lc.setDigit(0, 7, 0, true);
  lc.setDigit(0, 6, 0, false);
  lc.setDigit(0, 5, 0, true);
  lc.setDigit(0, 4, 0, false);

  lc.setDigit(0, 3, 0, true);
  lc.setDigit(0, 2, 0, false);
  lc.setDigit(0, 1, 0, true);
  lc.setDigit(0, 0, 0, false);

}


void loop() {

  SW1.update();   // Start-Stop
  SW2.update();
  SW3.update();
  SW4.update();

  if (SW1.rose()) {
    statusSwitch1 = !statusSwitch1;
  }
  if (SW2.rose()) {
    statusSwitch2 = !statusSwitch2;
  }
  if (SW3.rose()) {
    statusSwitch3 = !statusSwitch3;
  }
  if (SW4.rose()) {
    statusSwitch4 = !statusSwitch4;
  }

  if (statusSwitch1 == true) { //trigger the timer lane1 to start running

    tn = millis() - deltaT;
    a = tn / 10000;
    b = (tn / 1000) % 10;
    c = (tn / 100 ) % 10;
    d = (tn / 10) % 10;

    lc.setDigit(0, 7, a, false);
    lc.setDigit(0, 6, b, true);
    lc.setDigit(0, 5, c, false);
    lc.setDigit(0, 4, d, false);
  }
  else {

    deltaT = millis() - tn; // freeze timer lane1
    a = tn / 10000;
    b = (tn / 1000) % 10;
    c = (tn / 100 ) % 10;
    d = (tn / 10) % 10;

    lc.setDigit(0, 7, a, false);
    lc.setDigit(0, 6, b, true);
    lc.setDigit(0, 5, c, false);
    lc.setDigit(0, 4, d, false);
  }

  if (statusSwitch3 == true) { //trigger the timer lane2 to start running

    tn = millis() - deltaT;
    a1 = tn / 10000;
    b1 = (tn / 1000) % 10;
    c1 = (tn / 100 ) % 10;
    d1 = (tn / 10) % 10;

    lc.setDigit(0, 3, a1, false);
    lc.setDigit(0, 2, b1, true);
    lc.setDigit(0, 1, c1, false);
    lc.setDigit(0, 0, d1, false);
  }
  else {

    deltaT = millis() - tn;  //freeze timer lane2
    lc.setDigit(0, 3, a1, false);
    lc.setDigit(0, 2, b1, true);
    lc.setDigit(0, 1, c1, false);
    lc.setDigit(0, 0, d1, false);
  }

  if (statusSwitch1 == true && statusSwitch2 == false) { //trigger the 4LED 7 Segment "Lane1" to stop timer

    tn = millis() - deltaT;
    a = tn / 10000;
    b = (tn / 1000) % 10;
    c = (tn / 100 ) % 10;
    d = (tn / 10) % 10;

    lc.setDigit(0, 3, a, false);
    lc.setDigit(0, 2, b, true);
    lc.setDigit(0, 1, c, false);
    lc.setDigit(0, 0, d, false);
  }

  if (statusSwitch3 == true && statusSwitch4 == false) { //trigger the 4 LED 7 Segment "Lane2" to stop timer

    tn = millis() - deltaT;
    a1 = tn / 10000;
    b1 = (tn / 1000) % 10;
    c1 = (tn / 100 ) % 10;
    d1 = (tn / 10) % 10;

    lc.setDigit(0, 7, a1, false);
    lc.setDigit(0, 6, b1, true);
    lc.setDigit(0, 5, c1, false);
    lc.setDigit(0, 4, d1, false);
  }
}

TRIX_TRAX_2_LANE_TIMER.ino (3.98 KB)

Please use the CODE tag for code, not QUOTE. You can edit your post.

You don't need a RTC or a 555. The clock in the Arduino is accurate enough for this task.

The Bounce2 library is useful for mechanical buttons. With an IR sensor there is no bounce so you don't need that unless you're testing with buttons. Then it may make sense to keep using that library, because you changing the code like that would require more testing.

If any of your buttons rise (.rose()) then you flip the state of the corresponding statusSwitchX. So after lane 1 has started, statusSwitch1 is true. So it will always restart. I would have put that start action inside the if() statement so it is only executed once when the car starts.

Then the next time that sensor rises, statusSwitch1 will be changed to false. But doesn't that mean the car just started for the second time?

Then you don't seem to be using deltaT correctly. It never gets assigned a value. In normal C programming, this means that it can be any random value. On the Arduino you can be sure that it starts at zero but it's still wrong to use the variable without assigning a value to it.

The trick is to record the value of millis() when each car starts. Then the elapsed time is just endTimeLane1-startTimeLane1.

MorganS:
Please use the CODE tag for code, not QUOTE. You can edit your post.

You don't need a RTC or a 555. The clock in the Arduino is accurate enough for this task.

The Bounce2 library is useful for mechanical buttons. With an IR sensor there is no bounce so you don't need that unless you're testing with buttons. Then it may make sense to keep using that library, because you changing the code like that would require more testing.

If any of your buttons rise (.rose()) then you flip the state of the corresponding statusSwitchX. So after lane 1 has started, statusSwitch1 is true. So it will always restart. I would have put that start action inside the if() statement so it is only executed once when the car starts.

Then the next time that sensor rises, statusSwitch1 will be changed to false. But doesn't that mean the car just started for the second time?

Then you don't seem to be using deltaT correctly. It never gets assigned a value. In normal C programming, this means that it can be any random value. On the Arduino you can be sure that it starts at zero but it's still wrong to use the variable without assigning a value to it.

The trick is to record the value of millis() when each car starts. Then the elapsed time is just endTimeLane1-startTimeLane1.

im sorry i already edit my post, yes i still use bounce because when i try to translate it to normal "INPUT" not "INPUT PULLUP" i can't run the project corrrectly.

doesnt mean that deltaT is the elapsed time?,so i have to declare endTimeLane1,endTimeLane2 and startTimeLane1,startTimeLane2?

i will try to change my code with your advice today.