Tech: Freematics One+
Moving further forward in time takes this episode to an even smaller embedded device with a very different purpose, which proved to be one headache too many...
Many years after the earlier tech projects I found myself interested in tracking the metrics of my vehicle, specifically tracking it in real-time to try to correlate different aspects of its performance using my tool of choice at the time (Splunk). At the time I embarked on this project the AutoPi didn't exist (which is a shame as it would have saved me a lot of headaches), but searching around did allow me to find the Freematics One+. This tiny device plugs into your OBD port and logs data from the engine, and can also log GPS data if you have the optional antenna.
One purchase later and I had the device in my possession, complete with the GPS antenna and some test cables allowing me to power the device on without needing it connected to the car. With the hardware present it was time to delve into the available software/code for it. Thankfully there was code already available and even a choice of IDE's depending on your programming skill. As I wasn't that familiar with C++ I started with the Arduino toolkit before switching to PlatformIO, though neither gave me entirely what I was after.
After spending some time digging through the available code and stripping it back somewhat I came up with the following objectives for the project:
- Create a slim set of code with only the functionality I need
- Leverage the OBD2 connector to get real-time stats such as speed/RPM/turbo pressure/temperatures
- Leverage the GPS to get real-time location
- Leverage the GSM modem to send data in real-time
- Leverage the SD-card to buffer data when GSM isn't available
- Send data to Splunk via HTTP (HEC)
- Get a device-to-ingest latency of less than 10 seconds
- Visualise the data in real-time via Splunk
And so the coding began... Patiently chopping up the existing code to remove the logic for other models, adding in custom code to handle data storage/data transmission, and improving the overall performance. So far so good, but then came the first hurdle, heat. Despite the code being slimmed down and not trying to run the CPU at its maximum 100% of the time, the heat of the device was too much for it to cope with. Even trying the standard firmware resulted in the same issue; the device would overheat and reset itself. Thankfully, after making plenty of holes on the top and bottom the device was able to cool itself properly even when under load.
The next challenge was getting data through to Splunk, without burning through a pre-paid data plan. Some careful adjustments to how the data was sent allowed for it to be human-readable but with a minimal footprint. In an ideal world the data would be sent in binary form (with some form of checksum for integrity verification) however that wouldn't be compatible with Splunk HEC and would require another component to be added into the mix. With the slimmed down output working it was time to tackle the next hurdle, connectivity.
As GSM signal varies depending on where you are (not to mention if your antenna is somewhere underneath your dashboard) you can't guarantee connectivity 100% of the time. To work around this it was time for some custom code to use the SD-card as a buffer for when connectivity dropped. It took a few attempts to get this to work cleanly (not to mention minimising the data output to reduce the write time), but in the end it worked as desired and acted as a clean store for temporary data.
At this point things were looking relatively good, with connectivity working and a prototype dashboard able to show the location of the vehicle on a map and its many engine metrics in real-time (quite a feat), however there was one problematic issue that I couldn't put my finger on... While the device would work some of the time, periodically it would misbehave and would outright fail without warning. As you may have guessed, this is where the headaches began.
Debugging this wasn't fun at all, and in the end required connecting a laptop to the device and driving around to capture the output. As it turned out, the ESP32 powering the device (specifically its core software) had an issue with serial concurrency. In order to optimise the performance of the code it leveraged threading, which given the dual-core nature of the ESP32 is a solid idea. It also leveraged a thread-safe queued logger to allow messages to be written to the serial port for debugging. Unfortunately, this is where things started to fall down...
The threaded nature of reading from the GPS while also reading from the engine and also queueing data/sending data was managing to corrupt the GPS data (via different serial lines), which in turn made everything else problematic. In the end I managed to write a very simple app that demonstrated the issue, reading from the GPS while trying to log to the console in rapid succession. Sadly, even after reporting the issue to the vendor it was never resolved while I worked on the project, leaving me to demise the device (and subsequently replace it with the AutoPI).
Overall it was a real shame that this never worked as I had hoped, as given the very low power of the device and the size/portability it would have been great to have this connected as a permanent device. I did check the tool-chain about 2 years after and found that an issue with the corruption I had described had been fixed, however as the AutoPI had been released and provided a lot more functionality and was easier to work with I didn't revisit this project.