obd2diag – An OBD-II via Bluetooth Diagnostics Tool

This is the project homepage for “obd2diag”, an On-board Diagnostics (OBD-II) to Bluetooth adapter, based on the ELM-327 Controller and the BTM-222 Bluetooth module.

Please Note: This project was done many years ago, so the provided information may not be accurate / up-to-date anymore!


The obd2diag board lets you interface with your vehicle’s OBD-II port over bluetooth. Using the ELM-327 controller makes the board suitable for almost all types of vehicles. The BTM-222 Bluetooth adapter provides an elegant way of galvanic isolation between your computer and your car. Also, most smartphones are capable of pairing with other Bluetooth devices. So theoretically, one could use the obd2diag board to perform car diagnosis from a smartphone.


Most modern cars have an OBD-II interface, which is a standardized way of reading out various sensor and diagnostics data from the vehicle. OBD-II is mostly for the emission related parts of the vehicle and essentially defines three things:

  1. A standard connector and the fact that every car must have one.
  2. The kind of data that is to be provided through the OBD-II interface, e.g. emission sensors, as well as standard “addresses” for the various sensors, called “Parameter IDs” (PIDs).
  3. The “check engine” light and many error codes behind it.

Unfortunately, the OBD-II specification seems to be a combination of multiple official and/or industry standards which sometimes apparently have evolved from manufacturers’ standards. This means that there is quite a variety of different implementations.

The variety of different implementations becomes obvious when looking at the allowed protocols through which the OBD-II data may be provided. These are the onces I found out about through the various online resources:

  • SAE J1850 Pulse-width modulation (PWM).
  • SAE J1850 Variable pluse width (VPW).
  • ISO 9141-2, sometimes also called “K-” or “KL-line”.
  • ISO 14230 Keyword Protocol 2000 (KWP2000).
  • ISO 15756, in the OBD-II context often referred to as CAN.

So in summary, OBD-II defines what data must be provided, but not exactly how it is to be provided, except for the physical connector. 

Apparently, most European cars provide the OBD-II data through the K-line, which seems to be almost trivial to connect to using a computer. All it takes seems to be a USB-to-UART converter and a bunch of transistors for level shifting. A quick search reveals that fully assembled adapters are sold for around 15 EUR at the time of writing.

However, my car (an “Opel” for what it’s worth) uses the CAN protocol/bus to provide the OBD-II data, so the cheap adapters aren’t suitable for me. I did find adapters that supported my car, but they were more than 100 EUR which seemed like a bit much for basically reading out error codes.

Luckily, I stumbled across the ELM-327 controller which supports most or all OBD-II protocols. Since I was looking for a project, I decided to build an ELM-327 based OBD-II adapter to diagnose my car. Of course, buying a ready-made adapter would have been cheaper, but then again, that wouldn’t have been half the fun. The following paragraphs describe my build and how to use it.


As illustrated by the image below, the obd2diag board consists of three main parts: The power supply, the bluetooth module BTM-222 and the OBD-II controller ELM-327. The BTM-222 device operates at 3.3 Volts; the ELM-327 runs at 5 Volts. Both are connected through a UART.

Fig. 1: Block Diagram

UART connection

Because at least some level shifting logic would have been required to make the ELM-327 and the BTM-222 work together on the UART connection, and because I wanted to allow for easy debugging from a PC, I decided to add two RS-232 converters for the two UARTs. By placing two pin headers side by side, it’s easy to connect to either the BTM-222 or the ELM-327 directly. Jumpers can be used to connect the two UARTs in the finished product.

Power Supply

The power supply provides 3.3V and 5V for the two component blocks. In retrospect, I should have generated 8V off the power supply, too, because that voltage is required for some of the logic surrounding the ELM-327. That way, I would have ended up with less different parts.

The nominal supply voltage is 12V. However, from what I gathered on the internet, the car power supply can vary between 8V and 24V in various situations (e.g. car starting, jump start). Also, it is desirable to have a circuit breaker because the car battery is powerful to supply enough current to fry pretty much any kind of micro-electronics componentry. Besides that, it may be a good idea to build in some kind of reverse voltage protection. I stumbled across a sample circuit on how to build a car power supply (German) wich I decided to follow.

Finally, I wanted to be able to power the circuit from a lab power supply without too much hassle. So I added a standard connector and a jumper which lets me select whether the board is to be fed from the OBD-II adapter or the standard connector.

Bluetooth module

The connections of the bluetooth module are kept to a minimum. The only extra component I added is a blue LED that flashes when there is bluetooth activity. I figured this would help me debug. In the end, it wasn’t required. Also, the antenna is a simple piece of wire. The wire has a length of 31mm and should form a λ/4 antenna. This simple hack is enough to connect a laptop from a few meters away.


The ELM-327 part is the easiest to explain: It’s mostly a copy of the reference design shown in the device’s data sheet (pg. 67) minus the power supply and the UART connection. I did however include parts of the suggested modifications to safe power (fig. 12 on pg. 71 of the data sheet).

Physical Layout

This the first board I designed. Also, I felt that given the number of components the project requires, I wanted to have the circuit board manufactured. In order to be able to debug and correct errors later on, I wanted to add lots of debug points such as LEDs and solderable connections.


ELM-327 Commands

The ELM-327 accepts AT-style commands. The command set is documented in the user’s guide. Here’s a list of the most important commands:

  • AT Z to reset the ELM-327.
  • AT SP 0″ to make the ELM-327 search for a connection with the car.

Linux Bluetooth Serial Connection

Here’s a quick guide on how to connect to the BTM-222 module via Bluetooth on a Linux laptop. First, you need to scan the Bluetooth airspace for the device’s ID as follows:

$ hcitool scan 
Scanning ... 
        00:12:6F:22:53:53 btm222

At this point, you can connect to the device:

$ sudo rfcomm bind 0 00:12:6F:22:53:53 
$ sudo rfcomm show 0 
rfcomm0: 00:12:6F:22:53:53 channel 1 clean

The above should have made a file /dev/rfcomm0 to appear on the laptop. You can use e.g. minicom to talk to the BTM-222 through this device file. The BTM-222 is setup up as 38400 8N1.

In the serial line session with the BTM-222, you can always hit atz, which is the command to reset the ELM-327. If everything went well, it should look like this:


ELM327 v1.4b 



Here’s a set of pictures that show what the finished project looks like:  

The complete board

The complete board, in all its (reworked) beauty.

power supply jumper that selects between standard power supply and OBD-2

The power supply jumper that lets me select between a standard power supply and the OBD-2 connector.

Home-made jumpers that connect the RS-232 Ports

Home-made jumpers that connect the RS-232 Ports of the ELM-327 and the BTM-222 bluetooth module.

Adapter cables

A couple of adapter cables that can be used to connect a PC directly to either the ELM-327 or the BTM-222.

A fix for the only real errata

A fix for the only real errata on the PCB (see errata section below).

Breadboard that replaced broken CAN Transceiver

Breadboard that replaced a broken MCP2551 CAN Transceiver.


Of course, there are a few bugs in the design. The ones that I know of are documented below.

Version 1

  • The ELM-327’s UART Tx signal has the same polarity as the Rx signal and thus must not be inverted by the RS-232 converter. Solution: Connect the ELM-327’s UART_Tx signal (Pin 17) to R2OUT (Pin 9) on the MAX-232.
  • Well, not a design error, but the CAN Transceiver (MCP2551) died during one of the first tests. I replaced the SMD part with an external breadport and a DIL version of the part. It would have been better to use the DIL version of the part from the beginning.



Here are a few links related to this project.