Measuring Car Stats with OBD Logging

Ever since my stereo wires were routed to the front, I can happily live day to day with my dashboard gutted. My primary goal here is to add bluetooth and OBD logging functionality to my car using everybody’s favorite micro-computer, the Raspberry Pi.

This one’s named Lucio, and he’s set up to do exactly that. I added a PIco UPS hat for effortless graceful shutdowns when AC power is suddenly cut. Without this, the Pi would experience tons of data corruption, a problem it’s very prone to. This little guy also has a relatively massive $5 USB audio adapter, since the one on-board is dirt.

Power is coming straight from the fuses conveniently inside the glove box (thank you Munich) into a 5V 3A step-down USB regulator. Of which, by the way, I’ve had to replace 3 times now from accidentally switching the polarity ಠ╭╮ಠ

Adding bluetooth was deceptively easy. The latest Pi V3 has Wifi/Bluetooth built in (albeit sharing a controller), and essentially all it takes is having bluetooth/pulseaudio launch at startup and routing audio to the USB sound card.

We also have a Bluetooth OBD adapter hooked up, and with the help of python-obd library I was able to collect the available data and log it to the Pi’s MySQL. There actually aren’t many values my car will let me pull, but some interesting ones like current RPM, speed, MAF intake, engine load, and coolant temp were nice as a jumping off point.

Here’s the script that’s currently running.

It has a long way to go. With almost 11 hours of driving time to play with, I did some analysis on the values being pulled in and here’s what I found:

Total rows: 44324
Total Time Recorded: 10:50:12
Average Sample Rate: 0:00:00.880155
Average RPMs: 1667
Average Speed: 35mph
Average Engine Load: 25
Average High RPM (>3500): 4258

Sampling Rate

The sampling rate was a little under a second per row, which is better than I expected but still fairly bad. Ultimately this is because of how I’m pulling the data from the OBD connector.

The script continually pulls 4 (sometimes 6) values from the car one after another, then finally pushes that collection of data as one row into the database. Each pull is blocking the script and each value must wait an entire cycle before being pulled again.

Luckily python-OBD has async functions which I plan to use in the future, breaking this massive table into several and posting data as fast as I can possibly pull it in. Continuity of the timestamps will be blown to the wind…

RPMs / Speed / Engine Load

This I just calculated for fun. As it turns out I’m a bit of a Daisy driver. 1667 average RPMs on a car that idles at ~1100 is quite low. I thought (still think?) that the time idling at a stoplight would be, as statisticians say, “mellowed the heck out” by droning on the freeway at ~3000 rpms. I believe I did enough of both in those 10 hours to strike a balance, so all that would be left is my acceleration/deceleration.

This theory checks out, since my average RPMs when over 3500 are still a dismal 4258.

My average speed I don’t even want to comment or make assumptions on. It includes the 3-5 minutes of time I let my car idle, which all pulls in at a whopping speed of 0.

Also I’m not sure what engine load is, but I can say with certainty it’s a whole 25 on average. So that’s great.


In a system where time is of the essence, I should really be using non-blocking functions. I should also open up my car more 😉

I have more ambitious plans for Lucio here, like syncing its tables to a slave upstairs or communicating all this fresh data with a Nexus 7 that’ll be mounted on the dash. But for now, I plan to churn out megabytes of my own habits.