Arduino Based Lap Timer? Please Help...

I'm attempting to make this project. https://www.instructables.com/id/Arduino-Based-Lap-Timer/

Here is the code from that.

#include <Wire.h>
#include <EEPROM.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include <SoftwareSerial.h>

SoftwareSerial Thermal(3, 2);
Adafruit_7segment matrixGreen = Adafruit_7segment();
Adafruit_7segment matrixRed = Adafruit_7segment();

int photocellPin = 7;     
int photocellReading;  
int photocellBreak = 0;
int lapCount = 0;
int lapTime = 0;
int lapTimes[10];
int FastestLap = 6000;
int minLaptime = 1000;
int clockSync = 7600;
int totalTime = 0;
int TotalLaps = 3;

int heatTime = 80;
int heatInterval = 255;
char printDensity = 15; 
char printBreakTime = 15;

float timeprint;

void setup() {
  Serial.begin(9600);
  pinMode(A1, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  
  matrixGreen.begin(0x70);  // no address soldered
  matrixRed.begin(0x71);    // A1 soldered

  matrixGreen.print(10000, DEC);
  matrixRed.print(10000, DEC);

  matrixGreen.writeDisplay();
  matrixRed.writeDisplay();
  //EEPROM.put ( 0, FastestLap);

  delay(1000);

  Thermal.begin(19200); // to write to our new printer
  initPrinter();

}

void loop() {


  DisplayText(0);
 
  int Whattodo = 0;

   Whattodo = Button();
   Serial.println(Whattodo, DEC);
   if (Whattodo == 1) {
      LapTime(TotalLaps);
     }
   if (Whattodo == 2) {
       Serial.println("Set Laps");
      SetLaps(); 
      }

}

void SetLaps() {
 int l;
 int la;
 int b;
 
 DisplayText(1);

 la = analogRead(A2);
 b = analogRead(A1);
 
 while (b < 200 or b > 300) {
  l = map(la,1023,0,1,9);
  
  matrixRed.print(l, DEC);
  matrixRed.writeDisplay();

  delay(10);
  la = analogRead(A2);
  b = analogRead(A1); 
 }

 TotalLaps = l;
}


void DisplayText(int T) {
  // 1 = Laps

  if (T==0) {
   matrixGreen.writeDigitRaw(0,B01000000);
   matrixGreen.writeDigitRaw(1,B01000000);
   matrixGreen.writeDigitRaw(3,B01000000);
   matrixGreen.writeDigitRaw(4,B01000000);
   matrixGreen.writeDisplay();

   matrixRed.writeDigitRaw(0,B01000000);
   matrixRed.writeDigitRaw(1,B01000000);
   matrixRed.writeDigitRaw(3,B01000000);
   matrixRed.writeDigitRaw(4,B01000000);
   matrixRed.writeDisplay();
  }
   
  
  if (T ==1) {
   matrixGreen.writeDigitRaw(0,B00111000);
   matrixGreen.writeDigitRaw(1,B01110111);
   matrixGreen.writeDigitRaw(3,B01110011);
   matrixGreen.writeDigitRaw(4,B01101101);
   matrixGreen.writeDisplay();
  }
  
  
}

int Button() {

  int select = 0;
  
  int b = analogRead(A1);
  while (b > 900) {
   b = analogRead(A1);
  }
  
  if (b > 400 and b < 500) {
    select = 1;
   }
  if (b > 300 and b < 400) {
    select = 2;
   }
  if (b > 200 and b < 300) {
    select = 3; 
   }
  

  return select;
  
}

void initPrinter()
{
 //Modify the print speed and heat
 Thermal.write(27);
 Thermal.write(55);
 Thermal.write(7); //Default 64 dots = 8*('7'+1)
 Thermal.write(heatTime); //Default 80 or 800us
 Thermal.write(heatInterval); //Default 2 or 20us
 //Modify the print density and timeout
 Thermal.write(18);
 Thermal.write(35);
 int printSetting = (printDensity<<4) | printBreakTime;
 Thermal.write(printSetting); //Combination of printDensity and printBreakTime
 
}

void LapTime(int Laps){
 
  RaceStatus(0);
  photocellReading = 0;
  lapTime = 0;
  lapCount = 0;
  
  photocellReading = digitalRead(photocellPin);
  while (photocellReading == photocellBreak  ) {
    photocellReading = analogRead(photocellPin);
    if (analogRead(A1) >  200 and analogRead(A1) < 300) { 
       Serial.println("Back to menu");
      return; 
      }
  }
  
  matrixGreen.print((Laps), DEC);
  matrixGreen.drawColon(false);
  matrixRed.print(0, DEC);
  matrixRed.drawColon(true);
  matrixGreen.writeDisplay();
  matrixRed.writeDisplay();

  delay(1000);
  
  for (int x=0; x<10; x++) { lapTimes[x] = 0; }
  
  while (photocellReading != photocellBreak) {  // wait for start of Race 
    photocellReading = digitalRead(photocellPin);
    if (analogRead(A1) >  200 and analogRead(A1) < 300) { 
       Serial.println("Back to menu");
      return; 
      }
  }
  
  // Start LapTiming!!!

  while (lapCount < Laps) {

  matrixGreen.print((Laps - lapCount - 1), DEC);
  matrixGreen.drawColon(false);
  matrixGreen.writeDisplay();
  
  while (photocellReading != photocellBreak or lapTime < minLaptime ) {
    delayMicroseconds(clockSync);
    lapTime = lapTime+1;
    matrixRed.print(lapTime, DEC);
    matrixRed.drawColon(true);
    matrixRed.writeDisplay();
    photocellReading = digitalRead(photocellPin);
    if (analogRead(A1) >  200 and analogRead(A1) < 300) { 
       Serial.println("Back to menu");
      return; 
      }
   }

   EEPROM.get(0, FastestLap);
   if (lapTime < FastestLap) {
     EEPROM.put ( 0, lapTime);
               
   }
   lapTimes[lapCount] = lapTime; 
   lapCount++;
   lapTime = 0;
  }

  

  Thermal.println("Crazy Kart Race Results! ");
  Thermal.println("=========================");
  totalTime = 0;
  for (int l=0; l<Laps; l++){
    Thermal.print("Lap ");
    Thermal.print(l +1);
    Thermal.print(": ");
    totalTime = totalTime + lapTimes[l];
    timeprint = (float)lapTimes[l]/100;
    Thermal.print(timeprint,2);
    Thermal.println(" seconds");
  }
  Thermal.write(10);
  Thermal.print("Total: ");
  Thermal.println(TimeFormat(totalTime));
  Thermal.write(10);
  Thermal.write(10);

   
}


String TimeFormat(int t) {

  int millisec = t % 100;
  int tseconds = t /100;
  int tminutes = tseconds / 60;
  int seconds = tseconds % 60;

  String timestring = "";
  
  if (tminutes == 0) {
    timestring = String(seconds,DEC) + "." + String(millisec, DEC) + " Seconds";
  }
  if (tminutes == 1) {
    timestring = String(tminutes,DEC) + " Minute " + String(seconds,DEC) + "." + String(millisec, DEC) + " Seconds";
  }
  if (tminutes > 1) {
    timestring = String(tminutes,DEC) + " Minutes " + String(seconds,DEC) + "." + String(millisec, DEC) + " Seconds";
  }
  
  return timestring;
}


void RaceStatus(int Status) {
 if (Status == 0) {
  matrixGreen.print(10000, DEC);
  matrixRed.print(10000, DEC);
  matrixGreen.writeDisplay();
  matrixRed.writeDisplay();
  }

 if (Status == 1) {
  EEPROM.get(0, FastestLap);
  matrixGreen.print(FastestLap, DEC);
  matrixGreen.drawColon(true);
  matrixRed.print(0, DEC);
  matrixGreen.writeDisplay();
  matrixRed.writeDisplay();
  }

  
}

I have a E3F-5DN1 NPN NO through beam sensor and the Arduino Uno. I'd like to bench test the concept before I spend too much money on this.

I've been looking for a simple example to connect the Sensor to the Uno and monitor the times through the serial monitor.
If the code above was modified to use Serial.println and accept the serial input to set and reset the race options I could test this much easier.
Does anyone have an example like that?

How is sensor connected to UNO?

Hi JCA34F
I'm connecting it however the sketch is written. In the example code it's connected to pin 7.
I found another example see here.
That sketch uses pin 8 and outputs to the serial monitor the count of the number of times the beam is broken.

So basically the Sensor signal wire will be connected to a digital input pin on the UNO.

Hopefully this answers your question. Let me know if you need additional info.

Attached is my bench setup. It might be hard to see but know that all the connections are the same as in the script and as seen here.

I don't have the LCD Displays or Thermal Printer.
The primary thing I need help with is modifying the sketch so it sends all data to the serial monitor and not the LCDs or Printer.

Thanks again for all the help.

Confirm that the sensor/transmitter needs six volts to operate. If so, a 10K+2K voltage divider will give you a five volt signal to the Arduino input. You must do this because the Arduino inputs will die if you apply six volts. If using a different supply voltage for the sensors the resistor values will change.

An image search of the part number should turn up a wiring/connection diagram.

Hi Dougp

Thanks for reminding me I had forgotten the max input voltage was 5 volts.
I am using a 12v Lipo battery to supply power to the photoelectric switch. Thankfully I don't think I've killed any inputs. With 12v as my source I believe I need 10k+6.8k voltage divider correct?
I've used a voltage divider before but I forget exactly how I had it connected.
I'm doing something wrong because when I check the voltage on the load side I still see 12v even after I pass it through my 10k+6.8k resisters.

Any Idea how I can fix the code to allow me to use the serial monitor instead of the LCD displays and printer?

Thanks for the info.

20200910_192205sml.jpg

Hi Doug

I figured out what I was doing wrong see attached image. I'm now only sending 4.7v to pin 7.
Thanks again for reminding me of that.

Any help with the code would be greatly appreciated.

Hi All

I found a sketch that allows me to test the stopwatch function using only the serial monitor.
Here is the code.

#include <Bounce2.h>

const byte ledPin = 13;

const byte startButton = 2;
// Instantiate a Bounce object
Bounce startDebouncer1 = Bounce(); 

const byte resetButton = 3;
// Instantiate another Bounce object
Bounce resetDebouncer2 = Bounce();  

void setup() {  
  pinMode(startButton, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance :
  startDebouncer1.attach(startButton);
  startDebouncer1.interval(5); // interval in ms
    
  pinMode(resetButton, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance :
  resetDebouncer2.attach(resetButton);
  resetDebouncer2.interval(5); // interval in ms
  
  pinMode(ledPin, OUTPUT);

  Serial.begin(9600);

  Serial.println("StopWatch using Arduino Uno");
  Serial.println("Press Following Switches:- ");
  Serial.println("Black Switch for Start/Stop");
  Serial.println("Red Switch for Reset");
}

bool startState = LOW;
bool resetState = LOW;

unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;

void loop() {
  // Update the Bounce instances :
  startDebouncer1.update();

   if ( startDebouncer1.fell() ) {     // Call code if button transitions from HIGH to LOW
     startState = !startState;         // Toggle start button state
     startMillis = millis();
   }

  if (startState)
  {
    currentMillis = millis();
    elapsedMillis = (currentMillis - startMillis);
 
    Serial.print("elapsedMillis: ");
    Serial.print(elapsedMillis);
    Serial.println("");
    
    unsigned long durMS = (elapsedMillis%1000);       //Milliseconds
    unsigned long durSS = (elapsedMillis/1000)%60;    //Seconds
    unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
    unsigned long durHH = (elapsedMillis/(3600000));  //Hours
    durHH = durHH % 24; 
    
    Serial.print("Time: ");
    Serial.print(durHH);
    Serial.print(" : ");
    Serial.print(durMM);
    Serial.print(" : ");
    Serial.print(durSS);
    Serial.print(" : ");
    Serial.print(durMS);
    Serial.println("");
    
    String durMilliSec = timeMillis(durHH, durMM, durSS,durMS);
  
    Serial.println("******************************");
    Serial.println("");
    
    delay(150);
  }
  
  resetDebouncer2.update();

  if (resetDebouncer2.fell())
  {
    resetState = HIGH;
  }

  if (resetState)
  {
 
    Serial.println("StopWatch using Arduino Nano");
    Serial.println("Press Following Switches:- ");
    Serial.println("Black Switch for Start/Stop");
    Serial.println("Red Switch for Reset");
    Serial.println("");

    delay(100);
    
    resetState = LOW;
  }
     
}

String timeMillis(unsigned long Hourtime,unsigned long Mintime,unsigned long Sectime,unsigned long MStime)
{
  String dataTemp = "";

  if (Hourtime < 10)
  {
    dataTemp = dataTemp + "0" + String(Hourtime)+ "h:";
  }
  else{
    dataTemp = dataTemp + String(Hourtime)+ "h:";
  }
  
  if (Mintime < 10)
  {
    dataTemp = dataTemp + "0" + String(Mintime)+ "m:";
  }
  else{
    dataTemp = dataTemp + String(Mintime)+ "m:";
  }
  
  if (Sectime < 10)
  {
    dataTemp = dataTemp + "0" + String(Sectime)+ "s:";
  }
  else{
    dataTemp = dataTemp + String(Sectime)+ "s:";
  }
  
  dataTemp = dataTemp + String(MStime);

  Serial.print("String Time: ");
  Serial.println(dataTemp);
  
  return dataTemp;
}

The only problem I have now is this sketch isn't working with my switch.
I assumed it was because of this line bool startState = LOW; but even when I changed it to high it doesn't start and stop with my photo sensor.
I also noticed I had to hold the button for the stop to work and I don't think that will work because the line is broken for such a short time.

Any idea how I can get this working?

Friends

I'm still hoping I can find someone to help me bench test this project without spending 100 dollars or more.
I'm currently working to get my Through Beam Switch to work with the sketch seen here.

#include <Bounce2.h>

const byte ledPin = 13;

const byte startButton = 2;
// Instantiate a Bounce object
Bounce startDebouncer1 = Bounce(); 

const byte resetButton = 3;
// Instantiate another Bounce object
Bounce resetDebouncer2 = Bounce();  

void setup() {  
  pinMode(startButton, INPUT);
  // After setting up the button, setup the Bounce instance :
  startDebouncer1.attach(startButton);
  startDebouncer1.interval(5); // interval in ms
    
  pinMode(resetButton, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance :
  resetDebouncer2.attach(resetButton);
  resetDebouncer2.interval(5); // interval in ms
  
  pinMode(ledPin, OUTPUT);

  Serial.begin(9600);

  Serial.println("StopWatch using Arduino Uno");
  Serial.println("Press Following Switches:- ");
  Serial.println("Black Switch for Start/Stop");
  Serial.println("Red Switch for Reset");
}

bool startState = HIGH;
bool resetState = LOW;

unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;

void loop() {
  // Update the Bounce instances :
  startDebouncer1.update();

   if ( startDebouncer1.fell() ) {     // Call code if button transitions from HIGH to LOW
     startState = !startState;         // Toggle start button state
     startMillis = millis();
   }

  if (startState)
  {
    currentMillis = millis();
    elapsedMillis = (currentMillis - startMillis);
 
    Serial.print("elapsedMillis: ");
    Serial.print(elapsedMillis);
    Serial.println("");
    
    unsigned long durMS = (elapsedMillis%1000);       //Milliseconds
    unsigned long durSS = (elapsedMillis/1000)%60;    //Seconds
    unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
    unsigned long durHH = (elapsedMillis/(3600000));  //Hours
    durHH = durHH % 24; 
    
    Serial.print("Time: ");
    Serial.print(durHH);
    Serial.print(" : ");
    Serial.print(durMM);
    Serial.print(" : ");
    Serial.print(durSS);
    Serial.print(" : ");
    Serial.print(durMS);
    Serial.println("");
    
    String durMilliSec = timeMillis(durHH, durMM, durSS,durMS);
  
    Serial.println("******************************");
    Serial.println("");
    
    delay(150);
  }
  
  resetDebouncer2.update();

  if (resetDebouncer2.fell())
  {
    resetState = HIGH;
  }

  if (resetState)
  {
 
    Serial.println("StopWatch using Arduino Nano");
    Serial.println("Press Following Switches:- ");
    Serial.println("Black Switch for Start/Stop");
    Serial.println("Red Switch for Reset");
    Serial.println("");

    delay(100);
    
    resetState = LOW;
  }
     
}

String timeMillis(unsigned long Hourtime,unsigned long Mintime,unsigned long Sectime,unsigned long MStime)
{
  String dataTemp = "";

  if (Hourtime < 10)
  {
    dataTemp = dataTemp + "0" + String(Hourtime)+ "h:";
  }
  else{
    dataTemp = dataTemp + String(Hourtime)+ "h:";
  }
  
  if (Mintime < 10)
  {
    dataTemp = dataTemp + "0" + String(Mintime)+ "m:";
  }
  else{
    dataTemp = dataTemp + String(Mintime)+ "m:";
  }
  
  if (Sectime < 10)
  {
    dataTemp = dataTemp + "0" + String(Sectime)+ "s:";
  }
  else{
    dataTemp = dataTemp + String(Sectime)+ "s:";
  }
  
  dataTemp = dataTemp + String(MStime);

  Serial.print("String Time: ");
  Serial.println(dataTemp);
  
  return dataTemp;
}

My Photoelectric switch is normally open. When closed by breaking the beam it provides +4.7v to pin2 by way of a voltage divider.
With that in mind shouldn't the code be pinMode(startButton, INPUT_PULLDOWN);
So the pin is normally being pulled low till the switch is pressed?
I know the UNO doesn't support INPUT_PULLDOWN so should pinMode(startButton, INPUT) work?