µLogTimer: Lap Timer Project

Here is an update on my latest version of an onboard IR-based lap timer, suitable for cars, karts, motorcycles, bikes, etc. This one has no display, and simply records individual lap times for later downloading to a PC. It utilizes a SparkFun uLog data logger and a 38KHz IR receiver (like a GP1UX311QS or TSOP38) and can be powered from a 110mAh LiPo battery. The result is a very compact unit.

µLogTimer with 110mAH LiPo Battery in the palm of my hand highlighting its small size.

Note in the picture above, the IR detector receives its power supply from the uLog and is simply soldered into the 3.3V, GND, and X pin holes (per the datasheet, a more robust installation would apply a 0.1uf cap between VCC/GND and 100 ohm resistor in the VCC line, but hey…).


The uLog with 2M of dataflash memory has plenty of storage space (2M translates into potentially 540,672 laps of storage). The µLogTimer will require a device like the FTDI Basic to download lap times. The communication protocol is 8N1 with no handshake at 38,400 baud. The µLogTimer responds to 3 simple commands:

  • ‘e’ – Erase lap time memory.
  • ‘d’ – Download lap times.
  • ‘a’ – Download the entire dataflash memory contents.
  • Here is an example of downloaded lap times made during a test:

    This example uses Termite RS-232, however any terminal program would be suitable.

    Trackside Beacon/Transmitter

    The µLogTimer responds to an AIM trackside beacon. The beacon continuously transmits a coded IR pulse which the µLogTimer receives and uses to define the start/finish line. The µLogTimer simply needs to be positioned such that the IR detector has an unobstructed view of the transmitter. AIM beacons are prolific and it’s hard to imagine there not being one at any well-attended track event. However, see below how easy it is to convert an adafruit TV-B-Gone Kit into a beacon transmitter.

    AIM Beacon Transmitter

    Source Code

    It was a challenge to fit all of the features into the memory confines of the ATtiny24 onboard the uLog, so the program is not rich in features. I will admit to some “oddness” in the code in order to reduce its size. The program is built upon the confusing tangle of outdated and very poorly commented source code available for download on the uLog webpage.

    The µLogTimer program is available on this post here.


    Since the uLog ATtiny24 is running on the internal 8MHz RC, the timer accuracy will vary by chip and ambient temperature. The internal RC can be calibrated to improve accuracy by comparison to a valid external source. I have performed this calibration using a 32KHz DS3231 TXCO (ChronoDot), see this forum post for details.

    adafruit TV-B-Gone as Transmitter

    If an AIM transmitter beacon is not available, or if one wants to run this system on a “private coded” IR signal which prevents interference with others, you could easily make your own transmitter. One solution is to modify the program on an adafruit TV-B-Gone. An example of a private IR beacon code is included in the source code.

    adafruit TV-B-Gone

    Here is the modified ATtiny85 TV-B-Gone program:

    AIM Lap Trigger Beacon using TV-B-Gone Hardware 
    Portions (c) by:
    TV-B-Gone Firmware version 1.2
    for use with ATtiny85v and v1.2 hardware
    (c) Mitch Altman + Limor Fried 2009
    Last edits, August 16 2009
    With some code from:
    Kevin Timmerman & Damien Good 7-Dec-07
    Distributed under Creative Commons 2.5 -- Attib & Share Alike
    // What pins do what
    #define LED		PB2
    #define IRLED	PB0
    // Shortcut to insert single, non-optimized-out nop
    #define NOP __asm__ __volatile__ ("nop")
    #define freq_to_timerval(x) ((F_CPU/x - 1)/2)
    //for 8MHz we want to delay 8 cycles per microsecond
    //this code is tweaked to give about that amount
    void delay_us(uint16_t us) {
      while (us != 0) {
    //This function is the 'workhorse' of transmitting IR codes.
    void xmitCodeElement(uint16_t ontime, uint16_t offtime) {
      //start outputting the carrier frequency on OC0A, PB0, pin 5
      TCNT0 = 0; //reset the timers so they are aligned
      TIFR = 0;  //clean out the timer flags
      //timer0 mode #2 CTC, with OCRA as TOP, toggling OC0A(PB0) on compare match, no prescaling
      TCCR0A =_BV(COM0A0) | _BV(WGM01);
      TCCR0B = _BV(CS00);
      //turn off timer0
      TCCR0A = 0;
      TCCR0B = 0;
      //make sure that the IR LED is off since timer may have stopped while the LED is on
      PORTB |= _BV(IRLED);
    int main(void) {
        uint16_t flash;
        DDRB = _BV(LED) | _BV(IRLED);    //set the visible and IR LED pins to outputs
        PORTB = _BV(LED) | _BV(IRLED);   //LEDs are off when pins are high
        OCR0A = (uint8_t)freq_to_timerval(38000); //value for 38kHz
        TCCR0A = 0;	  //stop timer0
        TCCR0B = 0;
        flash = 0;
        while(1) {
            if (flash == 2000)
              PORTB &= ~_BV(LED);      //turn on visible LED at PB0 by pulling pin to ground
            //measured AIM beacon pattern [inverted by PNA4602M]:
            //high 6ms/low 624us/high 1.2ms/low 624us/high 1.2ms/low 624us [repeat]
            //Alternative Private Beacon Code:
            //300us ON / 1200us OFF / 300us ON / 1200us OFF / 300us ON / 6000us OFF
            //900us ON/9300us = 9.7% duty time
            xmitCodeElement(622, 1195);  //timing tweaked via AVR Studio Stopwatch
            xmitCodeElement(622, 1195);
            xmitCodeElement(622, 5994);  //IRLED on 1.872ms/off 8.4ms = 18.2% on time
            if (flash == 2005) {
              PORTB |= _BV(LED);       //turn off visible LED
              flash = 0;

    One could easily make their own version of transmitter out of an arduino, or similar device. It would only take a brief study of the TV-B-Gone schematics and code to figure it out. Good luck if you decide to make your own version.


    About Jim Eli

    µC experimenter
    This entry was posted in Uncategorized and tagged . Bookmark the permalink.

    2 Responses to µLogTimer: Lap Timer Project

    1. inventordrew says:

      I’m looking at making one of these but with an ATMega32U4 and the same external flash chip. Mostly because it’ll run off a 16Mhz crystal for better accuracy from day to day (according to the datasheet, the RC could vary by up to a 1.4 seconds over a 40 second lap… if the temperature changes a lot). And because I think it’ll have plenty of grunt for doing extra fancy things (like also logging motor temperature and/or accelerometer inputs along side the lap times)
      How do you find the range of the IR? Do you use a shroud around either the Rx or Tx to increase accuracy?

      • Jim Eli says:

        How do you find the range of the IR?

        I primarily use an AIM transmitter which has both a low and high power setting. I don’t use the high setting, as it can easily transmit across several lanes of a kart track. Transmitter placement must be carefully selected. I would guess the range is 50-100′.

        Do you use a shroud around either the Rx or Tx to increase accuracy?

        No. If you build your own transmitter you can use narrow-angle IR LEDs (I think I used 17 degrees) to get a similar effect. I believe the Adafruit TV-B-Gone uses both narrow/wide-angle IR LEDs. I have conducted limited experiments shrouding the IR receiver (with a high-tech soda straw).

        Good luck.

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out /  Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out /  Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out /  Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out /  Change )


    Connecting to %s