Stopwatch Project for my Club

Please see my Note at Replay #3

Hi there,

I'm just going to program a stopwatch.

A switch on pin 50 for starting and a push button on pin 51 for stop.

Each time you press the button on pin 50 should run its own time, which then stops at a pressure on the button at pin 51 again.

It is a continuous loop between start and stop.

It should be a time measurement for my slalom kart club.

This works currently, unfortunately, only in part.

I can press the button twice to pin 50 and 2 times the button on pin 51 and then have my 2 times.

But I press twice Pin 50, Pin 51, and then once again pin 50 to start a third time, he does nothing, not even when multiple pressing the button on pin 51

Thanks in advance

Markus1995

Below is the code.

#include <LiquidCrystal.h>

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int backLight   = 10;    // LCD Panel Backlight LED connected to digital pin 10
int lightLevel  = 255;   // Initialise light full on
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor 
  // my [Mark Bramwell's] buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  if (adc_key_in < 50)   return btnRIGHT;  
  if (adc_key_in < 195)  return btnUP; 
  if (adc_key_in < 380)  return btnDOWN; 
  if (adc_key_in < 555)  return btnLEFT; 
  if (adc_key_in < 790)  return btnSELECT;   
  return btnNONE;  // when all others fail, return this...
}

#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 50                // button on pin 50
#define buttonPin51 51              // button on pin 51

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int buttonState51;                    // variable to store button state
int lastButtonState;                // variable to store last button state
int lastButtonState51;                // variable to store last button state
int blinking;                       // condition for blinking - timer is timing
int blinking51;                       // condition for blinking - timer is timing
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long startTime51 ;                    // start time for stop watch51
long elapsedTime ;                  // elapsed time for stop watch
long elapsedTime51 ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time
int fractional51;                     // variable used to store fractional part of time
int start = 0;
int stop1 = 0;
unsigned long interval1 = 10000;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);                // start the LCD library

  pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
  pinMode(buttonPin51, INPUT);       // not really necessary, pins default to INPUT anyway
  digitalWrite(buttonPin, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.
  digitalWrite(buttonPin51, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.
  lcd.print("Bereit");
}

void loop()
{ 
  Zeit1();
  Zeit2(); 
}

//ZEIT 1-----------------------------------------------------------------------------------------------------------------------------------------------

void Zeit1 () { // Zeit 1 

    // check for button press
  buttonState = digitalRead(buttonPin);                   // read the button state and store
  buttonState51 = digitalRead(buttonPin51);

  if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
    // if true then found a new button press while clock is not running - start the clock

    startTime = millis();                                   // store the start time
    blinking = true;                                     // turn on blinking while timing
    delay(50);                                              // short delay to debounce switch
    start++;
    lastButtonState = buttonState;                          // store buttonState in lastButtonState, to compare next time

  }

  else if (buttonState51 == LOW && lastButtonState51 == HIGH && blinking == true){     // check for a high to low transition
    // if true then found a new button press while clock is running - stop the clock and report

    elapsedTime =   millis() - startTime;              // store elapsed time
    blinking = false;                                  // turn off blinking, all done timing
    lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time
    delay(1000);
    stop1++;


    // routine to report elapsed time 
    lcd.setCursor(0,0);            // move cursor to beginning of line "0"
    lcd.print("Zeit 1: ");
    lcd.print( (int)(elapsedTime / 1000L));         // divide by 1000 to convert to seconds - then cast to an int to print

    lcd.print(".");                             // print decimal point

      // use modulo operator to get fractional part of time 
    fractional = (int)(elapsedTime % 1000L);

    // pad in leading zeros - wouldn't it be nice if 
    // Arduino language had a flag for this? :)
    if (fractional == 0)
      lcd.print("000");      // add three zero's
    else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
      lcd.print("00");       // add two zeros
    else if (fractional < 100)
      lcd.print("0");        // add one zero

    lcd.print(fractional);  // print fractional part of time 
  }

  else{
    lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
  }
}

//Zeit 2-----------------------------------------------------------------------------------------------------------------------------------------------

void Zeit2 () { // Zeit 2

    // check for button press
  buttonState = digitalRead(buttonPin);                   // read the button state and store
  buttonState51 = digitalRead(buttonPin51);                   // read the button state and store

  if (buttonState == LOW && lastButtonState == HIGH  &&  blinking51 == false && start % 2 == 1){     // check for a high to low transition
    // if true then found a new button press while clock is not running - start the clock

    startTime51 = millis();                                   // store the start time
    blinking51 = true;                                     // turn on blinking while timing
    delay(5);                                               // short delay to debounce switch
    lastButtonState51 = buttonState51;                          // store buttonState in lastButtonState, to compare next time

  }

  else if (buttonState51 == LOW && lastButtonState51 == HIGH && blinking51 == true && stop1 % 2 == 1){     // check for a high to low transition
    // if true then found a new button press while clock is running - stop the clock and report

    elapsedTime51 =   millis() - startTime51;              // store elapsed time
    blinking51 = false;                                  // turn off blinking, all done timing
    lastButtonState51 = buttonState51;                     // store buttonState in lastButtonState, to compare next time

    // routine to report elapsed time 
    lcd.setCursor(0,2);            // move cursor to beginning of line "2"
    lcd.print("Zeit 2: ");
    lcd.print( (int)(elapsedTime51 / 1000L));            // divide by 1000 to convert to seconds - then cast to an int to print
    lcd.print(".");                                  // print decimal point

      // use modulo operator to get fractional part of time 
    fractional51 = (int)(elapsedTime51 % 1000L);

    // pad in leading zeros - wouldn't it be nice if 
    // Arduino language had a flag for this? :)
    if (fractional51 == 0)
      lcd.print("000");      // add three zero's
    else if (fractional51 < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
      lcd.print("00");       // add two zeros
    else if (fractional51 < 100)
      lcd.print("0");        // add one zero

    lcd.print(fractional51);  // print fractional part of time

  }

  else{
    lastButtonState51 = buttonState51;                         // store buttonState in lastButtonState, to compare next time
  }
}

Some remarks:
First have you seen - http://playground.arduino.cc/Code/StopWatchClass -

long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long startTime51 ;                    // start time for stop watch51
long elapsedTime ;                  // elapsed time for stop watch
long elapsedTime51 ;                  // elapsed time for stop watch

should all be unsigned long as this the datatype millis() returns

from your description I think your state-machine is not resetting right. Think this is because zeit1() and zeit2() are coupled too much code dependency.
I cannot see the problem directly.

debouncing the buttons can be done easier, without delay

  // SCAN BUTTONS 5x PER SECOND
  if (millis() - lastCheck >= 200) 
  {
    b50 = digitalRead(50);
    b51 = digitalRead(51);
    lastCheck = millis();
  }

Thank you,

the Stopwatch class I've seen, but I do not know how I could use them here.

Maybe I just think too complicated.

We usually drive at the same time with 2 karts.

The 2 buttons are the light barriers.

The first kart driving through the first light barrier. The "Stopwatch" begins to count on.

At about half the distance the second kart also runs through the first light barrier. His "stopwatch" begins to count on.

Now comes kart 1 finish (light barrier 2), and it appears his time.

Meanwhile kart 2 is still driving at, Kart 1 moves already get rid of (by photocell 1) and a new era begins for Kart1.

Meanwhile Kart 1 is back on track, Kart 2 arrives at the finish (light barrier 2). and it is the time of Kart 2 is displayed.

Now moves back kart 2 go (light barrier 1), during which kart 1 is still on the track.

And so on

I hope this explanation may help you a bit.

THis assumes that kart2 cannot pass kart1 during the race?

In my kart experience that is a false assumption...

Not at Slalom Kart,

The karts always come in the same order to the finish.

Here is an example obstacle course:

Kart 1 drives off and when it is the second time in P2, runs Kart 2 los.

Cool route :wink:

OK, karts do not pass each other. then it becomes much simpler.

use one pin for both start and stop
use an array for the times.
stripped the blinking and lcd

int buttonPin = 50;
int buttonState;
int lastButtonState = HIGH;

unsigned long times[4];
int idx = 0;


void setup()
{
  Serial.begin(9600);
  Serial.println("ready?");
  pinMode(buttonPin, INPUT_PULLUP); 
}

void loop()
{
  // get times
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH)
  {
    times[idx] = millis();
    idx++;
    lastButtonState = buttonState;
    delay(100); // debounce
  }
  else if (buttonState == HIGH && lastButtonState == LOW)
  {
    lastButtonState = buttonState;
    delay(100); // debounce
  }

  if (idx == 4) 
  {
    Serial.print("KART 1: ");
    Serial.println(times[2] - times[0]);
    Serial.print("KART 2: ");
    Serial.println(times[3] - times[1]);
    idx = 0;
  }
}

Thank you,
we build every week on a new route.

With us, start and stop each a light barrier or a button.

In your sketch you have now indeed only a button.

How can I change this?

it is then also possible to display the time after each kart?

Or if we go 3 times for 3 karts.

Thanks in advance

some changes to have > 2 karts.

assumption is that all karts start before the first finishes

int buttonPin = 50;
int buttonState;
int lastButtonState = HIGH;

#define KARTS 3

unsigned long times[KARTS*2];
int idx = 0;


void setup()
{
  Serial.begin(9600);
  Serial.println("ready?");
  pinMode(buttonPin, INPUT_PULLUP); 
}

void loop()
{
  // get times
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH)
  {
    times[idx] = millis();
    idx++;
    lastButtonState = buttonState;
    delay(100); // debounce
  }
  else if (buttonState == HIGH && lastButtonState == LOW)
  {
    lastButtonState = buttonState;
    delay(100); // debounce
  }

  if (idx > KARTS)
  {
    Serial.print("KART");
    Serial.print(idx - KARTS);
    Serial.print(": ");
    Serial.println(times[idx - 1] - times[idx - KARTS - 1]);
  }
  if (idx == KARTS*2) 
  {
    idx = 0;
  }
}

depending on the sensor you can connect two triggers to 1 pin
or you modify the code so that a second pin does the same as the first :wink:

Wow

Thank you :slight_smile:

I have modify your first code:

int buttonPin = 50;
int buttonState;
int lastButtonState = HIGH;

unsigned long times[4];
int idx = 0;


void setup()
{
  Serial.begin(9600);
  Serial.println("Bereit?");
  pinMode(buttonPin, INPUT_PULLUP); 
}

void loop()
{
  // get times
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH)
  {
    times[idx] = millis();
    idx++;
    lastButtonState = buttonState;
    delay(100);                                               // debounce
  }
  else if (buttonState == HIGH && lastButtonState == LOW)
  {
    lastButtonState = buttonState;
    delay(100);                                              // debounce
  }

  if (idx == 3) 
  {
    Serial.print("KART 1: ");
    Serial.println(times[2] - times[0]);
  }

  if (idx == 4) 
  {
    Serial.print("KART 2: ");
    Serial.println(times[3] - times[1]);
    idx = 0;
  }
}

Now almost everything works.

Only I would like to display the time after each kart as we always 5 rounds in a pub (sometimes 6 or 7) take 2 karts and then change the driver.