1086

OBD2 for Raspberry Pi with Pi-OBD add-on board or DXM OBD2 module and OBD2 software taken from my other labs project Firmware Update for OBD2-Analyser NG.

This project turns the Raspberry Pi into an OBD2 on-board diagnostic tester. So, the Pi can read OBD2 vehicle data and it can read and clear emissions-related diagnostic trouble codes and inspection/maintenance readiness monitor data.

Preface
You might have stumbled across my other OBD2 project here. That project provides firmware and OBD2 software (Mingw32 and Raspbian) for the OBD2-Analyser NG published in the September 2009 issue of the Elektor magazine. However, there is one big drawback with that project: the required hardware is no longer available. Finally, my new OBD2 project will fix that :)

The OBD2-Analyser NG uses a DIAMEX DXM OBD2 module interfacing with a vehicle bus on one side and providing a serial interface on the other side. The Raspberry Pi features a serial interface at its GPIO pins. Both serial interfaces operate with 3.3V line drivers and are easy to connect. So, I came up with the idea to develop a simple add-on board for the Pi using a DXM OBD2 module. However, I did not have a spare DXM OBD2 module available. Therefore, I somehow had to find a way to use the DXM on my OBD2-Analyser NG. Its serial interface is connected to an AVR AT90CAN128 microcontroller. A free port of the AT90CAN128 is available at the OBD2-Analyser NG's expansion pin header. So, I implemented a simple firmware change to route DXM data from the serial interface to port pins accessible at the expansion pin header and vice versa. After that, I wired the pins to the serial interface GPIOs of the Pi and could successfully control the DXM on the OBD2-Analyser NG with my OBD2 software running on the Pi.

After sharing that great news with DIAMEX, my project was sponsored by them with a free DXM OBD2 module that I used to build a prototype on a breadboard. Furthermore, DIAMEX developed a Pi-OBD add-on board based on their modern AGV OBD2 module, a follow-up module to the DXM, and I added support for AGV in my OBD2 software. So, now there are even two variants to add OBD2 to Raspberry Pi:

Variant 1: OBD2 for Raspberry Pi using the DIAMEX Pi-OBD add-on board
  • Pi-OBD add-on board (*)
  • OBD2 cable (*)
  • 7" touchscreen (**)
  • Raspberry Pi/Raspbian with free serial device, e.g. /dev/ttyAMA0 or /dev/ttyS0
  • HHGui OBD2 software for the Pi

(*) Pi and display are powered via the OBD2 cable
(**) displays connected via the HDMI ribbon cable are recommended, other displays need some hardware hacks

Variant 2: OBD2 for Raspberry Pi using the DIAMEX DXM OBD2 module
  • DXM OBD2 module
  • A few additional parts like PCB (a breadboard will do), wires, connector for GPIOs, connector for OBD2 cable, optional but recommended: 2 resistors, 1 capacitor, 1 diode
  • OBD2 cable
  • Vehicle 12V socket to USB adapter + USB cable to power the Pi and the display
  • Raspberry Pi/Raspbian with free serial device, e.g. /dev/ttyAMA0 or /dev/ttyS0
  • Display for the Pi (minimum display size 320 x 165 pixels) (*)
  • HHEmu OBD2 software for the Pi

(*) displays connected via the HDMI ribbon cable are recommended, other displays that occupy (but do not use) the Pi's serial interface require 2-3 mini-clips to get access to the serial interface and GND. Instead of mini-clips, wires soldered to that pins on the bottom side of the Pi are recommended for a reliable connection. If a display uses the first 26 pins only, GND can be connected to pin 30, 34 or 39.

1. The DIAMEX Pi-OBD add-on board

The Pi-OBD add-on board basically is an DIAMEX AGV OBD2 interface combined with an automotive-proven power supply/voltage regulator for the AGV, the Pi and a display. All put on a PCB that fits the Raspberry Pi B+, 2 and 3. The complete system is powered via the OBD2 cable. The Pi-OBD add-on board contains two connectors for an OBD2 cable: a 2x5 box header or a 9x1 male pin header. Of course, connector usage is mutual exclusive. The AGV OBD2 interface on the Pi-OBD add-on board is a follow-up OBD2 interface to the DXM. It is much more configurable than the DXM.

The AGV interface supports the following OBD2 protocols:
  • SAE J1850 PWM and VPW
  • ISO 9141 (keyword protocol with 5-baud wakeup)
  • ISO 14230 (KWP2000 with 5-baud wakeup or fast initialisation)
  • ISO 15765 (CAN with 11 or 29 bit identifier and 250 kbit/s or 500 kbit/s baud rate)(*)

(*) The baud rate of the CAN protocols with 11 or 29 bit identifier and default 250 kbit/s baud rate is configurable.

The Pi-OBD uses a few GPIOs and covers some more. So, using a display connected via an HDMI ribbon cable is recommended. However, since the SPI GPIOs are not used by the Pi-OBD it is possible to build an adapter for displays connected via the SPI GPIOs.

Pi Pins and GPIOs connected to an 8x1 female header on the Pi-OBD:

Pin  2: +5V
Pin  4: +5V
Pin  6: GND
Pin  8: GPIO 14 - serial interface Tx
Pin 10: GPIO 15 - serial interface Rx
Pin 12: GPIO 18 - used for Pi-OBD module reset (pin low = reset, pin high = no reset)
Pin 14: GND
Pin 16: GPIO 23 - used for bootloader access (pin high + module reset = bootloader activated for Pi-OBD firmware update)

Pins 1, 3, 5, ..., 15 are covered by the Pi-OBD, but the Pi-OBD contains holes for mounting a connector in case a display or other hardware needs access to these pins.
A 2x1 male pin header for +5V and GND is available on the Pi-OBD to power the display.

The Pi-OBD add-on board contains 4 holes on the PCB matching the 4 holes on the Pi B+, 2 or 3. So, it can be mounted using 4 spacers and 4 screws.

2. The DXM OBD2 Module Add-on Breadboard

The DXM OBD2 module is well known to Elektor readers from the OBD2-Analyser NG project published in the September 2009 issue of the Elektor magazine and the Wireless OBD2 project published in the April 2011 issue. It is still available with updated firmware from www.diamex.de. You can get an OBD2 cable from them, too.

My add-on breadboard consists of a DXM OBD2 module, a 9x1 male pin header for the OBD2 cable, a 3x1 male pin header for the serial interface and a few wires for the connections. Additionally, I mounted a diode in the +12V line for reverse voltage protection, a small blocking capacitor near the power supply pins of the DXM and two resistors in the serial Tx/Rx lines that provide protection against wiring errors. A schematic that shows the wiring between DXM and OBD2 connector can be found in the official documentation of the DXM. Schematics showing the same wiring and a 1N4004 diode, a 10µF/63V capacitor and a 330 Ohm resistor are printed in the article of the OBD2-Analyser NG.
If you use bent pin headers and mount the DXM and the additional parts in a flat way, you should be able to mount the add-on board reversed. So that it fits under a display.

2.1 Wiring
The DXM takes the 12V from the OBD2 connector and has an internal 3.3V voltage regulator onboard. Do not forget to connect the 3.3V voltage regulator output to the 3.3V input. If you have no use for the antique PWM/VPW or K-line protocols, i.e. you use the OBD2 tester just in vehicles that use CAN protocols, you do not have to make these connections.

OBD2 connector                                           DXM module                          Raspberry Pi          
Pin   2 PWM/VPW+  -----------------------------  Pin  2 PWMP
Pin 10 PWM/VPW-  ------------------------------  Pin  3 PWMM
Pin   4 Chassis GND  ---------------------------  Pin  4 GND  ---------------------  Pin  6 Ground
Pin   5 Signal GND - Pin 4 Chassis GND
Pin   6 CAN-High  --------------------------------  Pin 32 CANH
Pin 14 CAN-Low  ---------------------------------  Pin 31 CANL
Pin   7 K-Line  -------------------------------------  Pin 33 KLINE
Pin 15 L-Line  -------------------------------------  Pin 34 LLINE
Pin 16 12V  --------  >|- diode ----------------  Pin   1 12V - capacitor - Pin 4 GND
                                                                         Pin   9 3V3OUT - Pin 14 3V3IN
                                                                         Pin 24 TXD ----- resistor ----- Pin 10 GPIO 15 Rx
                                                                         Pin 25 RXD ----- resistor ----- Pin   8 GPIO 14 Tx

Note: The DXM and AGV modules feature a command that returns the voltage measured at the module's power supply input. If a diode is used, keep in mind that the returned voltage is not equal to the battery voltage. That is due to the forward voltage drop of the diode. For the used silicon diode the drop is at least 0.7V and increases with current. So, if you later enter the system information menu of the HHEmu OBD2 software, the DXM-Voltage displayed there is less than the battery voltage.

3. Raspberry Pi

So far, I have tested the add-on boards and the OBD2 software using the following setup:
  • Raspberry Pi 2/Raspbian, official 7" touchscreen, Pi-OBD add-on board or DXM add-on breadboard
  • Raspberry Pi 3/Raspbian, Waveshare/Joy-it 3.2" touchscreen, Pi-OBD add-on board or DXM add-on breadboard (*)
(*) Since I did not use bent pin headers, the DXM add-on breadboard does not fit under the display.
Since I did not build an adapter, the Pi-OBD add-on board does not fit under the display. It can be mounted to the right or top of the Pi using just 2 instead of all 4 spacers. The Pi-OBD add-on board does not power the Pi and the display in my configuration, since I did not connect 5V. I soldered a 2x1 male pin header to Tx/Rx at the bottom side of the Pi 3 and connected Rx/Tx of the Pi-OBD there. GND is taken from pin 39. The Pi-OBD's reset and bootloader pins are connected to pin 32 (GPIO 12) and 36 (GPIO 16). The 3.2" display just covers the pins 1-26, so pins 32, 36 and 39 are accessible.

On both Pis I use the serial device /dev/ttyAMA0. Usually, that device is already used by the Pi and you have to free it.
On the Pi 3 you additionally have to reconfigure or disable Bluetooth to make that device available. Read the serial interface configuration section in the file Readme_raspberry.txt that is part of the attached OBD2 software zip-file.

4. OBD2 Software for the Pi

The OBD2 software uses the OBD2-Analyser NG firmware inside. Since that just speaks DXM, I would waste a significant amount of limited FLASH memory in the real firmware to add support for AGV that never will be used there. Therefore, I decided to make a separate version for AGV using a define HHEMU_OBD_PI set in the makefile. Furthermore, for the AGV version I disabled some OBD2-Analyser NG menus and features that are of no relevance (e.g. Beeps, Bluetooth menu, USB menu, Serial interface menu, DXM simulator mode).

So, depending on the add-on board you need different versions of the OBD2 software. The Pi-OBD add-on board needs the HHGui software, the DXM add-on board needs the HHEmu software.

The OBD2 software needs a minimum window size of 640 x 330 pixels (if a background image can be read during software initialization, see details further down) or 320 x 165 pixels without background image.

4.1 HHGui OBD2 Software

HHGui is short for Pi-OBD2 Handheld GUI. The name implies that the GUI resembles a real OBD2 handheld tester like the OBD2-Analyser NG. In fact, HHGui uses the same background image feature than HHEmu. If the image HHGuiBackgroundPic.png is found on program startup, the simulated LCD screen of HHGui is printed to the LCD area of a scanned image of the real OBD2-Analyser NG. Furthermore, the OBD2-Analyser NG buttons displayed in the background image actually function as buttons when touched on a touchscreen. That makes the illusion of a real handheld even more perfect. By the way, as long as you keep the original size and the position of buttons, you can create your own background image and use that with HHGui.

Start HHGui with
./hhgui device 115200 init=AGV
Usually, device is one of /dev/ttyAMA0, /dev/ttyS0 (Pi 3 miniUART) or /dev/serial0. The device must be free and configured (see chapter 3 above).
Further self-explanatory command line options like fullscreen or maximize combined with nocursor can be given.

If you start HHGui without background image, touchscreen control differs. Then, the visible window area is divided into 4 rectangular regions.
Clicking or touching the top left area is like pressing the Up button.
Clicking or touching the bottom left area is like pressing the Down button.
Clicking or touching the top right area is like pressing the ESC button. (*)
Clicking or touching the bottom right area is like pressing the OK button.
That allows to use even small touchscreens with 320 x 240 pixels.

  (*) The top right area additionally contains a hidden top right area with 30 x 30 pixels in size. Clicking or touching that toggles between fullscreen mode and standard window size. This is needed to be able to close HHGui on a touchscreen even in fullscreen mode that does not have a close button.

In some menus long-pressing/touching the button areas has a special meaning. E.g. long-pressing Up/Down in a list, will make a page scroll.
Long-pressing ESC makes a software reset. Then, HHGui displays the start screen and jumps to the main menu.

If you start HHGui without device and baud rate, e.g. typing just ./hhgui, HHGui is started in OBD2 simulator mode. In that mode, you can view and test all menu items and OBD2 services that are supported by HHGui. Furthermore, a lot of OBD2 parameters like the number of diagnostic trouble codes can be configured in that mode if you have connected a keyboard or if you use a virtual keyboard for input of commands. The commands are described in my other OBD2 project in the HHEmu command summary chapter.

4.2 HHEmu OBD2 Software

The OBD2 software named HHEmu is described in detail in my other Labs project here: http://www.elektormagazine.com/labs/firmware-update-and-emulator-for-obd2-analyser-ng-wireless-obd2

Start HHEmu with
./hhemu device init=DXM

That is identical to
./hhemu device 9600 init=DXM

Usually, device is one of /dev/ttyAMA0, /dev/ttyS0 (Pi 3 miniUART) or /dev/serial0. The device must be free and configured (see chapter 3 above).
Other command line options are identical to the HHGui options described above.

4.3 Other Ways to start HHGui/HHEmu

Apart from the start out of the console described above, you should take further variants into account: auto start HHGui/HHEmu in desktop or start HHGui/HHEmu via desktop menu entry or start HHGui/HHEmu via double-clicking a start script.

Create/edit a file
nano /your_path_to_obd2_software/startobd.sh

Depending on the start with or without background image it should contain the following lines:

OBD2 software with background image
cd /your_path_to_obd2_software
./hhgui /dev/ttyAMA0 115200 init=AGV nocursor maximize
or
cd /your_path_to_obd2_software
./hhemu /dev/ttyAMA0 init=DXM nocursor maximize

OBD2 software without background image
./hhgui /dev/ttyAMA0 115200 init=AGV nocursor fullscreen
or
./hhemu /dev/ttyAMA0 init=DXM nocursor fullscreen
Correct the path to your HHGui/HHEmu directory and depending on your setup correct the serial device.

If the file is not executable, enter chmod +x ./startobd.sh
If you use a system directory, you need sudo chmod +x ./startobd.sh

4.3.1 Auto start HHGui/HHEmu in Desktop

There are several ways to do that. The one that works for me is:

Start editor with
sudo nano ~/.config/lxsession/LXDE-pi/autostart
insert
@lxterminal -e /your_path_to_obd2_software/startobd.sh
before the @xscreensaver line

save and exit.
Reboot to test it.

4.3.2 Start HHGui/HHEmu via Desktop Menu Entry

Copy a xxx.desktop file from /usr/share/applications to another directory.
Change to that directory.
Rename the file to hhgui.desktop or hhemu.desktop and edit the file.
Change the Name line to
Name=HHGui
or
Name=HHEmu
Change the Exec line to
Exec=lxterminal -e /your_path_to_obd2_software/startobd.sh
Change all other lines to your needs. Especially, select a meaningful icon or create one.
Save the file, copy or move it back to /usr/share/applications (you need sudo to do that).
A new desktop menu entry HHGui or HHEmu will show up.

4.4 OBD2 Diagnostic Services supported by HHGui/HHEmu

The most important part of OBD2 on-board diagnostic is specified in the ISO 15031-5:2015 standard that is based on the SAE J1979 standard. The full name of the standard is 'Road vehicles - Communication between vehicle and external equipment for emissions-related diagnostics - Part 5: Emissions-related diagnostic services.
These diagnostic services request emissions-related data from 1-8 OBD2 electronic control units (ECUs). The main electronic control unit that delivers OBD2 data is the engine control unit (also ECU). To avoid misunderstandings engine control module (ECM) is a better name for it. For vehicles with automatic transmission the transmission control module (TCM) is also a good candidate for delivering emissions-related data.

The standard defines diagnostic services identified by a service ID (SID). Most services support different functionalities addressed by a function identifier. Depending on the SID the function identifier is called parameter ID (PID), test ID (TID), on-board diagnostic monitor ID (OBDMID) or vehicle information type (INFOTYPE).

HHGui and HHEmu support the following diagnostic services:

Service 0x01 - Request current powertrain diagnostic data
This service is used to request current data, like vehicle speed, engine RPM, coolant temperature, oil temperature, boost pressure and so on. Current data also contains inspection/maintenance readiness monitors or static data like the location and number of oxygen sensors.
The nice feature with most of that data is, that it is raw sensor data that is not yet manipulated for a gauge. So in case of vehicle speed, you get the actual speed and not the speed the speedometer is showing you.

Service 0x02 - Request powertrain freeze frame data
This service is used to get a set of saved data related to a diagnostic trouble code (DTC) that caused freeze frame storage. Some DTCs trigger saving of current data at the time the error occurred. The set of saved data is called freeze frame data. This can be inspected later to analyse the cause of the fault.

Service 0x03 - Request emissions-related diagnostic trouble codes
This service is used to read confirmed DTCs. DTCs get the confirmed status in case the DTC is caused by misfire likely damaging the catalyst(s) or if a fault has been detected by the ECU in two consecutive driving cycles under the same conditions. A confirmed DTC is indicated to the driver via the malfunction indicator light (MIL). A steady light indicates a fault that allows driving to the next workshop. A blinking light indicates a fault likely to cause further damage when driving on.

Service 0x04 - Clear/Reset emissions-related diagnostic information
This service resets confirmed and pending DTCs, I/M readiness monitor data, freeze frame data and further data. Furthermore, it disables the MIL. After this service has been executed a vehicle is not ready for inspection. It has to be driven a while until all supported I/M readiness monitors again have successfully been run.
Some vehicles/ECUs require the ignition on and engine off condition before this service succeeds. Of course, using that service without having repaired anything should be avoided. The service 0x01 PID 0x30 returning the number of warm-ups since DTCs cleared and the PID 0x31 returning the distance travelled since DTCs cleared will reveal when data has been cleared.

Service 0x07 - Request emissions-related diagnostic trouble codes detected during current or last completed driving cycle
This service is used to read pending DTCs. It can be used after repair to see if a problem has actually been fixed. It avoids having to drive for two driving cycles until a confirmed DTC would show up again.

Service 0x09 - Request Vehicle Information
This service is used to read the vehicle identification number (VIN), software calibration IDs (CALIDs), software calibration verification numbers (CVNs), in-use performance tracking (IPT) data (this contains statistical data, like the number of ignition-cycles or how often OBD2 monitors have been run) or the ECU name.

Service 0x0A - Request emissions-related diagnostic trouble codes with permanent status (CAN protocols only)
This service is used to read permanent DTCs. Each confirmed DTC triggers setting of a permanent DTC at the end of an ignition-cycle. Permanent DTCs cannot be cleared by executing service 0x04 or by disconnecting the battery. They are automatically cleared by an ECU after repair, when the ECU determins that the error condition for a fault is no longer present for several consecutive driving cycles.

The services 0x05, 0x06 and 0x08 not described here are not supported by HHGui/HHEmu yet.

Please note that OBD2 diagnostic services cannot be used to configure anything in a vehicle. Furthermore, besides the MIL no other fault lights can be reset. For that purpose manufacturer specific diagnostic services have to be used. Therefore, resetting a service interval/service now message or clearing an airbag fault light or the configuration of door locking cannot be done with OBD2.

5. Proof of Concept (The full Story)

I did not have a spare DXM OBD2 module available, but I have built the OBD2-Analyser NG published in the September 2009 issue of the Elektor magazine. That uses a DXM OBD2 module that actually can be used without desoldering it. The DXM is connected via its serial interface to the USART0 of an AVR AT90CAN128. In Bluetooth mode the latest official firmware v1.2.1 acts as a gateway and forwards the USART0 data to its port F, port pin 7 that is connected to the serial interface of a BTM-222 Bluetooth module. In Rx direction the firmware reads data from the BTM at port F, pin 6 and forwards the data to USART0 that sends it to the DXM.

So, for a quick test I used the existing gateway mechanism, but changed it to use the free port F, port pins 1 and 2. These are easily accessible at the J2 extension header pins 2 and 3 of the OBD2-Analyser NG. Ground is available at the J1 extension header pin 1.

The serial interface of the Pi uses GPIO 14 (pin 8) for the Tx line and GPIO 15 (pin 10) for the Rx line. Ground is available at pin 6.

So, for the test I made the following connections:
Raspberry Pi                       OBD2-Analyser NG                                   AT90CAN128
Ground        pin 6               extension header J1 pin 1 Ground
Tx GPIO 14  pin 8               extension header J2 pin 3 Rx                  port F bit 2
Rx GPIO 15  pin 10             extension header J2 pin 2 Tx                  port F bit 1

For the connections I used a breadboard and put small 200 Ohm resistors in the Tx and Rx lines to avoid damage, in case I would make a wiring mistake. You can see that in the attached image.

This is the hardware test setup. The software changes are implemented as part of my OBD2-Analyser NG firmware update v1.7.1. The result is a new Serial Interface Mode accessible via the main menu of the firmware. The Serial Interface Mode menu item in the main menu must be enabled beforehand by ticking the related checkbox in the settings menu.

After flashing the new firmware, the OBD2-Analyser NG can be connected to a car or 12V power supply. Then, the Serial Interface Mode menu must be entered to activate the gateway routings described above.

The HHEmu OBD2 software needs a few changes, too. These are implemented in HHEmu v2.80. If HHemu is started with a serial device given on the command line, it is waiting for a prompt from the other side. Since the DXM in my test setup is not directly connected, it does not notice that it is now connected to the Raspberry Pi. It is still conected to USART0 of the AT90CAN128 and will not send a prompt, since it already has sent one that was read by the OBD2-Analyser NG, before the Serial Interface Mode was entered. Therefore, I implemented the nosync command line option. If you connect a DXM module right to the Raspberry Pi, this change is not needed. However, you need another command line option init=DXM to initialize the DXM module. In my test setup the DXM is already initialized by the OBD2-Analyser NG firmware.

For convenience, I implemented another command line option to make the baud rate configurable. Normally, HHEmu tries to connect to a (virtual) serial interface with 9600 Bd 8N1. According to the DXM documentation, the DXM module has a factory setting of 9600 Bd. Therefore, that would match. However, during OBD2-Analyser NG initialisation the DXM baud rate is changed to 19200 Bd by the firmware. So, in my test setup the DXM module runs with 19200 Bd.