Monthly Archives: March 2017

Dive into an OBD2 world with ELM327

Today we are going to have a bit of introduction to what the OBD2 and ELM327 is, protocols and trouble codes. This is necessary to understand what we are going to do later on.

First a dictionary:

OBD / OBD2 – OBD2 is the second version of connector that is available in all modern cars and connects to CAN bus or ECU of the car. We will use only protocols compliant with OBD2 connector, OBD is an old version to which OBD2 is not backwards compatible.
CAN – Controller Area Network, serial bus that allows car components to communicate with ECU.
DTC – Diagnostic Trouble Codes.
PIDS – Parameter IDs for CAN requests.

I am going to use ELM327 controller (or Chinese counterfeit). It is quite cheap and easy to buy and does support a lot of protocols:

0 – Automatic
1 – SAE J1850 PWM (41.6 kbaud)
2 – SAE J1850 VPW (10.4 kbaud)
3 – ISO 9141-2 (5 baud init, 10.4 kbaud)
4 – ISO 14230-4 KWP (5 baud init, 10.4 kbaud)
5 – ISO 14230-4 KWP (fast init, 10.4 kbaud)
6 – ISO 15765-4 CAN (11 bit ID, 500 kbaud)
7 – ISO 15765-4 CAN (29 bit ID, 500 kbaud)
8 – ISO 15765-4 CAN (11 bit ID, 250 kbaud)
9 – ISO 15765-4 CAN (29 bit ID, 250 kbaud)
A – SAE J1939 CAN (29 bit ID, 250* kbaud)
B – USER1 CAN (11* bit ID, 125* kbaud)
C – USER2 CAN (11* bit ID, 50* kbaud)

Modern cars usually have CAN connection, older ones may have a different protocol. Luckily there is automatic connection available in ELM which tries all the protocols and selects the working one (I assume this is the first that responded for the request).

User can communicate with ELM327 using AT commands, popular in modems communication. The specific subset depends on the controller version. There is a good breakdown of commands supported in each version in the table: https://www.elmelectronics.com/wp-content/uploads/2016/07/AT_Command_Table.pdf

The description and usage for each command is available in the datasheet for ELM372. There is also an indication for which protocol it is available which may come in handy:

https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf

Next thing are “Diagnostic Error Codes”, usually connected with “Check Engine” light:

Check engine lights.
Source: http://carcare.sg

 

 

 

 

 

 

This generally indicates current (or possible in  the future) problem with one or more parts of the engine. I have merged some data available on the internet for quick reference of trouble codes:

More or less complete list of DTC codes is available here:

http://www.launchtech.co.uk/dtc-codes-list/

There is much more data available on wiki about the OBD2 in general which might be useful later: https://en.wikipedia.org/wiki/OBD-II_PIDs

That’s all for now as it gets quite long. Stay tuned 😉

Opel Corsa D Diagnostic Mode (Test Mode)

Just a quick update. During of OBD2 connection test I have found a possibility to enter test mode in the car where I can validate results using values that trip computer receives from ECU – yay! Even though my car does not have trip computer 😀

Press km reset button four times and hold it at fourth time for 10 seconds (or just until screen changes). There will be a few screens (selectable with the same button):

  1. Car production version and date.
  2. Firmware production version and date.
  3. ???
  4. Vehicle speed and engine RPMs.
  5. Battery voltage and status.
  6. Dashboard backlight level (0-100) and coolant temperature.
  7. ??? (100 / L2 XXX)
  8. ??? (100 / S2 XXX)
  9. ??? (100 / P2 XXX)
  10. ??? (100 / t2 XXX)
  11. Fuel level in liters and remaining distance. – I don’t know what is in the second line, maybe short and long term trim?
  12. Fuel flow and fuel economy.
  13. Days and distance from reseting inspection.

What’s inside the chinese ELM327 USB

Hi,

I had to buy a few ELM327 with USB cable for different project. I have no use for USB cable as it is in the module, but I hope there is UART and kinda liked the idea of just stripping out the USB cable and replacing with the other one without changing the case.

This is it:

And without the label:

Under the label.

Screw holes, nice. But no screws inside 🙁 Just melted PCV. Well, let’s open it anyway, maybe I am missing something:

Opening the case the hard way.

With a bit of force it worked. Here is what’s inside:

   

Small chip (8 legs, one floating) is the NV342-0 which is CAN transceiver (Vsplit is N/C): http://www.onsemi.com/pub/Collateral/NCV7342-D.PDF

In the second picture a soldered on the top board has 12kHz oscilator and PL-2303HX – UART to USB converter (Prolific one).

The main controller is probably under the black blob in the middle. And the cable cannot be disconnected without desoldering.

I am actually really surprised with this, it seems to be multi-layer PCB (more than two layers for sure) with a BGA chip. Quite well engineered, maybe not so well done (handmade :D), but still, better than I predicted for the price.

NodeJS addon with C++ and Objective-C

I have finished the module a few days ago (and it does not work, check the previous post) so now it is a good time to show a bit of technical difficulties and solutions.

First things first – an introduction. What we want is a class (I think in JS more proper name is a  prototype) with a few methods:

  • StartScan – with callback for results.
  • StopScan
  • IsScanning
  • GetState – current state of bluetooth (on/off etc).

We start with a module file – obd_cougar_lib.cc, structure of binding.gyp was described before for that project so I won’t paste it again, this is the file:

https://github.com/killpl/obd_cougar/blob/master/cougar_bluetooth_lib/binding.gyp

I used nan as the whole internet recommended and ended with something like this:

Let’s divide it into parts and describe one by one. First we need a module to export information and module initialization information. First says what we want to export and second is a static function that creates that object:

We use two defines to achieve this – NODE_MODULE  with two parameters: module name and second is initialization function conveniently declared by macro NAN_MODULE_INIT  with one parameter – a name. We export here a class and a function – we don’t have to export just a one thing.

Then we need a class to export – let’s call it Cougar_Bluetooth and init from inside of Init – this is visible in the snippet above. Next create a class:

There  static NAN_MODULE_INIT(Init) method which initializes class by setting a class name with

and constructor (the “new” method) with:

Of course we need methods inside the class too:

Method static NAN_METHOD(New) is our constructor, but in JavaScript we have to take care also for the possibility of using the constructor without the new operator – we just call the constructor with provided arguments in that case. Also we have a static field to hold that constructor. There we use a trick to avoid initialization in another file – we don’t need this if it is static variable in static method, so we return a reference to that object:

Last but not least I will show you how we can create a method in the class, this time descriptions will be inline in code:

That’s all. I have tested callback with simple logger class (to log messages from the addon to JS console) and it works. There were no callback calls for scan, because my devices are not BLE.

Seems quite easy at this point, but believe me – it wasn’t. At least it is not when you don’t have a code that you can copy and paste or clone.

CoreBluetooth and bluetooth devices enumeration on OS X

So ending our adventure with first module – bluetooth devices enumeration I have bad news. OS X does not support programatically enumeration of generic Bluetooth devices. There is CoreBluetooth, but it works only with BLE (Bluetooth Low Energy). There is the GameKit, but it only works if you want to pair two or more devices with specified service type – in most cases iPhone with Mac. I wanted something like this:

So we have now a module that enumerates BLE devices nearby. And ELM327 is not a BLE device. GREAT 😀

Anyway, I have learned a lot about what is not possible and a lot about what is not. For new it will be enough to tell user to just connect the device before use. Whole prototype project is in this commit:

https://github.com/killpl/obd_cougar/commit/f2a2e32ef41cef369ac94a7e5e7bf3dad18df147

In directory prototypes. Next article (soon) will be more technical about module developement based on cougar_bluetooth_lib module.

Testing ELM327 without the car

Hello!

It’s winter here and so I have decided to explore possibilites that might help me avoid programming in the car. First it is cold, second it is not comfortable at all. At some point I have to go outside, but not just yet.

I bought OBD2 male connector (the same one you have in your car) to power up the ELM327 on my desk  with no CAN connection. Let’s take a look at OBD2 schematics:

OBD2 pinout schematics.

OBD2 connector pinout schematics.
Source: instructables.com

I need to power up the ELM327 – the start sequence after power-up is self test, then it starts to broadcast Bluetooth. So I can develop the connection library, test sending and receiving messages over bluetooth and even check voltage. Clever, especially when it is cold outside and you don’t have the garage. Or you live in Russia.

Anyway, to start we need 12V on pin 16 and ground on pins 4 and 5 (I have checked with multimeter and my adapter has those pins bridged, so I actually needed just one). This is how the connector looks like (black ground, red 12V):

OBD2 connector on the desk with wires attached.

OBD2 connector on the desk with wires attached.

Few hours later I connected it to the stabilized DC power supply where I set 12V – it should work fine on PC power supply too if you don’t have lab power supply on your desk:

ELM327 connected to the power supply with my connector.

ELM327 connected to the power supply with my connector.

It works (red light on the right), there was a boot sequenece and self test visible too, but it’s hard to capture it on the picture. And surprise – 30mA for idle, 42mA on start. This was really strange for me, as far as I know whole car with ignition off usually draws 30-50mA. This is a lot.

A good example how OBD2 pins should not be soldered.

A good example how OBD2 pins should not be soldered.

So I took the whole connector apart and soldered the wires.

Damn, too much solder, I had to repeat the process 🙁 It did not help at all anyway. Strange. I have to add it to the things to consider for later, I don’t like it to draw so much current on idle, or maybe it is not idle?

Let’s connect and check the connection, there is OBD2 on the list (or just a mac address, after double click it will be renamed). Default passcode provided by Apple was 0000, it did not work, I had to put 1234:

macOS devices list with OBD2 adapter ready to pair.

macOS devices list with OBD2 adapter ready to pair.

I tried Cornflake as a serial GUI application, but it does not work at all, so I have used terminal with screen (38400 is a baudrate) – make sure that bluetooth devices list says “not connected” until you actually run the command:

screen /dev/tty.OBDII-SPPDev 38400

Terminal with screen connected to OBD2.

Terminal with screen connected to OBD2.

AT L1 command sets the line feed to be sent by the device – it is hard to read responses when terminal tries to put them in the one line.

AT I is an Info command, @1 displays device informations.

AT RV is a Read Voltage command, it should display voltage on the battery pin. Shame it did not, I have 12V with tolerance of +/-0.05V here. Great it could be calibrated, so I set the 12.00V with Change Voltage command and from now on I am going to have better readouts of my car battery voltage.

Node Module Version Mismatch: Expected 50

Today I got the same error as in the title. Installed nvm, tried all versions of node from 6.8 to 7.1 which reulted in 48 and 51 result mode version (in file config.gypi).

So I’ve opened Electron page https://electron.atom.io/ and checked current Electron and node versions. Then a few commands to run:

And it does not work anyway… And there is no indication what is wrong, except now Electron expects NODE_MODULE_VERSION 53 and I have somehow 51. Checked node_version.h file and there is #define NODE_MODULE_VERSION 51 . So nothing wrong and still does not work.

I have searched for NODE_MODULE_VERSION 53 and noticed that it is on master for Electron, which is 8.0. And there is no Node 8.0 in nvm (and I won’t like to use alpha version anyway). So blind guess – downgrade the Electron:

And now bozon start  works fine 🙂

 

@Edit:

Got today once again:

So just a reminder – after the restart it is mandatory to use nvm use 7.4 again 😉

Binding.gyp file for Objective-C++ project built using XCode

Hi!

Last time we started with the project and I promised that next will be an addon. I don’t have it finished yet, but stepped into an unknown teritory of configuring everything to compile and link find with an Objective-C(++) code and native macOS libraries: CoreBluetooth and CoreFoundation.

There are not many informations at all on the internet about how to make it work so I had to do a lot of guessing and trying.

First I made a rookie mistake (I am a newbie with Node addons so no surprise here) and added include_dirs at the wrong level of the file. Which made it unusable for both Xcode and node-gyp.

And I spent a few hours just setting it manually in Xcode settings (some of node-gyp commands remove the project file, node-gyp rebuild  for example, or just node-gyp clean ) before I found the problem.

I was really pissed off at the moment when I have found out that most of settings that I put there were just not parsed at all because there were not added as a child element of target.

Anyway.

We need to build on OS X using native libraries. I wanted to use Objective-C too just to try how it works. So first we may add .m and .mm files (.m is Objective-C, .mm is Objective-C++ – there is not much difference between them, second just allows C++ code inside) so my “sources” now looks like this:

Of course it won’t work now. We need to change at least two more things. First (this is not mandatory, but I really recommend that) we add conditional settings based on operating system. This way we will not break compile on another platforms in the future:

Then we populate the “mac”:

Notice how libraries are imported (“link_settings”). Somehow for one library it is:

It does not work for more than one though, tried using comma etc. The way I put it works.

Next thing is CLANG_CXX_LIBRARY which means I can use C++11 and -ObjC++ which tells the compiler that some of the code will be in Obj-C.

Now also project created with this command works and can be built using Xcode:

This works fine so I will now try to finish the library and add some logging possibility. Stay tuned 😉

Let’s start with C++ NodeJS addon

First things first – I know literally nothing about NodeJS C++ addons. I have an experience with C++ and with interopearation between C+++ and other languages, but not JavaScript and definitely not NodeJS (except small, top-secret project in bozon).

So we are going to learn together ;] Happy?

Let’s get started with getting project structure prepared – current architecture divides the project into (at least) three layers, which makes it kind of “Buissness Logic Desing Pattern”:

  • JavaScript / HTML presentation layer.
  • JS / NodeJS thin proxy as a business logic.
  • C++ addon for NodeJS for whole OBD2 protocol and connection.

The first layer has to run on desktop – which does not often happen for JS apps. That’s where Electron kicks in. It is a framework for building desktop apps with NodeJS, HTML and CSS, which nicely fits my needs.

Sometimes I am actually a lazy person and don’t like to create whole project structure by hand, so for that I’ve been using Bozon. It is not perfect, but creates a project scaffolding with build script, run script and unit testing script (created with Gulp, whatever this is). Exactly what I need, everything else I can do myself. You can see it created yourself in this commit.

Okay, enought about libraries, let’s start with creating NodeJS addon in C++, so we can see how it works.

First we create a source code of our binding layer file as described in documentation:

Then we have to create a binding.gyp describing build configuration:

At the end install and run the node-gyp:

Now we have a scaffolding for the C++ plugin which can be easily built. There is one more thing actuall, I don’t like writing C++ in the notepad, so I wanted to have an XCode project and this is quite easy to do with one command:

Clever. The build does not work without node-gyp configure ran after though.

Then we want nan module which creates an abstraction between v8 and node version and our C++ code. I wanted to do this myself, but there is no need to reinvent the wheel:

And change our bindings file, there should be added information about include directories:

Now every use of #include <node.h>  should be replaced with #inlcude <nan.h> .

Also if you use like me Xcode you need to edit project “binding.xcodeproj” and add to search paths nan directory:

Also we will in the future have more than one NodeJS library so we might want some common code – path to headers should be added the same way.

This is all for now, in next post we are going to try this with bluetooth enumeration on macOS and think about why node-gyp does not create proper project with HEADER_SEARCH_PATHS.