Connecting your Raspberry Pi to a Bluetooth OBD-II Adapter
Ever heard the phrase “you just can’t work on cars these days because they’re all computerized”? Well, it’s 2013, and unless you’re an expert with pneumatic engine control systems, you’re probably in better shape working with the Engine Control Module. This post shows you how to connect your Raspberry Pi to a Bluetooth OBD-II adapter and to run a few simple commands.
First off, here’s a list of exactly what I’m using:
- CanaKit Raspberry Pi (512 MB) Basic Kit (Raspberry Pi 512 MB + Clear Case + Micro USB Power Supply)
- Plugable USB Bluetooth 4.0 Low Energy Micro Adapter (Windows 8, 7, XP, Linux Compatible; Classic Bluetooth and Stereo Headset Compatible)
- BAFX Products (TM) – PIC18F2480 Bluetooth OBD2 scan tool – For check engine light and other diagnostics – Android compatible
- 2004 BMW 325i (black)
OBD stands for On-Board Diagnostics, and this standard connector has been mandated in the US since the 1996 model year. It’s a 16 pin connector, and by law, it must be within 2 feet of your steering wheel, so it should be pretty easy to find. Mine looks like this with a little door covering it most of the time:
The OBD-II connector is how you can connect to your car’s Controller Area Network (CAN) Bus. You can collect all sorts of real-time information from the CAN Bus through the OBD-II port, and also pull any “Check Engine Light” Malfunction Indicator Lamp (MIL) trouble codes. There are two flavors of MIL codes — those that cause the MIL to light up without flashing, and those that cause it to flash. If your MIL is on, but it isn’t flashing, you have an emissions problem — basically you’re polluting the environment more than you’re supposed to, but your car isn’t really at risk of damaging itself. Lots of things can cause the MIL to light up, your gas cap could be loose, you could have a bad O2 sensor, or your air/fuel ratio may be off. Cars run by burning a precise mixture air and fuel, and if that mixture is off, the car won’t be burning fuel as efficiently as it could be. If your MIL is blinking, you should pull over. Something is very wrong.
The OBD-II specification defines 10 different modes of operation, each with a series of Parameter IDs (PID):
Once we have the OBD-II adapter plugged in and powered on, we’ll need to connect to it from our Raspberry Pi.
As you can see here, I’ve plugged my Bluetooth USB adapter into it, and I’ll be connecting over SSH for most of the rest of this (though you could just plug in to an HDMI monitor and open the terminal). I’m using Raspbian OS on my Pi, which is a variant of Debian.
There are a few things you’ll need to do to get bluetooth working on your Raspberry Pi. First off, some of this requires you to be root, so unless you’re super concerned about security on your Pi, just do everything else here as root:
pi@raspberrypi ~ $ sudo su root@raspberrypi:/home/pi#
If this is a new Raspberry Pi, and you haven’t already updated the apt-get package manager, you’ll want to do that now:
# apt-get update
*# apt-get upgrade*
These will take awhile to run, so go have a coffee or something. Once apt-get is up to date, you’ll want to enable DBus:
# update-rc.d -f dbus defaults
D-Bus is a message-bus system, a way for applications to talk to one another. It works with Unix sockets between applications and daemons. It is needed by Bluez, which we’ll be installing in a moment. At this point, however, you should restart your Pi:
After logging back in and re-entering root mode, you can then install a few bluetooth tools using apt-get:
# apt-get install bluetooth bluez-utils blueman
Now if you list the USB devices on your Pi, you should see the Bluetooth dongle connected (mine is the Broadcom Corp one below):
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 0a5c:21e8 Broadcom Corp.
Assuming everything is working, you should be able to scan for available bluetooth devices nearby with hcitool:
# hcitool scan
Scanning ... CC:6D:A0:11:08:66 Roku Player 00:0D:18:A0:4E:35 OBDII 00:0D:4B:F0:CB:6E Roku Player
You can see here, I have a few Roku boxes on nearby TVs and my OBDII adapter has an address of 00:0D:18:A0:4E:35. If the hcitool scan didn’t work, you can check to make sure bluetooth is enabled with an hciconfig command:
# hciconfig hci0: Type: BR/EDR Bus: USB BD Address: 00:02:72:C6:A6:81 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING PSCAN RX bytes:121283 acl:138 sco:0 events:12710 errors:0 TX bytes:70273 acl:104 sco:0 commands:12591 errors:0
If that didn’t work, you can check your bluetooth status:
# /etc/init.d/bluetooth status
And (re)start it if need be.:
# /etc/init.d/bluetooth [stop/start/restart]
At this point, you can pair with the Bluetooth OBD-II reader using Bluez:
# bluez-simple-agent hci0 00:0D:18:A0:4E:35
You might be prompted to enter a PIN at this point, but I wasn’t. If you are, try “1234” with this adapter. Others use “0000”. You can then make the adapter trusted so you don’t have to manually pair with it every time it becomes available:
# bluez-test-device trusted 00:0D:18:A0:4E:35 yes
At this point, after monkeying around with a variety of different bluez commands to try to connect form the command line, I gave up and launched a VNC session to us Preferences => Bluetooth Manager. You could also just plug in to a monitor, but here’s how to set up VNC if you don’t want to use a monitor:
# sudo apt-get install tightvncserver
# vncserver :0 -geometry 1920x1080 -depth 24
Once you’ve connected, you’ll have a new device at */dev/rfcomm0 *with which to communicate.
To begin to communicate with /dev/rfcomm0, you’ll want to install screen:
# apt-get install screen
And then connect to /dev/rfcomm0 with Screen. Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells:
# screen /dev/rfcomm0
Within Screen, you’ll be able to enter a number of commands. First off, you should know about some of the AT commands. These commands are system commands that mimic some of the AT “ATtention” commands of the old Hayes Modem command set. Remember “ATDT” (ATtention Dial Tone)?
First off, you’ll want to set up some formatting options, because the default is to jumble responses on top of queries, making them hard to read:
Restarts the device. You’ll need to do this from time to time.
Turns linefeeds on
Turns headers on
Turns spaces on
Set the protocol to Auto
These commands should all return a simple “OK” response from the ELM327 chip. If you want information about that chip, you can enter:
>ATI ELM327 v1.5
But that’s all pretty boring. Let’s start querying some information from the car! First off, let’s see if we have any stored MIL trouble codes with a mode 03 query:
>03 SEARCHING... 87 F1 12 43 04 44 00 00 00 00 15
I do have a stored error code of 0444 (I’ve left my gas cap loose to cause it for this demonstration). The response here is shown as a sequence of hex pairs. Directly in front of the 0444, you’ll see a “43”. This is saying that it is a response to a 03 query (the 4 indicates a response, the 3 is the query it’s responding to). The rest can be ignored.
What about pulling the VIN? That’s a mode 09 query with a PID value of 02, so we enter:
>0902 87 F1 12 49 02 01 00 00 00 57 2D 87 F1 12 49 02 02 42 41 45 56 F5 ...
This actually returns 5 frames (lines) of data for the entire encoded VIN, but I don’t really want to post my VIN to the world, so I’ve truncated the last 3 lines above. You can also pull real-time information. Here’s an example of pulling the current RPM of the engine. Real-time data is a Mode 01 query, and the RPM query is a PID of 0C:
>010C 84 F1 12 41 0C 0A DC BA
Again, we have some hex data, so how do we decode it? We’re interested in the two pairs after the response indicator, which in this case is “41 0C” (4 for the response, 1 because it was a mode 1 query, and 0C because the PI was 0C). The RPM response is reported in quarters of an RPM (don’t ask me why), and OADC in hex equals 2780 in decimal. 2780 divided by 4 = 695*RPM* which is basically just idling.
Here’s a screen capture of this basic process using the screen command:
So that’s it, that’s the basics of how to connect a Raspberry Pi to your OBD-II port on a car via Bluetooth.
Hint: you can quit out of Screen with Ctrl-A, Ctrl-D.
Here are some great places for more information: