Saturday, November 24, 2012

Lap Timer Part 5 - Buzzer, External Audio and Some Builds

The latest version of the lap timer includes two new features -

1) External Audio - There is now an option to use a very simple amplifier circuit which is small enough to fit inside most project boxes. This will give you a lot more volume when you are using the system outdoors.

2) Countdown - With countdown switched on, the lap timer will beep to count down the last few seconds of the current lap time - it adds a little extra pressure - to beat the lap you have to beat the beeps.

For previous steps of the build along see the project index page -
http://rcarduino.blogspot.com/p/project-index.html

Before we get to the build, here are some user pictures of current builds, if you have pictures of your own build I am happy to share them.

ALLY - Transponder mounted in touring car chassis


    Howie314 - Using an LCD Shield for a fast build
This build by Arduino Forum User Howie314 uses a LCD Keypad Shield, it keeps the size down and means there is very little soldering required to build the project. Many LCD Shields are available and all work in a similar manner meaning that you can get a lap timer up and running quickly with almost no soldering required.

If someone would design an LCD Shield with a rotary encoder as well as buttons we could have the perfect lap timer interface.

Howie314 is one of the first using the most recent version of the code with the new options of external audio and countdown. Additional options that I am considering in the near future are 1) Window magnet transponders and 2) AIM Transponders. See the end of post for more details.










Howie also did some work on the user interface as the LCD Shield uses a single analog pin to read multiple buttons. It makes sense to offer a version of the build along based on these readily available shields so I will be taking a look at Howies modifications with a plan to offer a single version of the project which can be run on standalone builds or LCD Shields - props to Howie.


ALLY's Build and Enclosure

Arduino forum user ALLY has used a standalone LCD and soldered his own buttons. This gives a bit more flexibility in the type of display and enclosures you can use, but also requires more work to build.
ALLY Transponder Mount
Here is a shot of ALLY's transponder mounted in his RC Touring car. Notice that the IR Emitter is mounted on a small post, this is a nice solution as the LED is well away from any areas that would impact in a crash.

If you want to try something similar make sure to keep the wires to the LED short. I tried wires of about 15 cm which unfortunately acted as an antenna causing radio interference.
ALLY's Carbon

ALLY has used a large carbon fibre effect enclosure, there is lots of room to add indicator LEDs, or one of my favorite features - a small amplifier for optional external speakers.
Lap Timer Piezo Buzzer and External Audio
One of the most useful features of the lap timer is instant audio feedback, this is particularly important with RC Car racing and Kart racing where corners are fractions of a second apart and checking a display is not an option.

The feedback is deliberately simple but totally effective - one beep to confirm a lap and two beeps if its a new best lap.

To add the audio features we have two options

1) A Piezo Buzzer
2) An External Speaker

I have found it useful to have both options in my build, using the quieter peizo for testing near my home and the external audio to overcome the additional noise at the track, the latest code includes a menu to switch between these two output options.

Piezo With Transistor Driver
To get as much volume as possible from the buzzer we can drive it using the battery voltage rather than the regulated 5 volts from the Arduino. To switch the higher battery voltage from an Arduino pin we use a NPN transistor connected between the piezo (the load) and ground. This arrangement allows us to switch the higher voltages and currents through the Peizo and can also be applied to other loads such as high powered LEDs, relays and other components you may want to use in your future projects.



Components
1 * 2.2K Resistor
1 * P2N2222 Transistor
1 * Piezo Buzzer 

External Audio Through A Speaker
The Peizo option can be used without adding the external audio option, but if you want more volume in your build read on -

In order to power a speaker we need a few more components to drive the extra current, one easy to use option is the LM386 Audio Amp chip. This is used extensively throughout the RCArduino blog in a variety of audio projects, full details and videos of the chip in action cab be found here -

http://rcarduino.blogspot.com/2012/08/adding-audio-to-arduino-projects.html

The LM386 Audio Amp can be build to a very compact form factor to fit your chosen enclosure -
Parts List
1 x LM386-N4
2 x 100uf Electrolytic Capacitors
1 x 0.1uf Capacitor
1 x 100Ohm Resistor
1 x 10K Potentiometer1 x Phono socket for speaker connection



Schematic - Note the audio output is from analog pin 5, for simplicity only the audio components are shown, as there
For the latest code, contact me Duane B though the Arduino forum.

Future Developments
Some common requests that I will be adding in the near future are -

1) Support for individual transponders - this will take some experimenting, but it should be possible to create a simple transponder scheme which will allow several lap timers to be used simultaneously with each car paired to a specific lap timer.

2) Support for magnetic transponders - I am told that many kart tracks use a magnetic strip under the track to activate transponders which are similar to magnetic window sensors, I hope to work with an Arduino forum user to add support for this option, it should be simple, but I have nowhere to test the system locally.

Inspired by Howie314's use of an off the shelf LCD Shield I will also add support for a build along based on this quick start option.

If you have a build you want to share, please submit some pictures,

Stay Tuned

Duane B

 

16 comments:

  1. Hi all,

    work is progessing on my build. I have completed my PIC based transponder, which will allow me some flexibility with respect to pulse coding. Especially where more thanone unit is in use.

    I am hoping to do some lap time comparisons with an AMB system at the weekend, I will post back more info.

    My next stage is either to add a facility to dump session data to serial port or ad an sdcard.

    ReplyDelete
  2. Hi, Do you have any ideas on how to create a unique signal per car ? ALLY is going to try and get hold of some transponders from a few discontinued commercial personal lap timers, I am going to send him some code to see what they are using to for unique codes. The challenge is that the cars are in the detection area for a very short time and the code are corrupted on the way into and out of the detection area so you need something unique that can be transmitted 3 or 4 times in a very short space and that will not over lap with other signals present during this short time. As for SD Card storage, I build the original design to have the option of selecting different types of storage. In the file LapTimes.h you will see a class ILapStore and then the derived class CEEPROMLapStore, to add SD Card support I would suggest keeping this model by creating a new class CSDCardLapStore, this means you can keep the rest of the code intact or even select whether to use EEPROM or SDCard at run time - i.e. test for a card, if there is one use CSDCardLapStore if not, use CEEPROMLapStore. If you need help with this let me know. Duane B

    ReplyDelete
    Replies
    1. Hi m8,

      In terms of a unique signal, AMB for example will invariably use a pulse width based code or similar. The easiest approach for the IR application is to transmit a code, SIRC is a good example. This is essentially a 12bit 1.2ms=1 0.6ms=0 interface. I think these pulses would have to get shorter to allow more than one complete code transmission. This is why I implemented a PIC based transponder. (very little drift) In basic testing my PIC(PT) is providing a very consistent 600uS pulse repeated at 1khz. Serial output tests show +/-1ms drift. I have the MIN/MAX pulse settings set 20us either side of programmed pulse and it is working ok. If the pulse width was to drop by a factor 10, it should be possible to detect different signals based on a 10-20us pulse width spacing. My first stab would be an interpretation of SIRC, with perhaps 60 and 120uS pulses. assuming a start and finish header of sorts to allow the code to better determine a valid signal, 8 bits would still provide 255 possible transponder codes. (More than enough)

      Other options I have considered are Bluetooth sniffing, but this requires some RF knowledge to limit the Receiving antenna to a narrow notch.

      Delete
    2. Sorry, please read mS as uS

      Delete
    3. Also worth noting that the limiting factor is the 38Khz carrier.

      Delete
  3. Something like this -


    class CSDCardLapStore : public ILapStore
    {
    public:
    virtual lap_time_t getLapTime(lap_handle_t lapHandle);
    virtual void setLapTime(lap_handle_t lapHandle,lap_time_t lapTime);
    virtual void clearAll();
    virtual uint16_t getMaxLaps();
    };

    ReplyDelete
  4. You can put this in the setup function to dump the current laptimes to the serial monitor when the Arduino starts -

    for(int nCount = 0;nCount < MAX_LAPS;nCount++)
    {
    Serial.print(nCount);
    Serial.print(" ");
    Serial.println(CLapTimes::formatTime(gLapTimes.getLapTime(nCount)));
    }

    Let me know if it works for you, I pulled it from an older version of the code.

    Duane B

    ReplyDelete
  5. Scrap that, use this, its a comma separated list so easy to import into XL, the columns are lap number, raw lap time and then formatted lap time

    for(int nCount = 0;nCount < MAX_LAPS;nCount++)
    {
    Serial.print(nCount);
    Serial.print(", ");
    Serial.print(gLapTimes.getLapTime(nCount));
    Serial.print(", ");
    Serial.println(CLapTimes::formatTime(bestLapTime,true));
    }

    Duane B

    ReplyDelete
  6. Hi,
    Here is a ready made sketch from adafruit that will let you read the raw IR Codes from existing transponders -

    http://learn.adafruit.com/ir-sensor/using-an-ir-sensor

    Duane B

    ReplyDelete
  7. Hi,

    I did this last night. It allows me to trigger a serial dump as part of the menu system.

    Don't slate my novice coding ;)

    void doDownloadData()
    {

    boolean bFinished = false;
    uint8_t nSession = 0;

    lap_handle_t lapHandle = 0;
    uint16_t nSessionAverage = 0;
    uint16_t nSessionBest = 0;
    uint16_t nSessionLapCount = 0;
    // tmpLap = gLapTimes.moveNext(nLapNumber);

    for (nSession =0; nSession < 255; nSession++)
    {
    lapHandle = gLapTimes.getSessionHandle(nSession);
    if(lapHandle == INVALID_LAP_HANDLE || (lapHandle == 0 && gLapTimes.getLapTime(lapHandle)==0))
    {
    }
    else
    {
    //////////////////////////////////////////////////////////////////////////////
    // Print Session Header
    ///////////////////////////////////////////////////////////////////////////////
    Serial.print(getRamString(PSTR("Session: ")));
    Serial.print(nSession);

    //Serial.println(lapHandle);

    gLapTimes.getSessionSummary(lapHandle,nSessionAverage,nSessionBest,nSessionLapCount);

    Serial.print(getRamString(PSTR(" Best Lap:")));
    // Best Lap Time
    Serial.println(CLapTimes::formatTime(nSessionBest,true));

    Serial.print(getRamString(PSTR("Number of Laps: ")));
    Serial.print(nSessionLapCount);
    Serial.print(getRamString(PSTR(" Average Lap: ")));

    // Average Lap Time
    Serial.println(CLapTimes::formatTime(nSessionAverage,true));

    //////////////////////////////////////////////////////////////////////////////
    // Print Lap Data
    ///////////////////////////////////////////////////////////////////////////////

    //boolean bFinished = false;
    uint8_t nLapNumber = 0;

    for (nLapNumber =0; nLapNumber < 500; nLapNumber++)
    {

    if (gLapTimes.getLapTime(nLapNumber) == EMPTY_LAP_TIME)
    {
    break;
    }

    Serial.print(getRamString(PSTR("Lap No.")));
    Serial.print(nLapNumber);
    Serial.print(getRamString(PSTR(" ")));
    char *pTime = CLapTimes::formatTime(gLapTimes.getLapTime(nLapNumber),true);
    Serial.println(pTime);

    }

    }
    }
    }

    ReplyDelete
    Replies
    1. Slight error in the above, I forgot to point the lap print to the current session.

      //////////////////////////////////////////////////////////////////////////////
      // Print Lap Data
      ///////////////////////////////////////////////////////////////////////////////

      //boolean bFinished = false;
      uint8_t nLapNumber = 0;
      lap_handle_t startLapHandle =gLapTimes.getSessionHandle(nSession);

      for (nLapNumber =startLapHandle; nLapNumber < 500; nLapNumber++)
      {

      Delete
  8. Hi,
    Thats a nicely formatted session/lap dump, I was dumping in CSV Format to load with xl - probably not as immediatley useful as your format.

    Over the christmas break I will merge your additions back into the main branch and look at setting up a repository for the code so that others can contribute.

    Duane B

    ReplyDelete
    Replies
    1. Hi is there any new developments with your lap timer for arduino please

      Yours

      Richard

      Delete
    2. Hi is there any new developments with your lap timer for arduino please

      Yours

      Richard

      Delete
  9. If you want your ex-girlfriend or ex-boyfriend to come crawling back to you on their knees (no matter why you broke up) you must watch this video
    right away...

    (VIDEO) Have your ex CRAWLING back to you...?

    ReplyDelete