For the personal training in sports that require time measurements, there are no cheap systems available to measure the time for a fixed segment accurately. The systems used in competitions are too expensive and too complicated to set up for regular personal use.

Furthermore, for small hobby competitions with friends, an accurate time measuring system that is cheap, easy to set up and portable would be useful. There are apps like Strava that use GPS data to time segments, but this is very inaccurate and cannot be used to get reliable timings.

With a cheap controller that uses a light barrier to detect athletes crossing and signals the exact time with ultrasound to the smart phone of the athlete, an accurate timestamp can be recorded. These controllers can be distributed at the start and finish lines of particular segments to record accurate timings.


Timings Controller

Light barrier

The controller needs to detect the crossing with a light barrier. There are three different types of light barriers: through-beam, reflex and diffuse. With a through-beam light barrier, the transmitter and receiver are located at opposite sides and need to be aligned precisely. Furthermore, both sides are active, so either a physical connection of both sides or two power sources are necessary. A reflex light barrier has a transceiver on one side and a reflector on the other side. When a corner reflector is used, the light is reflected back to the source even if the reflector is not positioned perpendicular to the light beam. So, it is sufficient if the light beam hits the reflector anywhere and at any angle, which makes this system easier to setup. As the reflector is passive, no connection to the other side or electronics are needed. The maximum detection distance is lower than with a through-beam system as the light has to travel back and forth. A diffuse light barrier detects the light that is reflected by the object triggering the light barrier itself, so only a single sensor is needed. The setup of this system is by far the easiest as nothing has to be aligned. However, it is dependent on the objects reflectance, it is not as precise as the other systems, and the detection distance is low. Because of this, it is not applicable for the controller. I choose a reflex light barrier as it is slightly easier to align than a through-beam system, no connection of both sides is necessary, and the detection distance is sufficient.

The light barrier I use outputs a signal while the beam is crossed. This signal has to be debounced as a single athlete triggers the light barrier multiple times while crossing. For example, on a bicycle, the light barrier could trigger many times just for a single rider because there are many open gaps the light beam can pass through. To get a precise measurement, it is desirable to detect always the same part of the rider or bike. The easiest option is to setup the light barrier at the axle height around 35 cm above the ground. The controller should trigger on the first obstruction of the light beam which corresponds to the tip of the front wheel. With a cool down timer, the controller could be reset after the light barrier did not trigger for a specified amount of time. This time maybe needs to be configurable, depending on the approximate crossing speed of the athlete which depends on the situation. With a speed of 5 m/s (18 km/h) and a bike length of 1.8 m, the total crossing takes 1.8 m / 5 m/s = 360 ms. However, the maximum gap is smaller, as each wheel triggers the light barrier at least at the left and right edge. On almost all bicycles, the gap in between the wheels is smaller than the diameter of the wheels. Cutting the length of the bike in 3 chunks, the cool down time can be reduced to 120 ms. This ensures that each rider only triggers the signal once, but if riders are close to each other, the sensor is resetted quickly.

Velocity measurement

If the athlete provides the exact length of his bicycle, the timings controller can calculate the crossing speed by dividing the bicycle length by the duration between the start of the first trigger and the end of the last. However, the accuracy of this could be really low because of flex of the bike, steering or crossing the sensor at an angle. With only the short length of the bicycle, even small differences of the measured length could make a big difference in the end velocity.

On a mountain bike with a lot of travel, a fully compressed front suspension reduces the length of the bike significantly. For example, with the Orbea Laufey 29" in size M, it is reduced by 54 mm. When the rider crosses the sensor at an angle, the diagonal length the sensor measures is reduced according to the Pythagorean Theorem. Furthermore, when the rider turns the handle bars, the measured length is reduced as well. For small angles, this factor is very small, but it still adds to the overall error. Coming back to the previous example, a bicycle length of 1884 mm (737 mm wheels + 1147 mm axle distance), a length reduced by 54 mm, and a crossing speed of 10 m/s would result in a velocity error of 0.054 m / (1.884 m / 10 m/s) = 0.287 m/s.

As the timestamps only have finite precision, more error is introduced to the system. A detection on the smart phone is not feasible as the timestamps there are far less precise because of the audio processing as described later. The precision on the controller depends on the cycle length, that is how long it takes to run the loop which checks if the beam is crossed. The controller itself can be improved by using a faster microprocessor. But the light barrier I am using right now does not specify any precision or timings and is likely the bigger constraint. If the light barrier is not fast enough, it could be disassembled and the included photoelectric sensor could be controlled directly by the micro controller.

As this is only an additional feature which also needs further communication between the controller and the smart phone to exchange the exact timestamps, I will first focus on the main functionality of reliably emitting and detecting the audio signal to record the timings.

Audio signal generation

As soon as the controller detects the crossing, it should signal this with an ultrasonic audio signal to the Timings App. Most audio amplifier circuits and loudspeakers are designed for audible frequencies from 20 Hz to 20 kHz. There are different types of speakers that are more or less usable for high frequencies. The most common types for high frequencies are electromagnetic speakers and piezoelectric speakers. An electromagnetic speaker uses a coil to move a magnet which is connected to a membrane. A piezoelectric speaker uses a piezo crystal, which slightly deforms itself when a voltage is applied.

To test the signal generation, I am first going to use a sound generator on my computer and the sound card as an output. To amplify the audio signal, I use the LM386M audio amplifier IC as it has a preset gain so that only a minimum of additional components is necessary. I use the basic design from the data sheet which is rated to work with frequencies up to 300 kHz. The Line audio output of the sound card outputs sound at Speaker level which has a Peak-to-Peak voltage of around 1 V. I use a potentiometer to find an applicable volume setting for the connection of the audio signal and the amplification circuit and replace it with two fixed resistors afterwards so that it is fixed.

Audio amplifier circuit based on LM386M

First, I will compare a generic coil speaker, a simple piezo buzzer and two different piezo speakers in the frequency range from 18 kHz to 22 kHz (maximum of my signal generator). I am using the app Spectroid to measure the generated sound on my phone which is positioned perpendicular to the speaker with a distance of 1 m. With a sampling frequency of 48 kHz, frequencies up to 24 kHz can be detected. I use a length of 1024 bins and the Blackman-Harris window function. The following graphic shows a frequency sweep from 18 kHz to 22 kHz (from bottom to top) over the period of 15 seconds for each speaker.

Spectrum of a frequency sweep from 18 kHz to 22 kHz displayed over time

In general, the two piezo speakers produce a much louder sound with the same power. They also perform best with frequencies over 21 kHz. The simple piezo buzzer does not work well for frequencies higher than 20.5 kHz. The electromagnetic speaker is just slightly better and works reasonably well up to 20.8 kHz. Therefore I am using one of the piezo speakers.
Above 22 kHz, there is a mirrored signal of the main signal for every speaker. I am not sure where this signal originates at, so I will do further testing on this later on. For the piezo speakers, there are also many other resonance frequencies. Many of them disappear when the main audio signal has a frequency higher than 19 kHz. I will change out different parts of the system later to check where this is originating. The renkforce piezo speaker has severe noise issues around 18.5 kHz. I think this is because of clipping which I will check in the next test.

To read the light barrier, debounce its signal and change the audio signal frequency, I want to use a microcontroller. Therefore it is convenient to use it to generate the audio signal as well. However, most of these microcontrollers do not have a true digital to analog converter (DAC), especially not one that can operate at such high frequencies. Therefore, without additional circuitry, only a square wave can be generated. With my audio generator, I can switch between a sine and a square wave to test what difference it makes. I will do these tests at a reduced volume as well to check if the noise is reduced and the clipping avoided.

Spectrum of a frequency sweep from 18 kHz to 22 kHz displayed over time for a sine wave and a square wave

The rectangular signal has slightly more noise and the resonance frequencies are more defined, but overall there is not a big difference. Therefore I will try the square wave generation with the micro controller next. By switching to the micro controller and using only piezo speakers, I can also test if the amplification circuit is necessary. The piezo behaves like a capacitor whereas a regular electromagnetic speaker behaves as a coil. A regular speaker should not be connected directly to the micro controller but with a piezo, this is not a problem.

To get the same conditions for the amplification circuit as before, i am using a coupling capacitor to remove the DC bias of the micro controllers signal. I also have to reduce the gain as the Peak-to-Peak voltage of the micro controller is 5 V which is five times higher than the line output of the sound card. For the direct connection, a coupling capacitor is not required as the piezo behaves like a capacitor. I use a potentiometer again to adjust the gain.

With the micro controller, there are different options to generate the signal. With a hardware timer, the signal can be generated accurately in the background whilst other tasks can be performed in the foreground. I use the Arduino AVR Core wich comes with an included Tone library that uses hardware timer 2. I use an Arduino UNO which features an ATmega328P micro controller. It runs at 16 MHz and there are 3 different hardware timers available: 0 and 2 are 8 bit timers and 1 is a 16 bit timer. With the default Tone library, only the 8 bit timer 2 can be used. Therefore, for frequencies starting at 18 kHz, we have to count to \left \lfloor{ \frac { 16 MHz } { 18 kHz } }\right \rfloor - 1 = 443. However, this is bigger than the maximum value 255 of the 8 bit timer. Therefore, we have to set the pre scaler to the first level which is 8. So we have to count to \left \lfloor{ \frac { 16 MHz } { 18 kHz } \frac { 1 } { 2 \cdot 8 } }\right \rfloor - 1 = 54. In general, the desired frequency can be achieved by setting the OCR (output compare register) to OCR = \frac {16 MHz}{ frequency} \frac{1} { 2 } \frac{1} { 8 } - 1. This limits the audio generation to specific frequencies. For 18 kHz, the closest value is 18.181 kHz with OCR = 54. The next possible frequency is 18.518 kHz with OCR = 53. The steps will get bigger with higher frequencies. This should not be an issue though, as I don't need many different frequencies and the farther they are apart, the easier they are to distinguish in the signal processing.

Frequency / Hz181811851818867192301960720000204082083321276217392222222727232552380924390

Audio signal processing

To detect the ultrasound signal from the controller, specific frequencies in the audio signal recorded by the smart phones microphone need to be detected. A Fourier transform is used to transform an aperiodic signal to the frequency domain. After the transform, an aperiodic signal is continuous, a periodic signal is discrete and vice versa. As the audio signal is sampled by the device, we would get a continuous signal in the frequency domain, which is not processable on a digital device. To solve this problem, the transformed continuous signal is sampled again. This is called the discrete Fourier transform (DFT). There is an algorithm to compute the DFT efficiently on digital devices, the fast Fourier transform (FFT). The FFT takes a sampled signal of a specific length, i.e. time, and transforms it to the frequency domain.

Audio recording / Sampling

First of all, the audio recorder of the smart phone has to be configured. As I need to detect frequencies up to 22 kHz, according to the Nyquist criterion, a sampling rate of at least two times that is necessary. I will use the next common sampling rate for audio signals to meet this criterion which is 48 kHz.


Next, a finite number of samples needs to be selected by windowing the input signal. For an accurate time measurement, a short sample size is desirable, as this will dictate the final resolution in the time domain. On the other hand, with a higher sample size, the resolution in the frequency domain is higher. This is the resolution of the waveform in the frequency domain, respectively the minimum spacing of frequencies that can be distinguished. One frequency domain sample is called a bin. To detect this reliably in the sampled frequency domain, the sampling rate in the frequency domain can be increased by zero-padding the input signal.

For example, if we want a resolution of 10 ms in the time domain, the maximum sample size is 10 ms \cdot 48 kHz = 480 samples. With 480 samples, the resolution in the frequency domain is \frac {24 kHz} {480} = 50 Hz, so in general, frequencies 50 Hz apart can be detected.

Just selecting a number of samples is equivalent to applying a rectangular window. As the window function is multiplied with the signal in the time domain; in the frequency domain, this results in a convolution. If we have a pure sinusoid which transforms to a simple impulse in the frequency domain; because of windowing, it will be spread out to neighbouring frequencies. This effect is called (spectral) leakage.

With a rectangular window, this spread is wide. There are different window functions that try to minimise this spread, but this is connected to a decreasing resolution. In general, there are two general types of windows: high dynamic range and high resolution.

High resolution windows should be used if frequencies that are nearby (only a few bins apart) and have similar amplitudes have to be distinguished. A high dynamic range window should be used if the frequencies to detect have enough frequency space in between but can have different amplitudes. For this application, as the frequencies can be far enough apart, a high dynamic range window seems the better choice so that even if there are other louder sounds, the frequency emitted by the controller can be detected. For a first prototype, I will use the Hanning window which should have a high enough dynamic range. The performance of other windows can be analysed later as it is easy to switch window functions in the code.

Fourier transform

After the audio signal is sampled and windowed, the discrete Fourier transform itself can be computed. For the efficient FFT algorithm, the sample size has to be a power of 2. With a signal size of 1024 samples in the time domain and a sampling rate of 48 kHz, the signal length used for one FFT will be 1024 / 48 kHz = 21.3 ms, which also is the highest possible resolution for the final timings. The resolution in the frequency domain is \frac {24 kHz} {1024} = 23.44 Hz, so each bin represents 23.44 Hz. This could be made more accurate by zero-padding the input signal. For example, doubling it in length results in a spacing of 11.72 Hz/bin. As discussed earlier, this only takes more samples in the frequency domain, it does not increase the overall frequency resolution of the transform. With this setup, I should be able to detect frequencies up to 24 kHz. With the Hanning window, a spacing of at least 10 bins, which is 234 Hz, should be enough to distinguish the frequencies reliably.

Frequency detection

A first really simple approach is to just choose the frequency with the highest amplitude from the frequencies I am interested in. When there is a change from one specific frequency to another, a timestamp is recorded.

App development

The current version of the app can be installed from https://play.google.com/store/apps/details?id=de.timspickermann.sportstiming or downloaded from the files section below. The audio processing is running in a foreground service and timestamps are detected successfully. To test the app, the website https://timspickermann.de/apptest/ can be used to emulate the controller. When the "Enable sensor" option is checked, an audio signal with 19 kHz is transmitted, the app notification should show "Sensor in range". As long as the "Trigger" button is pressed, the frequency is raised to 19.5 kHz which should be detected by the app and a timestamp should appear on the screen.

  • No labels