Introduction: Automated Timing System

Lots of sports from track to football now use the laser tracking system for timing runners. However, these can cost thousands of dollars for a relatively simple setup. I will try to create my own laser timing system as an alternative.

There are Arduinos at the finish and start points. The runner lines up in front of the first Arduino. When he leaves, the Arduino communicates with the finish line arduino to begin timing. When the runner runs in front of the arduino then it triggers to stop timing and the time shows up on a seven segment display.

Step 1: Casing

I decided to custom design and 3d print the casings for the times. The design was relatively simple, the box was designed to be large enough to accomodate the arduino and a battery pack. The two holes were elevated to be above the ground level so as to avoid interference from the ground. The designs are attached in STL files above.

I then exported the files to MakerBot Print and arranged them so the most surface area was on the bottom (the bottom of the box and the top of the lid). Then after making sure the quality was good, I printed them.

Step 2: Circuit Design

The circuit design is very simple. There are 4 components for the receiver (Ultrasonic sensor, Arduino Uno, Seven Segment DIsplay, and NRF2L01 Transceiver) and 3 components for the transmitter (no Seven Segment Display. I wired these up according to their datasheets and the board layout is shown above.

Step 3: Transmitter Code

#include <SPI.h>
#include <RH_NRF24.h>
const unsigned int TRIG_PIN=2;
const unsigned int ECHO_PIN=3;
const unsigned int BAUD_RATE=9600;
RH_NRF24 nrf24;
void setup() {
 pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  Serial.begin(BAUD_RATE);
  if (!nrf24.init())
    Serial.println("init failed");
  if (!nrf24.setChannel(125))           //set channel to 125
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");
}
void loop() {
 int distance= hit();
      if (distance>3 && distance < 20)
      {
        Serial.print("distance to nearest object:");
        Serial.println(distance);
        Serial.println(" cm");
        Serial.println(" goone");
        go_sequence_one();
      }
  
 delay(100);
}
void go_sequence_one(){
    delay(1000);
    int distance= hit();
    Serial.println(distance);
   if (distance>3 && distance < 20)
      {
           Serial.println(distance);
        Serial.println("GO_One");
        go_sequence_two();
      }
}
void go_sequence_two()
{
 int distance=hit();
  if (distance>3 && distance < 20)
      {
                Serial.println(distance);
        Serial.println("Not Yet");
        go_sequence_two();
      }
   else 
   {
     Serial.println("GOGOGO");
     uint8_t data[] = "GO";
    nrf24.send(data, sizeof(data));
   }
}
int hit(){
   digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  const unsigned long duration= pulseIn(ECHO_PIN, HIGH);  

int distance= duration/29/2; 

return distance; }

The code to start first sets up all variables and the sensor/transceiver. It then checks the distance to see if the runner has already gotten in starting position. If not then it keeps checking until that occurs. It then checks again to see if the runner is still there or if he has left early. If the runner is still in position, then it loops while checking distance until the runner moves, in which case it fires the message to the timer to begin.

Step 4: Receiver Code

#include <SevenSegmentExtended.h>
#include <SevenSegmentFun.h>
#include <SevenSegmentTM1637.h>
// nrf24_server
/*
NRF24L01      Arduino
CE       >     D8
CSN      >     D10
SCK      >     D13
MO       >     D11
MI       >     D12
RO       >     Not used 
GND      >     GND
VCC      >     5V
 */
#include <SPI.h>
#include <RH_NRF24.h>
const byte PIN_CLK = 4; // define CLK pin (any digital pin) const byte PIN_DIO = 5; // define DIO pin (any digital pin) SevenSegmentTM1637 display(PIN_CLK, PIN_DIO);
const int LED = 9;
int timeOUT = 0;
const unsigned int TRIG_PIN=2;
const unsigned int ECHO_PIN=3;
const unsigned int BAUD_RATE=9600;
RH_NRF24 nrf24;
void setup()
{
   display.begin();   
   display.clear();// initializes the display
  display.setBacklight(100);  // set the brightness to 100 %
  delay(1000);                // wait 1000 ms
   pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  Serial.begin(BAUD_RATE);
  if (!nrf24.init())
    Serial.println("init failed");
  if (!nrf24.setChannel(125))           //set channel to 125
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");
}
void loop()
{
  if (nrf24.available())
  {
    uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];   
    uint8_t len = sizeof(buf);
    if (nrf24.recv(buf, &len))             //read message
    {
      Serial.print("got request: ");
      Serial.println((char*)buf);
      begin_time();
    }
  }
 
}
void begin_time()
{
  int distance = hit();
   if (distance>3 && distance < 20){
     display.print(timeOUT);
     Serial.println("TIME IS");
     Serial.println(timeOUT);
    delay(5000);
   }
   else{
    delay(10);
    timeOUT++;
     Serial.println(timeOUT);
     
   begin_time();
      }
}
int hit(){
   digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
 const unsigned long duration= pulseIn(ECHO_PIN, HIGH);
 int distance= duration/29/2;
 return distance;
}

The timer begins when it receives communication from the transceiver. It checks every 10 milliseconds for movement in front of the sensor and if it sees it it halts the timing protocol and displays it on the Seven Segment Display