Arduino based timer

Hello I'm building a track and I need to know how long it takes my robot to finish. On the beginning side of the track there will be a laser on one side and a photo resistor on the other. The same for the end. Obviously I know how to check when the laser line is broken, however, i don't know how to time something and then save it as an integer. Basically I need to turn my Arduino into a stop watch! The time should never exceed 60 sec.

Thanks!

What resolution do you want. Just to the second, or to the 10th of second, or to 1000th second?

To the second should be fine, however, I forgot to mention that there might be more then one robot. For example i would like to save the time for the first and second place robot. Here would be a flow chart…

first line broken - start timer - second line broken - save time to int a - second line broken again - save time to int b -print to serial - restart program.

Ok, just a rough idea.

declare three variables, startTime, finishTimeOne, finishTimeTwo.
eg. long startTime = 0;
These should be long, since we will check/save the milliseconds.

When the start is detected save startTime, eg. startTime= millis();
When the finish line detects a finisher,
if finishTimeOne is still zero, then save millis() to finishTimeOne, else, save it to finishTimeTwo.

Now you have 3 times, in milli seconds. to get seconds subtract the milliseconds saved, and divide by 1000.

Does that make sense?

Thank you so much I will finish up today and post the results!

Thank you so much! Everything works except once it gets to Serial.println("startover"); the program does not move past that. Any ideas?

It would be nice if it would auto reset, however, I can live with that part not working.

Thanks for showing me how to make a "stop watch"!!!

EDIT:

I don't know why but if I restart the serial monitor on my computer it will start to do the program again. I'm starting to think that the program does in fact start over, but serial monitor is having some issue. I never restarted the Arduino just serial monitor.

int long startTime = 0;
int long finishTimeOne= 0;
int long finishTimeTwo = 0;

int s2 = 0; //value of s2
int s1 = 0; // value of s1

byte l =0; //way to move thorough differnt parts of the program

void setup() {
  
   Serial.begin(9600);
delay(1000);
              }
             
             
             
             
 void loop() {
               
               
   while ( l == 1); {   
     
          Serial.println("go");

   s1 = analogRead(A1);
  
  
  if (s1 < 650) 
  {
    startTime= millis();
    delay(500);
    l = 2; // jump to part two
  }
  
                    }
                       
                      
                      

while (l == 2){
  
  s2 = analogRead(A2);

  
  if (s2 < 650 ) 
  {
    
    
     if (finishTimeOne < 5)
    
     {
              finishTimeOne = millis();
                 
                   while (s2 < 650 ) 

                   {
  
                   s2 = analogRead(A2);
  
                   }


  
     }
    
    
    else {
      
        finishTimeTwo= millis();
    
    
    delay (100);
   
    finishTimeOne = finishTimeOne - startTime;
    finishTimeTwo = finishTimeTwo - startTime;
    finishTimeOne = finishTimeOne / 1000;
    finishTimeTwo = finishTimeTwo / 1000;
    
      Serial.println(finishTimeOne);
      Serial.println(finishTimeTwo);

   

     delay(3000);

     Serial.println("startover");
     
      finishTimeOne = 0;
    finishTimeTwo = 0;

     l = 1; // jump back to part one (not working)


      
    }
    
    
  }
  
}
  
}

I don't think the code is really what you want.
while ( l == 1); {will always run, since 1 does equal 1.
while (l == 2){ will never run, since 1 does not ever equal 2.
Am I missing something here?

You are missing something, but it is not your fault! For some reason the font that this forum uses is different then the one on my mac. What you are looking at is lower case "L" = 1. For some reason on this from when you post your code lower case "L's" look like 1's.

I don't know why but if I restart the serial monitor on my computer it will start to do the program again.

Starting serial monitor resets the Arduino, same as pushing the reset button.

Is there any chance that the two robots will pass the finish line overlapping each other, and so only break the line once?

For what you are trying to do with l=1 or l=2, there may be a more structured way of doing it. I don't know what convention professional programmers would use, but here are two possibilities.

boolean started = false;

loop() {
  if (!started) {
    // look for beginning of race conditions
  } else {
    // look for end of race conditions
  }
}

For situations that have more than two logical conditions, a way of handling it might be:

const int RaceNotStarted = 1;
const int RaceInProgress = 2;
const int RaceFinished = 3;
const int PrizesAwarding = 4;
const int GoingHomeNow = 5;

int state = RaceNotStarted;

loop()
  switch (state) {
    case RaceNotStarted:
      // code
      break;
    case RaceInProgress:
      // code
      break;
    case RaceFinished:
      // code
      break;
   etc...
  }
}

Within the code for each case would be conditions for changing the state to another state. So in "raceinprogress" case, you would have logic for detecting the finishing robots, and if that happened, you would set the state to RaceFinished for the next loop.

Ultimately, this is exactly what you are already doing with your "l" variable, but it may be a little more readable and scalable to larger situations.

Thank you so much! That does seem a lot more logical. I will implement that and see if it helps.

When it comes to the robots finishing around the same time i'm not to worried because the lasers are very low to the ground so as soon as the wheels pass it will be able to look for the next robot. If the wheels happen to pass at the same time I will call it a tie as they would have to be extremely close together.

I believe that i put in the code correctly, however, now the program just restarts back to the beginning every few seconds… even when the laser has not been crossed.

int long startTime = 0;
int long finishTimeOne= 0;
int long finishTimeTwo = 0;

int s2 = 0; //value of s2
int s1 = 0; // value of s1

const int RaceNotStarted = 1;
const int RaceInProgress = 2;
const int RaceFinished = 3;


int state = RaceNotStarted;

void setup() {

  Serial.begin(9600);
  delay(1000);
}




void loop() {


  switch (state)  {   

  case RaceNotStarted:

    Serial.println("go");

    s1 = analogRead(A1);


    if (s1 < 650) 
    {
      startTime= millis();
      delay(500);
      break;
    }






  case RaceInProgress:

    s2 = analogRead(A2);


    if (s2 < 650 ) 
    {


      if (finishTimeOne < 5)

      {
        finishTimeOne = millis();

        while (s2 < 650 ) 

        {

          s2 = analogRead(A2);

        }



      }


      else {

        finishTimeTwo= millis();



        break;


      }




    }

    const int RaceFinished = 3;

    delay (100);

    finishTimeOne = finishTimeOne - startTime;
    finishTimeTwo = finishTimeTwo - startTime;
    finishTimeOne = finishTimeOne / 1000;
    finishTimeTwo = finishTimeTwo / 1000;

    Serial.println(finishTimeOne);
    Serial.println(finishTimeTwo);



    delay(3000);

    Serial.println("startover");

    finishTimeOne = 0;
    finishTimeTwo = 0;

    break;

  }
}

Screen Recorded2013-08-09 22_28_29.mov (391 KB)

I have a hard time reading the code. Please use Tools - Auto Format to reformat the code. Thanks

Just another random thought: if you are going to implement state-based code like this, you must be absolutely certain that you can detect situations where reality has "escaped" your cases. For example, if you are in state "raceInProgress" and you are looking for the laser break that indicates robots have finished, if somehow the robots manage to finish without you detecting that event, or without triggering that event, your code will be stuck forever. Reality will go on, leaving your code behind. It's easy to fall into a situation where you think you have all of a state's entry- and exit- conditions covered, and it turns out there is a combination of factors you didn't account for, and reality ends up in a different state than your program thinks it is. The more constrained reality is, the safer it is to rely on trigger conditions that move you from one state to another. The less constrained reality is, the more you have to build general-purpose state detection into your code--in other words, you look at the state of reality, via sensors and other inputs, and make a determination as to what the actual state of reality IS, not what you think it MUST BE based on the triggers you have seen.

I apologize for the confusion, but I meant to give a general concept of how to construct the code, not a compile-correct template that could be dropped straight in. I'm sure there are kinks that need to be worked out. I'll take a look and see if I find anything.

I think I see the problem:

  switch (state)  {   
  case RaceNotStarted:
    Serial.println("go");
    s1 = analogRead(A1);

    if (s1 < 650) 
    {
      startTime= millis();
      delay(500);
      break;
    }

Within each state, you need to have logic to move the program to the next state, once the trigger condition is met. So the trigger condition for starting the race is that s1 < 650, indicating that the laser has been crossed. So you might write:

switch (state)  {   

  case RaceNotStarted:
    Serial.println("go");
    s1 = analogRead(A1);

    if (s1 < 650) 
    {
      startTime= millis();

      state = raceInProgress; // move the program to the next state

      delay(500);
      break;
    }

... what's happening in your code, I believe, is that the robots trigger the starting laser, but then the program just goes back to looking for it again, and never moves on to looking for the next trigger condition.

@ jackwp I updated the code. That tool is really awesome I did not even know that it was there. Thanks!

@ joshuabardwell I did not even start the robots or break the first laser beam! As soon as I plug in the Arduino and start the serial monitor it just spits out what you see in the video.

Great Drew,
If you post the code (formatted), we may be able to notice a problem (maybe not, but we will try). I am about to turn in. so maybe, we talk tomorrow.

Sounds good. Thank you so much!