Meet Cuckoo—An Embedded Open-Source Lap Timer
Meet Cuckoo—An Embedded Open-Source Lap Timer
As the embedded team in Polidea, we always wanted to work on a project just for fun, to explore new territories, or prove that some crazy idea can become a working device.
When the opportunity to do that appeared on the horizon, we organized a small brainstorm to determine what we wanted to do. The only thing we knew at the time was that we wanted to open-source our future project and make it accessible to everyone. Solving a real-world problem would be a nice bonus.
On the Right Track
After dismissing a few initial ideas, we decided to solve the issue of measuring lap times on race tracks during public track days. For anyone not familiar with the idea of a track day, it is an event during which anybody can use a race track to test out their car and driving skills. The problem is that the organizers do not always provide the lap timing devices, and even if they are, they do not give you instant feedback on your performance. Sometimes, even the summary of the whole driving session is not available, and drivers only get their best lap time.
Moreover, these devices need special equipment mounted near the finish/start line. Of course, numerous mobile apps measure lap times and other parameters like speed, g forces in the corners etc. The problem is, they do not seem to be very accurate. External GPS devices can be attached to the mobile phone to increase accuracy, but they tend to be very expensive. We knew we could create something better within a reasonable price range and still have some fun with it.
Our hobbyist experience with drones suddenly became surprisingly useful. We thought we could use transmitters used by drones to emit video and audio signals, which are later received by the pilot’s goggles. You could ask: “Why the heck do they need video and audio signal to measure lap times?”. We don’t. We thought we could only measure the signal strength and determine when the car passed near the transmitter placed on a finish line. A single transmitter seemed to be enough to serve multiple receivers placed in the cars or any other vehicles moving around the race track. We decided to use popular and widely available transmitters and receivers, connected to an nRF processor—a platform which we had been already familiar with. Its job would be to make the necessary calculations and drive the display presenting live data of the lap times.
We set out to solve a real-world problem in the way no one approached it before, using popular and available hardware components. Now, let’s go into details!
To put it simply, the main idea was to place the transmitter next to the finish line of the track. In the car, there would be the receiver checking the received signal strength. We assumed that we would be able to see the moments when the car goes next to the finish line just by observing the strength of the received signal. That was the theory. We were not sure if the distance would be close enough and if the inertia of the signal strength measurements would be low enough to see precise points of time corresponding to the new laps. To proceed with the implementation, we needed proof that our approach was doable. Therefore we did a few measurements to confirm the validity of the idea.
We attached the radio transmitter onto an electric scooter and did some races around our office’s open space and the building. You are right, the idea is inverted (the receiver should have been in the vehicle). As the movement is relative, it was not important. The radio receiver connected to a Raspberry Pi was located on a stationary point. Raspberry was in charge of saving the signal strength level traces to an SD card. The collected data raised our hopes that everything was perfectly achievable, and we would manage to successfully finish the project.
From the above picture, it is evident that the data is promising. The green, orange, and red lines around the building correspond to the paths that we were riding on the scooter. The paths were different to test different conditions, such as various distances between the receiver, the transmitter, and riding behind (or not) parked cars. Those conditions slightly impacted the received signal strength, but even so, in each case, you can clearly see a distinct peak of the signal. We just needed to measure the time between these peaks to get the lap time, which seemed to be an easy task.
From the start, we knew that our device had to connect to a mobile application, which we would also create. We needed a BLE capable SoC. nRF52 platform created by Nordic Semiconductors seemed just right. It’s widely used in the industry, their SDK is mature and well tested. We didn’t want to create our own PCB design, we just wanted to build a hardware prototype quickly. We picked nRF52840 dongle, as it was available off the shelf and was small enough to fit inside our device.
We used a cheap 5.8GHz receiver, which works only on the boscam channel. Together with patch antenna, it was good enough for our application. Besides the mobile application, we needed some kind of physical interface on our device. The obvious choice was just a few buttons and an LCD screen. The information displayed on the screen had to be clearly visible at first glance during the race. That’s why we went with a big char 2x16 LCD display with a well known HD44780 driver. To reduce the number of data lines required for the connection of HD44780 LCD, we used an I2C expander. Because of the differences in voltage levels between nRF and LCD (3.3V vs. 5V), we used a simple level converter module.
At first, the prototype which we created was just LCD, I2C expander, and voltage converter—all connected using a breadboard and wires. We used another nRF DK as a SWD programmer for our nRF dongle.
In our final prototype, we soldered all components on a universal board. We have also used a bigger screen. Moreover, we needed some kind of case for our device. Some universal cases can be bought off the shelf, but we wanted something made specifically for Cuckoo to mount our antennas inside correctly.
Since some of us are 3D printing enthusiasts, we have designed a case using Autodesk Fusion 360. It’s a CAD software used by professionals to model various mechanical parts. Our case has a GoPro compatible mount. It has two slots for the antenna inside, allowing to put it on the right or left side depending on where the transmitter is placed on the track. There are some holes for buttons, as well as holes for screwing the LCD in place. There is also a lid with a hole for power cables.
Our application wasn’t too complicated, so we decided to go with the bare-metal architecture without running any RTOS. The basic idea was to use analog to digital converter to sample analog RSSI signal coming from the receiver module. Based on that, our algorithm could detect when the finish line was crossed. RTC was used to measure the time between the consecutive laps. LCD was connected to nRF using I2C expander, so we used standard I2C nRF driver to implement more high-level driver, which allowed us to print text on the LCD easily, set cursor, etc. nRF flash storage was used to continuously store lap times during power off for later download over BLE by the mobile application.
The receiver module has only one analog output. That’s the RSSI pin, which has a voltage proportional to the strength of the received signal. Reading that output is a perfect task for an analog to digital converter. We configured the peripheral ADC on the nRF microcontroller to produce 14bits samples with 2,5kHz frequency. That means we had more than two thousand numbers to analyze per second. Basing only on that flow of numbers, we had to tell when the driver passed the finish line. The simplest algorithm would be to just wait for a local maximum of the signal strength trace. However, that was not that easy. We needed a more sophisticated algorithm to avoid false positives related to the signal noise and different track shapes.
To devise a flexible and working algorithm, we needed the data to work on and test against. As similar to the real data as possible. Therefore, we used exactly the same receiver and nRF board and did a shortcut by sending the raw data by UART to the Raspberry Pi. Raspberry was again responsible for saving the data on the SD card, but this time the data was real. Firstly, because we used the target hardware platform to generate them. Secondly, because we collected the data during real races on a real race track! That was it, we mounted the prototype inside a car and registered the data while driving on the track.
On the plots below, you can see the raw, unfiltered data (on the top). On the bottom, you can see the effect after applying a simple 5th order median filter. While the raw data could be confusing as there are many peaks—and some of them are just noise—the filtered plot is extremely readable. We can clearly identify the moments where the driver was passing by the finish line.
To show the character of each peak on the plot below, you can see one of them, zoomed. While the car is driving around 100km/h (62mph), the peak length is about 300 ms, and the car travels about 8 meters during that time. That’s about 800 samples, and it’s enough to detect the new lap event without a doubt. Don’t be confused that our measurement accuracy is close to 300 ms. It is a few orders of magnitude more precise. You can also see that the signal itself is quite noisy and that more than one local maximum appears.
Therefore, we implemented the following algorithm. If the median filtered trace value exceeds the threshold RSSI level for some arbitrary period (marked with green on the picture below), we trigger a new lap event. Then, there is a restricted time (marked with pink) during which, even if the signal meets the new lap event condition, it’ll not be generated. That’s all, it’s that simple. Even without rocket science, we accomplished the task of generating credible new lap events. Having those events, we only need to calculate the time between them, which is a trivial task based on the real-time counter in the nRF peripheral.
Why do we actually need a mobile app in this project? The main idea behind the app was to have a safe place to store our data. As the storage in the device is somewhat limited, it is a good idea to save our precious lap times on a mobile phone which offers more than enough space to store them. Moreover, the Cuckoo device itself does not offer a possibility to browse a history of our track sessions. While being really good at providing live information about our performance, there is no way to examine the data later on. The app is the perfect way to address this need.
One of our main goals from the beginning was to keep everything simple while offering a wide range of functionality. We also thought that being able to run the app on various types of mobile devices would be a good feature. Having all of the above in mind, we decided to write it using React Native and reduce the number of screens as much as possible.
After making these decisions, together with our design team, Utilo, we started to make the first sketches of the app. We managed to squeeze all of the functionality we wanted into three screens.
This is what we came up with.
The first screen is used mainly to establish a BLE connection with the selected device. Buttons to start and stop current driving session are also present, as well as the current lap time. History screen lets the user browse and manipulate the driving history—deletion of a driving session and name editing are also possible.
The live screen is mainly a reflection of what can be seen on the Cuckoo device screen but with additional data, such as a list of lap times from the current session. Big buttons are easily accessible while driving. In live mode, the lap times can be read out loud by the app, so the driver knows how he/she is doing without looking at the screen.
Meanwhile, the necessity of having a more catchy name appeared. We knew that we needed to have some colors and a product name in mind, to be able to design the app properly. Creating the brand and the app has been done simultaneously, so we had to adjust one to the other few times during the whole process.
The story behind the name Cuckoo started with an idea of having some single central device and multiple devices circulating around it. Like bees flying around the hive or birds around their nest. We decided to stick with the birds idea. Cuckoo is a bird that is associated with measuring time right away (who doesn’t remember old cuckoo clocks?) seemed like the perfect choice.
Our overall impressions after successfully completing the project are very positive. We are glad that our initial idea, which was kind of new and experimental, worked and evolved into the Cuckoo device. We cannot wait to test the final product out on a track!
If you have an embedded project in mind or want to talk about the Cuckoo, don’t hesitate to contact us!
Senior Software Engineer
Lead Software Engineer
Senior Software Engineer
You might also like
LeakCanary—Deobfuscation Feature Explained
LeakCanary—Deobfuscation Feature Explained
Learn how to detect and debug memory leaks during app deobfuscation with LeakCanary—an open-source project, to which our Senior Software Engineer, Michał, contributed.