No announcement yet.

Arduino lap timer project

  • Filter
  • Time
  • Show
Clear All
new posts

  • Arduino lap timer project

    Some of you may have seen my lap timer in the Little Mobara routed track that I have made. I wanted to more fully write up what I have done for this and to update this as I keep working to improve it with the aim to perhaps help others to build their own too. I had found hints of previous timers people had done, but not found anything that was still available with enough detail to build one. Hopefully this will bridge the gap for anyone wanting to build.

    So, why Arduino lap timer? I wanted to have a cheap timer for SLOP tracks and similar. Something that could be modified to suit the individual track and be reliable. Arduino looks to provide a good platform for taking hardware readings and performing simple processing of data and hook up to different outputs for a very low price. The language it uses is simple and small, enabling someone like me who has not done any significant programming for over 20 years, to pick up quite quickly.

    So the core unit is Arduino. The sensor I am aware may change as I try different types, and so this is treated separately as an individual unit to be plugged in and swapped out as needed. Similarly for the output display I have treated as a separate unit as from a learning standpoint I wanted to keep it simple, but leave open the possibility to include a more complex display later if needed.

    I did not want to use a light bridge for my application, or dead strips, reed switches etc, although may come to them later. But instead opted for something that would be discrete with minimal interuption on the track. So have chosen a photo interupter switch. This basically works the same as a light bridge where you have a light source and a light sensor, and you trigger an event when something comes between the source and the sensor. Just with the switch this is in one small unit with the gap between the 2 being 4.2mm on the particular unit I chose. The unit I have used is a Uxcell HY860D that costs about $7 for a pack of 10 on Amazon. Here it is mounted on a small plastic base for fitting to the track.

    For this you need a +5v line to the Anode side of the LED (indicated by the symbol on top of the case, and +5v to the sensor side which on this will be the leg diagonally opposite the LED Anode. You need a ground wire to the Cathode side of the LED, and then the final leg on the sensor side is your signal return for the Arduino input.

    As you can combine the 2 +5v wires, you will only need 3 pins connecting this to the Arduino. +5v, Ground, and Signal. Note that to restrict the current to the LED you will need to use a resister to stop it burning out. a 330 ohm resistor to the LED will be fine for this. I put mine directly on the Anode leg of the LED so that this forms part of the cable and does not sit on the board for the Arduino. This makes it simple if you change the type of sensor you use later, all you really need is to provide power to the sensor and a signal to read for the return.

    Next for the display for simplicity I chose an LCD unit for 2 rows of 16 characters. This gives enough space for displaying timing, is very common and cheap with prices around $8. Also as it is widely used you can find alot of sample scripts and projects that use them, and so good start points for programming as you can just copy/paste alot of the code. There are a couple of different types, you have a basic display that connects via 16 pins, and another that has a second board attached to it (serial interface) with just 4 pins. I would highly recommend for simplicity getting the one with 4 pins to make the cabling easier. The pins on this are +5v, Ground, and then 2 cables for the signal. You can search for IIC/I2C/TWI 1602 on Amazon or any other supplier and find a selection.

    Here is the display on my test setup.

    The Arduino unit itself then sits on a board for convenience for connectivity to the display and sensor, and to also house a single variable resistor for minor adjustments to the sensor signal, and also a buzzer to make an audible noise on detecting a lap. The picture above shows me using an Arduino Uno for the development, but in the application itself I use a Arduino Mini Pro for the smaller form. No code changes are needed, just make sure you select the right board from the Arduino IDE when sending to the device.

    A small note on the Arduino unit chosen. I have used a 5v device at 16Mhz. 5v because alot of components such as the LED's are at 5v and wanted to keep a simple common voltage. 16Mhz is currently I think the fastest device, and as I am timing to 1/1000th of a second, it is important to ensure the device will function at those speeds. You can get these for about $3

    Here is the schematic for the board the arduino mounts to.

    U1 = Arduino Mini Pro
    U2 = 2 pin connector for signal to LCD display
    U3 = Input power to the Arduino (+5v and ground)
    U4 = Power output for the LCD display
    J1 = 3 pin connector for sensor cable
    SP1 = simple buzzer speaker
    R1 = 1 mega ohm variable resistor

    A note about the pins used. The sensor signal comes to pin A0 on the Arduino. This is because we are reading an analogue signal that should have a value between 0 and 1024. The variable resistor allows to tune this signal to ensure we get a reading of over 1000 with nothing blocking the sensor. The value at which the lap is detected can then be set in the code.

    The speaker connectors to digital pin 8 as we are just generating a digital tone for lap detection.

    The display gets connected to pins A4 and A5 because they were the ones used in the code I copied and they work well

    So electrically speaking this is very simple. You can easily wire this up on a little breadboard in a very short time. I did this on an Arduino starter kit first, then transferred to a breadboard with soldered wires, and then later went to having a PCB made to clean it up and ease of changing connections for display and sensors.

    Will post more on the code I have written and some of my other findings later. If anyone wants the code I have used in order to have the above as a working timer, let me know and I will email it to you.

  • #2
    A note regarding the sensor used. When testing on the bench with a script that just reads the sensor values, I would typically see a reading of 1012 in a normal state, and this would drop to 30 when using a Carrera guide to interrupt the beam. You can completely block the light above the sensor, or shine a light onto it and not change the readings. They will only change when something actually breaks the beam.

    So when setting up the threshold in my code for when a lap was detected I had set this as 600 to allow for small variances in the readings and then only trigger when a large drop was detected. When fitted into the track I got varied results. Some cars looked good to trigger the lap timer, others would miss occasionally, others quite frequently. So something was behaving differently in practice than what was being seen on the test bench. I suspected car setup and the guide flags so I built a little test unit.

    On here I could also see the profile and measure the depth the guide sat in the groove as I knew the slot-it and scalextric guides were smaller than the Carrera. But on comparison this did not appear to make much difference as the cars themselves also sat a little lower and evened things out.

    Then onto this test unit I then installed the sensor and tried various cars over it. What I saw was that instead of a drop of over 900 on the readings, I would see only 100-200, and in some cases just 30-40. A big difference from the ideal I had based this on. When testing initially I had used the entore depth of the guide to break the beam, which in reality is not the case.

    To resolve this I then tested another sensor but this time mounting it so the top of the sensor was level with the top of the braid instead of underneath it. With this small difference in height the drop in sensor value then consistently exceeds 500. Which while still not the optimum, does give a much more solid trigger than before, this could probably be increased more if it sits a little proud to the track, but would then chance hitting some cars. I decided not to do this yet as the readings I get are so far very reliable.

    During this investigation I also had modified the timer code a little to help in troubleshooting by introducing a readout of the sensor value to the track display. Just a couple of lines extra, but the impact was that it suddenly started missing laps about 10% of the time, not good.

    So I got one of my cameras with a high speed recording function for 1000 fps and did some more tests.

    So after some extensive testing I found with the sensor mounted underneath the braid, and an event passing the actual sensor of less than .005 seconds, it was possible for the event to fall between 2 polling events to check the sensor. Removing my lines of code for troubleshooting, and mounting the sensor level with the top of the braid, this does not occur now except on one car which I believe to have a bad setup and excessive vibration on the track.

    Why is this important? Because while I have no issues really with the current setup, it does suggest it would be possible with sufficient speed to miss recording a lap. perhaps not so much on a SLOP track, but more so if you had a bigger track with the sensor on a longer straight, and using slot-it cars with the smaller guide etc. With Carrera guides I don't think an issue, as with the larger blade the event for passing the sensor is much longer and you would need a significant speed increase to see the same as a slot-it car.

    A couple of possibilities to eliminate this.

    Gap on current sensor is 4.2mm, replace this with one with a smaller gap - I have just got some with 3.2mm gap and will test soon.

    Change the code. What I currently use is a small loop to read the value at the sensor. If under the threshold for lap detection, then call a routine for lap detected, otherwise loop around and check the sensor again. While this is fairly minimal, it is not the most efficient way to do this. The best way is to use a hardware interrupt. Arduino has 2 pins that can be assigned to this task. You do not need to code to check these pins, just assign a function to perform if an event occurs on them. Regardless of what the arduino is doing, it will then stop to execute this function whenever it detects an event. This is something I need to work on and test further.

    You could eliminate this entirely by use of a light bridge as you are then triggering for the entire duration of a car passing a certain point on the track instead of just the guide blade passing a certain point in the track. For now though I will continue to try and make the intrack sensor as reliable as possible.


    • #3
      Additional note on the previous post. With regards to the red guide flags, when testing these I found that they do cause a reading from the sensor. However the reading is a drop in value of between 5-10 points. So while you could set the trigger fine enough to detect this, in the real world application I found this to be too fine and you start to get ghost laps. You would need to ensure power was very stable and the sensor and arduino board etc was completely shielded to try and eliminate the smallest possible noise that could cause a similar disruption in the reading. I think better to use regular black guide flags or look for a sensor other than infra-red.

      The code I have written/copied/butchered is below. Not the best in the world, but functional and I hope easy enough for someone to read and pick up as a start point for their own project. This records laps, laptime to hundredths of a second and best time in milliseconds. Would be easy enough to modify for a limited number of laps to race, total race time etc. I would avoid adding anything else into "loop" as it will increase the window into which it is possible to miss laps, of course unless you use an interrupt. You would need to download the supporting libraries from the Arduino website in order to compile this and upload to your board.

      // required section for 16x2 LCD display
      #include "pitches.h" // this refers to the tab used for generating the tones used to mark laps and best lap
      #include <Wire.h>
      #include <LCD.h>
      #include <LiquidCrystal_I2C.h>

      #define I2C_ADDR 0x27 // <<----- LCD Address. Find it from I2C Scanner
      #define BACKLIGHT_PIN 3
      #define En_pin 2
      #define Rw_pin 1
      #define Rs_pin 0
      #define D4_pin 4
      #define D5_pin 5
      #define D6_pin 6
      #define D7_pin 7
      LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6 _pin,D7_pin);

      // End of LCD spcific setup

      int ruptPin = 0; // select the input pin for the interrupter
      //used pin 2 for digital read and pin 0 for analog read
      unsigned long start, finished, elapsed, last, full, now, best;
      int lap=0;
      // int thresh=1000; // set the threshold for trigger. 100-1000 higher for bright environment
      // note that sensor should normally be around 1012 if LED is working
      int thresh=800;
      int minimum=1200; //define minimum lap time in milli seconds

      void setup()
      Serial.begin(9600); // set up Serial library at 9600 bps
      lcd.begin (16,2); // <<----- this for a 16x2 LCD display
      lcd.setBacklight(HIGH);// Switch on the backlight
      // lcd.setBacklight(LOW);// Switch off the backlight

      // August modification to display track name and threshold values at startup
      lcd.home (); // go home
      lcd.setCursor (0,0);
      lcd.print (" Little Mobara");
      // End of August modification

      void displayResult()
      float s;
      lcd.setCursor (0,1);
      lcd.print (" "); // this blanks the previous time

      // as milliseconds is always counting since device switched on
      // the lap time is always the current time in milliseconds minus what the previous end of lap time was

      if (lap==2) // this is for setting the first lap time as best lap initially
      tone(8, NOTE_C5, 128);
      tone(8, NOTE_A4, 128);

      if (elapsed<best) // checks if the lap time is less than previous best time
      best=elapsed; // if it is then set new best time and play 2 tones
      tone(8, NOTE_C5, 128);
      tone(8, NOTE_A4, 128);
      tone(8, NOTE_G4, 128); // if not new best time then just beep

      // now display the lap counts, last lap and best lap times

      lcd.home (); // go home
      lcd.setCursor (0,0);
      lcd.print ("Lap Last Best");
      lcd.setCursor (0,1);
      lcd.print (lap-1);
      lcd.setCursor (5,1);
      lcd.print(" ");
      lcd.setCursor (5,1);
      lcd.print (s);
      lcd.setCursor (11,1);
      lcd.print(" ");
      lcd.setCursor (11,1);
      lcd.print (best);
      // lcd.setCursor (6,1);
      // lcd.print (ms);

      // This not currently needed as no lap limit

      // if (lap==11)
      // {
      // Serial.print("Total time: ");
      // elapsed=now-start;
      // Serial.print("Best Lap: ");
      // }

      void lapdetected()
      // increment lap count
      delay(23);// for debounce

      // the loop routine runs over and over again forever:
      void loop()
      int sensorValue = analogRead(ruptPin); // read the value from the sensor
      if (sensorValue<thresh&lap>0) //all laps except first lap
      // last=now;

      if (sensorValue<thresh&lap==0) // setting up start time if first lap
      lcd.setCursor (0,1);
      lcd.print ("Race Started");
      tone(8, NOTE_GS6, 128);


      • #4
        You should be aware that some guide flags are nearly transparent to IR light and cars that use those may not count properly. A quick fix for the problem is to paint the guide flag with Magic Marker. That will wear off sooner or later and the problem will return. A better solution, besides changing guide flags, is to use a Dremel with the large sanding drum to make a slight recess in the guide flag that can be filled with Magic Marker so it won't wear off.
        One of our tracks had your type of sensors and we did not like fooling around with the guide flags, so when the track was replaced the new one had dead strips.


        • #5
          Yes, for this particular sensor the red guide flags only affect the signal by 3%. Even if I narrow the gap and have the sensor perfect to the top of the braid, I don't think that would improve enough to be able to remove the false lap detections. I think for the red guides in this configuration you would need to look more at a different wave length for the light that moved closer to visible light. But that should be easy enough to do once a suitable sensor is found, just swap the sensor out and everything else stays the same.

          The new sensors I just got in are a different form factor, but still the 940nm LED's. Although it does occur to me that this is basically a normal IR LED sitting in a plastic housing opposite the sensor. They are not electrically connected. It should be possible to just swap out the IR LED with another one to make a custom sensor and see what the readings come out as.

          Anyways, just a cheap timer for slop tracks etc. For serious racing I would think light bridge is a better option as you have a much larger target triggering the lap counting.


          • #6
            Good information. I have been looking for information on using either Arduino or Raspberry Pi micro processors for creating timers for a drag strip as well as lap timers for other types of tracks.


            • #7
              Analog read has a read time of 100 microseconds so you should be getting about 10000 reads per second. This should be plenty for your needs, I'm sure someone with better maths than me can work out how quick a car would need to be going to miss a read.

              You can optimize your loop code, by having just 1 if statement I.e.

              if (sensorValue<thresh)
              If (lap==0)

              My counter uses the hw interrupts because for more than one lane the slow update of the LCD means you would miss the other lane. I also use digital reads rather than analog (since interrupt pins are digital only). I then adjust the intensity of the led emitter with a resistor, or block part of the sensor off with insulation tape and it never misses a guide, I've used black, red and white with absolutely no problem once setup correctly, guides tested include, nsr, msc, scalextric, ninco.

              My 1 or 2 lane counter is detailed @


              • #8
                That mate looks awesome. I can't believe I had not stumbled into that while searching and working on my project. Even using pretty much the same hardware, the time I could have saved myself. But I have learned a lot and had fun doing so.

                I had not known of the interrupts when I started, and was just playing with them using a switch for testing before modifying what I have done. My next pcb already has a new connector for pin 2 to use interrupts and also another connector for seven segment led displays. Was aiming to use one board for multiple sensor types and displays and just upload the necessary script to it.

                Looking forward to getting home today so I can take a proper look at your code and learn more. Had not even thought of 2 lanes at the moment. My next thoughts were about selecting either time/lap races and being able to change the duration/laps. But for that I was looking at one of the little touch screens for the interface, so a while off yet.

                Interesting regarding the coloured guide flags. I will need to do further testing on that as I thought it to do with the 940nm led's and was going to give the 850nm ones a go.


                • #9
                  I found a bit of insulation tape at the bottom of the slot the best way of getting reliable readings, means the guide will cover the complete remainder of the light.

                  I think these sorts of projects are great for learning, especially when people share, so far I've seen people adapt my code for different displays i.e. oled, drag strips, one guy has built a version that works with scalextric digital. Haven't seen a touch screen yet. When I started I could already code, but I wanted to learn all the electronics stuff.

                  Strangely I dont use this anymore I now use a Bluetooth adapter and display all the info on an android tablet, I'll put a video up of this later. Have fun playing give me a shout if I can help with anything.



                  • #10

                    I have also had better results using the digital interrupt pins. I had to include some error checking in the code to eliminate false triggers.

                    I have also been using in-slot interrupters. They work well with guide flags, but in HO, they struggle with guide pins. I have changed over to a short range reflective photodetector (Panasonic PM2-LH10) placed next to each lane on a straight section of track. This does not work so well for 4 or 6 lane tracks, but the sensor does a nice job.

                    I am also working on implementing a BLE solution to display lap times on a phone or tablet.

                    Good Luck!


                    • #11
                      Great write-up, very helpful and very encouraging to those of us who might like to try this, thanks!


                      • #12
                        Hey Dazee, thanks for the write-up and code. I will save this for later on when I have remodelled my rec room to include a track room.



                        • #13
                          Have you tried increasing/decreasing the brightness of the LED on the sensor? At work if we have the LED too bright, the LED light will bleed thru or go around the object it is detecting.
                          I believe you are using a 330ohm resistor on that LED and 5 volts?


                          • #14
                            Thanks for the feedback. This is really just a start point as I am learning the Arduino platform and a bit about electronics. What I have done so far is on analog sensor input to the Arduino as I thought this would give me more scope to "tuning" the sensitivity of the sensor. However I now think this has limitations with regards to how fast an object you can capture. This is due to a fundamental difference that you keep going to check if anything has happened at the sensor, where as the digital interrupt in Slingshot's setup lets your code know when an even has occurred and so not likely to miss any laps.

                            Have got to do some job hunting today and tomorrow, so will likely be the weekend before I make the necessary changes to switch over and try using interrupts instead. Will post my results and any new code. Am holding off ordering any new boards being made until I do this too - I still want to get this a clean as possible and mounted on proper pcb's.

                            Lance, thanks for that. Yes I am using 5v with a 330 ohm resistor. I must admit my focus had been on adjusting the signal coming from the sensor, I had not even thought about adjusting the brightness of the input LED for it.

                            Something to add from my other thread about the track I am using this on at the moment. I have this plugged into a cheap voltage regulator board that gives it a constant smooth 5v. This in turn comes from the power input for the track. So there are no batteries or additional power supplies on it, it does not matter if the track voltage is set to 7.5v or 20v. It gets the right power and comes on with the track, it's good to go straight away.


                            • #15
                              You lost me at this...