FreeEMS

It has been a while since my last post, and I apologize for that. Between buying a house, and traveling for work, I’ve not had much time for silly things like updating my blog :) . As a few people are aware, I have a 1987 Camaro that has been nonfunctional for about 4 years now. It’s gotten to the point where I’m just sick and tired of looking at it, so I’ve lately embarked on a project to build my own ECU for it. Lucky for me, there is a FOSS Do-It-Yourself EFI as it were . In talking to the lead developer, it seems that they don’t really have any decent tuning client to assist with tuning the already very runnable codebase. This is where I saw a niche that I could fill. Enter: EMStudio. C++ Qt based tuner for the FreeEMS ecu. Thus far it has a fairly small feature list, it can open/edit ram data on the device, either via hex edit, or 2d table view , and display live data in a table or on gauges. All in all I’m very proud of how far it’s come and what it can do in such a short amount of time.

I just wanted to give a small update as to what I’m working on. I’m not dead or gone, I’m just busy.

Visit to Scantool.net

So for the past month I’ve been on travel for work in Arizona. Yesterday I was on my way home, and happened to be in Phoenix. As it turns out, scantool.net’s HQ is located in Phoenix so I dropped by for a visit. I had not initially realized how large of a staff they have on site, but a good number of them took time out of their day to talk to me and I really appreciate that. I actually wound up being there for several hours. Between discussions over CAN network and sitting in the Chevy Sonic I had rented to decode a variety of CAN messages using their can sniffer, it was a very eventful and interesting day.

Initially we got into discussions about CAN based OBD2 messaging, specifically the meanings of the different identifiers in 11bit vs 29bit. It seems that there were a few different modes of CAN That I was confused about the OBDLink MX’s return values for. There are a few different CAN modes that the OBDLink MX supports, the main differencing factors are 11vs29bit, and 15765 vs 11898 protocols. 15765 has an extra byte in the return for PCI, or Protocol Control Information field, defined here. This was of course, throwing my software through a loop since I wasn’t handling this, and this made for an extra byte on top of everything else. 11898 CAN does not have this identifier, since it is just RAW can values. The OBDLink does not actually return what is listed in the wikipedia article on CAN_Bus, adding even more confusion. The underlying CAN hardware internal to the OBDLink MX strips out start-of-frame, the RTR/IDE bits, and the DLC (unless otherwise requested to show it via ATD1 if I remember correctly).

Armed with this new information, we moved into a conference room, set up one of their wonderful OBD2 simulators, a Y cable, and a second laptop/tool to attempt to try out my new CAN Parser software to sniff what a CAN datatool is doing. Of course, as with anything technology we ran into a few issues. The first of which was the fact that I was running linux. When connecting over rfcomm using a bluetooth adapter on linux, you have to manually bind the rfcomm channel on your device to access /dev/rfcomm0. This is a bit of a hassle, since upon power cycling the device, or disconnecting screen from that particular pty, it breaks the connection and you have to unbind and rebind, which doesn’t seem to work 100% of the time. This is not an issue with the Obdlink MX, this is a linux issue since windows has no issues keeping the com port connected and active even under device powercycles. I will have to investigate more thoroughly if there is a method for easy connecting under linux.

The few times we actually got it to work, I realized that there were a lot of contingencies I did not actually plan for in the writing of my CanParse application. So after some mad random coding, and a bit of pizza and soda (thanks guys!), we moved out into the car. Jason, from what I can tell (forgive me if I get this wrong), one of the hardware guys hooked up his can sniffer to the Chevy Sonic, while I hooked up the OBDLink MX via Y-cable. Couple of weird things happened, including the rpm dial flickering up and down and random dingings of the door alarm, even when the door was closed. We figured this was just his can sniffer doing something weird, and moved on. Unfortunately I did learn that my CanParse application is missing a few key usefulness features that will be required before it is used in such a fashion to actually decode what is happening on the CAN bus. I will be detailing these in a later post as I write them into the code. Using Jason’s scan sniffer application, we were able to decode several things over the course of about two hours, including how to control the radio from the steering wheel controls, and how to identify when the lock/unlock and blinkers went on and off. We were unable to control the blinkers or locks, possibly due to a gateway node on the CAN network blocking our traffic, or us just not seeing the proper commands and only viewing notifications. Not entirely sure, but it was still very cool information to have. Just an example, but one could write a piece of hardware that monitors the CAN network, and logs lock-unlock events, turn signals, speed, rpm, a whole bunch of values to identify if someone is driving the car appropriately, or dangerously. I can think of a couple companies which could benefit from this, a couple who would want this, and a couple who NEED this :) .

Couple of other key things to note that came out of this meeting. There is an asynchronous communications mode that is eventually planned (ATMA mode with bidirectional communication), however logistically it’s not simple, so it may not happen very soon. It is definitely on their minds though, which is a huge bonus to the CAN crowd. I know that pretty much anyone with a MX and a CAN car would benefit from this, so I can only hope that they implement it soon.

The other thing had to do with CAN masks, I’ll go over that in my next post along with ATMA/STMA/STM differences.

Couple of pictures.

 

Their offices, they have cubicles

This is the back side of the cubicles. They’re not too large. There is a little white fan looking thing to the left of the paper cutter. It is a Wimshurst Electrostatic Generator. And let me tell you, even through 4-5 people, it still hurts.

This is the lab, they have cool workbenches for assembling stuff ESD safe-like.

And last but not least, me standing with the guys who took so much time out of their days to talk to me and deal with all my questions. From left to right, Joe, Jason, Me, Vitaliy, Vitaliy. That’s right, there are two of them. And I thought it was a unique name :) . Thanks again guys!

OBD2 CAN Parsing

So I’ve been on travel for a few weeks, and the rental vehicle I got is a Chevy Sonic. Ignoring the fact that it’s a brand new shitbox, I noticed that it has GMLan. I fortunately brought my OBDLink MX along with me so I can plug in and play with the car. Upon playing around a little with a terminal I found that messages go by so fast, that it’s really not practical to use a terminal at all for monitoring CAN messages. I put together a little CanParser application to assist in the process, and this lead me to try and figure out exactly how to parse CAN messages.

For all intents and purposes in the automotive world you can break down CAN messages into 11bit, and 29bit. This is how many bits are in the header of each message. The Sonic uses both, however predominantly 29bit so that is where I focused my efforts. Let’s take a long at some messages.

10 30 40 58 C0 9A 01
10 22 00 40 00 00 00 00 0F FD 00 00
10 30 80 60 C0 9A 01
10 22 E0 40 00 1B EC C3 C0 49 0A C6

10 30 40 is the header for the first message, and the rest is the actual message. The header can be broken apart into priority, param, and source IDs. The priority is bits 4,5, and 6 of the first byte, so that would be a priority of 4. Param is split between the first three bytes. Two bits of the first, the entire second, and third. Source is then the 4th byte This may seem a bit confusing, so I’ll break it down bit by bit. Say we have the message:

10 0A C0 97 82 08 01 FF D4
The header is 10 0A C0 97
  1  |   0  |   0  |   A  |   C  |   0  |   9  |   7
0001 | 0000 | 0000 | 1010 | 1100 | 0000 | 1001 | 0111
Written another way:
000 | 100 | 00000010100110 | 0000010010111
0     4         56               97

Skip 3 bytes in the front, then the next 3 is the priority, b100, or 0×04.
The next 14 are the paramID, 0×56, and the last 13 are the source ID, 0×97. then the rest of the message, 82 08 01 FF D4 is the packet that we want to play with. Unfortunately this is as far as I have gotten. I’ve not been able to figure out what any of the messages on the vehicle mean yet, but I’m slowly working on it.

I also have not yet been able to figure out how to parse 11bit CAN headers, with any luck that will be next.

ObdLibSharp

I’ve recently taken libobd, and ported it to c#! It actually wasn’t all that difficult to do either. A long time ago when I first started writing libobd, I made the decision to keep the core communications library, the one that handes the actual serial communication, parsing out messages, but not handling them, as a seperate library. It’s compiled into libobd, but it’s written in pure c++ so it can be compiled on any platform without library dependancies. This allows my to export functions and hook into them from any language, for instance, from c# using pinvoke.

pinvoke is a very powerful tool that allows you to load a library at runtime, and call functions within that library. The main limiting factor, is that the functions must not be name-mangled, as a c++ compiler often does. Compiling functions defined as extern “C” causes the compiler to not mangle the names, and thus allows me to call the functions from c#. Below are a few of the functions I put into libobd to allow me to use it:

__declspec(dllexport) void *obdLibNew()
{
return new obdLib();
}
__declspec(dllexport) int obdLibOpenPort(void *ptr,const char *portname,int baudrate)
{
obdLib *lib = ((obdLib*)ptr);
return lib->openPort(portname,baudrate);
}

The declspec(dllexport) means that the function will be exported with cdecl calling convention. This is important, as here are the counterpart function prototypes in c#:

[DllImport(obdlibloc, EntryPoint = "obdLibNew")]
public static extern IntPtr obdLibNew();
[DllImport(obdlibloc, CallingConvention = CallingConvention.Cdecl)]
public static extern int obdLibOpenPort(IntPtr ptr, String portname, Int32 baudrate);

The way this works, is I can call obdLibNew() from c#, and it returns an IntPtr. this IntPtr is a pointer to the actual instance of the c++ library. While technically this is having unmanaged code inside c#, and therefore very dangerous, if done correctly is is a perfectly fine and valid way to interop between C++ and c#. One issue that I ran into, was how to pass a string from a c# application into the C dll file. This was easily solved by using byte[].

__declspec(dllexport) bool obdLibSendObdRequest(void *ptr,const char *req,int length, char *reply,int replylength,int sleeptime, int timeout)
{
obdLib *lib = ((obdLib*)ptr);
std::vector<byte> replyvect;
if (!lib->sendObdRequest(req,length,&replyvect,sleeptime,timeout))
{
return false;
}
if (replyvect.size() > replylength)
{
//Not enough room in the buffer
return false;
}
for (int i=0;i<replyvect.size();i++)
{
reply[i] = replyvect.at(i);
}
return true;
}

[DllImport(obdlibloc, EntryPoint = "obdLibSendObdRequestString", CallingConvention = CallingConvention.Cdecl)]
public static extern bool obdLibSendObdRequestStringTwo(IntPtr ptr, String req, Int32 length, byte[] reply, Int32 replylength, out Int32 returnlength, Int32 sleeptime, Int32 timeout);

What this does, is it allows me to say in c#:

byte[] mybyte = new byte[1024];
int retlength = 0;
obdLibSendObdRequestString(ptr,”010C\r”,5,mybyte,1024,out retlength,10,1000);

This passes mybyte into the function, so mybyte is automatically filled with the reply, and retlength tells us how much of mybyte was used. It may seem hokey, but it works really well and reliably every time. This has allowed me to create a c# wrapper for the underlying obdlib class: http://www.mp3car.com/showthread.php?t=150896

So if you’ve ever wanted to integrate obd2 into a .net application but didn’t know where to start, there you go!

This is also available on libobd’s git at https://gitorious.org/libobd

 

 

 

CuteIPC

A project I’ve been working on, and testing in conjunction with tripzero, is something I call CuteIPC. Play on words for an Inter-Process Communication framework based off Nokia’s Qt (pronounced cute). The entire concept for this came from one of many arguments I have with tripzero, in which I proclaim that my monolithic style carpc frontend for the Windows Operating System is more beneficial from both a development and user standpoint than his multi-process Linux based concept. I’ll spout about exactly what that means in a later post.

As I often do, I gave trip the benefit of the doubt. We started discussing the limiting factors of a multi-process approach to a piece of software, and what hurdles would have to be overcome to make multi-process programming efficient. The big one was a lack of a decent cross-platform IPC framework. Qt has internally several IPC classes, however they all had limiting factors that guided us to the decision that we would have to write our own. The idea was to emulate the server-client architecture of dbus, where clients could offer services for any other client to take advantage of.

The implementation details involved the server running a TCP daemon on a offbeat port of localhost, so any client could connect, register its presents on the “bus”, and communicate with other clients connected to the bus. This is about how the typical IPC that I came across had worked. So why write our own? In three words: QObject JSON Proxies. What this does, is it allows me to procedurally generate class definitions of any client on the bus in JSON. Basically defining the interface that is exposed on the bus. Function calls, Signals and Slots, Properties, etc. Once these are defined in JSON, they are transmitted across the bus to any client who requests it. The client can then generate a header in ANY language, using this JSON as a definition file for how to generate the interface header.

Through some fancy code-trickery, this allows an application developer who is writing a GUI application, to access and use say, OBD2 functionality as if it was built into their program, even though it is seamlessly being ported over the IPC. An example is in order I believe.

{ “busname”:”revfeobd”, “name”:”RevFEObd”, “signals”: [ { "name":"pidReply", "args": [  {"type":"QString","name":"mode"}, {"type":"QString","name":"pid"}, {"type":"int","name":"set"}, {"type":"double","name":"time"} ] }, { “name”:”protocolReply”,  “args”: [ {"type":"QString","name":"protocol"} ] }, { “name”:”mfgStringReply”, “args”: [ {"type":"QString","name":"mfg"} ] } ] , “slots”: [ { "name":"deleteLater", "args": [ ] }, {  “name”:”addPid”, “args”: [ {"type":"QString","name":"pid"} ] } ] }

Looks like a mess dosen’t it? What this actually does, is define an interface for the RevFEObd class on the bus under the name revfeobd. Using this JSON as a template, we can generate this header file:

#include <QObject>
#include <cuteipc.h>
class RevFEObd : public QObject
{
Q_OBJECT
public:
RevFEObd(CuteIpc *ipc) {
m_ipc = ipc;
m_ipc->addObject(this);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”pidReply”,this,”pidReplySlot”);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”protocolReply”,this,”protocolReplySlot”);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”mfgStringReply”,this,”mfgStringReplySlot”);
}
CuteIpc *m_ipc;
signals:
void pidReply( QString mode,QString pid,int set,double time);
void protocolReply( QString protocol);
void mfgStringReply( QString mfg);

public slots:
void pidReplySlot(QString mode,QString pid,int set,double time) {
emit pidReply(mode,pid,set,time);
}
void protocolReplySlot(QString protocol) {
emit protocolReply(protocol);
}
void mfgStringReplySlot(QString mfg) {
emit mfgStringReply(mfg);
}
void deleteLater() {
m_ipc->callFunction(“revfeobd”,”RevFEObd”,”deleteLater”,QList<QVariant>());
}
void addPid(QString pid) {
m_ipc->callFunction(“revfeobd”,”RevFEObd”,”addPid”,QList<QVariant>()<<pid);
}
};

Ignoring all the bad formatting, this is generated procedurally at runtime. You can then compile this header into your application, and you have direct access to OBD2 functionality. Of course this still leaves the option of directly accessing the IPC and sending JSON calls directly, but the header generation provides for a much easier interface for those unfamiliar with JSON. It also allows for generation in languages other than c++. I’ve already gotten mostly written a c# header generator, which will allow for .net applications to take full advantage of anything running on the IPC bus.

OpenSSL and Qt on windows

Apologies for the long length in time between posts. I’ve been pretty busy, between looking for a house, and working long hours, I’ve not had much time to myself to post here. I’ll try to post more often. I do have content to post, just not the time to sort it out into comprehensible and informative posts.

Anyway, as part of my RevFE project, I’ve been working on an interface to mp3car’s AutoAppMart to allow for runtime download and install of plugins and misc applications. I do most of my development on Linux (kubuntu yay!), and then transfer source over to windows to compile and test for releases. I’ve gotten most of the core functionality to connect to the AutoAppMart and download apps complete, so I was transferring over to windows to compile and test when I noticed that I was unable to connect at all. After some digging I realized that the AutoAppMart uses https to communicate with the AutoAppMart itself. This is all find an dandy in Linux, since by default Qt comes with SSL built in, but in windows it fell flat on its face.

To use Qt in windows is usually a fairly lengthy process
1: Download MSVC++ express
2: Download Qt latest source, extract.
3: Wait 3-4 hours for it to compile
4: Done

However, doing it this way caused SSL support to be nonexistant. So, doing a bit of research I discovered that you can download OpenSSL in windows, compile it and point Qt to it for it to work. To install openssl, you go to their website, and download the latest. I used 1.0.0g with Qt 4.8.0 and it worked fine, your mileage may vary. You also need some version of Perl, I used ActivePerl, though any should work. Extract OpenSSL to any location (I used c:\openssl), then cd to that directory and run:

perl Configure VC-WIN32 no-asm –prefix=c:\libs\openssl

Assuming oyu want to use c:\libs\openssl as the output directory. Then type

ms\do_ms
nmake -f ms\ntdll.mak

This will generate and compile OpenSSL using nmake’s makefiles, and will generate linkable dll’s and lib files. Once this is complete, you have to recompile Qt. Go to the Qt directory, and run

nmake confclean

Wait 30 minutes while it cleans Qt

configure.exe -platform win32-msvc2010 -opensource -shared -debug-and-release -openssl-linked -I C:\libs\openssl\include -L C:\libs\openssl\lib

When it lists the included modules, be sure it says OpenSSL: linked. This means that you will have OpenSSL support available to you for your own applications.

Most of this information came from this blog, so thanks to him for posting it up. I figured I’d repost here just in case someone came across mine in search of the same answer.

VLC Video on a QML Surface

One of my ongoing projects, is a information and entertainment software for use in an automotive environment on a carpc, or a Frontend, called RevFE. It is written in c++/Qt like a lot of my projects, and makes heavy use of QML for the entirety of it’s GUI. Very recently I switched from Qt’s phonon, to libvlc to play the audio, and I found some interfaces that would allow me to play video as well, but it’s not exactly straightforward.

The best example of what I was trying to do came from the libvlc doc pages: http://wiki.videolan.org/LibVLC_SampleCode_SDL

This is close to what I’m trying to do, since QML is QGraphicsView based, I am unable to simply pass libvlc a winid or xorg window handle to paint on, I have to actually do the painting myself. I figured the best way to achieve this, would be to have the scene update an image in the background, and paint it on the screen every so often (30-60 frames per second or so). To create a custom QML item, you can subclass QDeclarativeItem, and override the function  paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget). I did just this:

void VideoWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
pixmapMutex.lock();
painter->drawImage(0,0,*pix);
pixmapMutex.unlock();
}

The mutex of course, is so that I don’t accidently write on the image while I’m drawing it. So this was simple enough, I was now painting an image (QImage) pix, onto the screen. As per the libvlc doc example, I now wanted to take the image data and put it into my QImage. You do this via the lock, unlock, and display static (or at least global) functions. Conveniently, they allow you to specifiy your own data pointer, so passing my QDeclarativeItem based class as that pointer, I can access my pixmap and mutex.

static void *lock(void *data, void **p_pixels)
{
((VideoWidget*)data)->pixmapMutex.lock();
*p_pixels = ((VideoWidget*)data)->pix->bits();
return NULL;
}
static void unlock(void *data, void *id, void *const *p_pixels)
{
((VideoWidget*)data)->pixmapMutex.unlock();
//((VideoWidget*)data)->update(((VideoWidget*)data)->boundingRect());
}

Inside the lock function, I’m setting p_pixels to the actual data on my QImage. This allows libvlc to directly draw into my QImage’s memory space, rather than me having to take care of it. Then, in the unlock, I’m calling update on my QDeclarativeItem, to make it redraw the screen and display the frame. This worked alright, but used a lot of CPU usage, so I commented that out, and made a timer to call update(boundingRect()); 50 times per second. This makes for smooth video, without excessive CPU usage. A simple application only playing a dvd iso video, uses from 10-15% cpu on an average dual core cpu (2ghzish core2duo).

Overall the method worked excellently, and I integrated it directly into RevFE, so it now has the ability to play videos on a QML surface. This will let me move the video with animated smooth movements, have fading controls as an overlay, and do pretty much anything QML can dream of, to the video surface. Final implementation can be seen here:

https://gitorious.org/revfe/revfe/blobs/master/plugins/mediaengine/videowidget.h

https://gitorious.org/revfe/revfe/blobs/master/plugins/mediaengine/videowidget.cpp

https://gitorious.org/revfe/revfe/blobs/master/revfe/QML/video.qml

These are in git on the master tree, so they may change, but they should be the same files.

ObdTool

For lack a better name, that’s what I’m calling my software at the moment. All this playing around with libobd and Mode $06 data, and I figured I needed a really good application to actually display the data as I’m parsing it out. ObdToolbox wasn’t a horrible attempt, but looking through it I found it very outdated. It didn’t even work with the latest versions of libobd and would require way too much work to get running again. So I took what I had learned and applied it to a new application, which has come out much better than expected. The application itself is still a work in progress, but it is coming along nicely and there are a lot of really cool features that I’ve pulled over from working with OBD2007 (and some of them, improved).

Main connection screen. This screen displays a good amount of information about both the scan tool, and the vehicle it’s connected to. I like the idea of an overview screen of sorts, just to give you an idea at a glance what’s going on.

 

Same screen, but with the information populated via Chunky_Ks’s wonderful obdsim. I highly recommend it for anyone attempting to do any sort of OBD2/ELM programming. I’ll have to do a post on his application at a later point. As you can see, ObdTool scans the vehicle to see if it supports different Modes.

 

One very interesting feature of ObdTool, is its ability to use QML Gauges. I’ve embedded a QML window within one of the tabs, which reads in an external QML file to display live analog gauges of values. In addition to that, ObdTool can be launched in a touch friendly gauge mode, complete with menu for setting com port and connecting/disconnecting all from a touchscreen.

 

I’ll put a couple more screenshots at the bottom for some of the more interesting features of ObdTool. One of the cool things about programming, is that every time I write an application I learn new things both about my own programming style, and about the language that I’m using. It also provides an opportunity in this case, to learn a lot more about the inner workings of OBD2 and modern vehicles as well. I’ve amassed a good amount of documentation about OBD2 which I’m sure will provide very useful in the future. I’ve posted some of the links below the screenshots at the bottom.

 

 

Here are some links that I’ve found really useful, but weren’t all that easy to find:

GM Mode $06 Information
Ford OBD2 Information
Wikipedia Technical article on OBD2 PIDS

More Mode $06 Parsing

After doing a good amount of additional research, I’ve managed to parse out a good amount of what Mode $06 message replies mean (At least on a CAN vehicle).

Sending 0600 gets you a list of Trouble ID’s (TID) between 0×00-0x1F supported, 0620 gives you 0×20-0x3F and so on up to 06A0. Parsing this the same one as you parse 0100, and we get a bunch of messages we can send.

Request: “0601″
Response: “7E8 10 1C 46 01 81 0E 0A CB 7E8 21 06 54 0E D8 01 87 10 7E8 22 00 9D 00 00 01 2C 01 7E8 23 88 10 00 84 00 00 02 7E8 24 58 00 00 00 00 00 00 ”
Request: “0602″
Response: “7E8 10 25 46 02 01 0A 0E 68 7E8 21 00 00 FF FF 02 81 0E 7E8 22 03 59 00 DC 0B B8 02 7E8 23 85 B1 F8 AA C5 68 00 7E8 24 00 02 86 10 03 92 00 7E8 25 00 17 70 00 00 00 00 ”
Request: “0605″
Response: “7E8 10 1C 46 05 81 0E 0A E5 7E8 21 06 54 0E D8 05 87 10 7E8 22 00 6B 00 00 01 2C 05 7E8 23 88 10 00 5D 00 00 02 7E8 24 58 00 00 00 00 00 00 ”
Request: “0606″
Response: “7E8 10 25 46 06 01 0A 0E 68 7E8 21 00 00 FF FF 06 81 0E 7E8 22 03 46 00 DC 0B B8 06 7E8 23 85 B1 F9 40 C5 68 00 7E8 24 00 06 86 10 03 3A 00 7E8 25 00 17 70 00 00 00 00 ”

Take the first message:

“7E8 10 1C 46 01 81 0E 0A CB 7E8 21 06 54 0E D8 01 87 10 7E8 22 00 9D 00 00 01 2C 01 7E8 23 88 10 00 84 00 00 02 7E8 24 58 00 00 00 00 00 00 ”

Split that on the header 7E8, and you get

7E8 10 1C 46 01 81 0E 0A CB
7E8 21 06 54 0E D8 01 87 10
7E8 22 00 9D 00 00 01 2C 01
7E8 23 88 10 00 84 00 00 02
7E8 24 58 00 00 00 00 00 00

Remove the header and counter bytes, reorganize the arrangement of the bytes

0181 0E 0ACB 0654 0ED8
0187 10 009D 0000 012C
0188 10 0084 0000 0258
00  00 00 00 00 00

So we have three messages for OBDMID (OBD Monitor ID) 0×01. TID 0×81, TID 0×87, and TID 0×88. All three of these are manufacturer specific TID’s, so we don’t actually have any information on what they mean, but we can still parse out the values. The third byte signifies how to parse the messages 0x0E means the result is in Amps, and you multiply it by 0.001. The fourth and fifth bytes are the value (0ACB), 2763. Multiplied by the mulitplier, and it’s 2.763Amps. The sixth and Seventh bytes are a minmum value, which multipled by the multiplier works out to 1.62Amps, and the eighth and ninth are the maximum which is 3.8Amps. Our value is between the min and max, so the test passes.

Easy right?
0181: Min: 1.62Amps, Max: 3.8Amps, Value: 2.763Amps, Test: Passed

Now, parse byte 0×10 means something else. In this case, it means it’s a time value, no multiple, and in miliseconds.

0187: Min 0ms, Max: 300ms, Value: 157ms, Test: Passed
0188: Min 0ms, Max: 600ms, Value: 132ms, Test: Passed

And so on and so forth. I’m working on parsing out what the “parse” byte means. I’ve got about 6 of them figured out, but since that’s all the vehicle I’m testing on support, that’s about all I can do. All of this information should be fairly standardized on CAN vehicles, however non-CAN vehicles parse this information a completely different way. Once I get my hands on one, I’ll try to post up some information on that.

libobd, and Mode $06

As a few people are aware, I am responsible for libobd, a cross-platform library for interfacing to any ELM327 compatible OBD2 scan tools. Recently I have begun working on some more features for this, including things like Mode $06 support (On-Board Noncontinuous monitoring tests), and other mode functionality. I recently rediscovered an application called OBD2007 which seems to have support for at least Mode $06. Below are some screenshots from the application.

Overall it’s a fairly easy to use application, though not entirely useful other than as a novelty. The gauges are pretty but jerky in movement and not customizable at all.

It also has a “Fuel” display, which can be used for keeping real time track of fuel mileage. Again, it seems to work alright but is jerky and not customizable besides being able to convert between Metric and SAE.

This, is the bread and butter. This is what I was actually looking for, and found. This gives me a list of exactly what the vehicle outputs. This is the view and information that I wanted to duplicate, but this was a far cry from being able to actually request the data. One of the nicer things about OBD2007, is the “Connection” tab. This shows the hex data responses from the ECU to the requests that OBD2007 is sending.

This information is what I need. This directly corrosponds to the display on the Mode $06 screen, so I can take both screens and parse out exactly what the hex data means. I’ve taken and pasted the actual entire responses from the ECU below:

 

7E8101C4601810E0B35
7E82106540ED8018710
7E822008A0000012C01
7E8238810006C000002
7E8245800000000000
7E810254602010A0E68
7E8210000FFFF02810E
7E822031100DC0BB802
7E82385B1F7C1C56800
7E8240002861004CA00
7e82500177000000000
7E8101C4605810E0B08
7E82106540ED8058710
7E822006A0000012C05
7E82388100073000002
7E82458000000000000
7E810254606010A0E68
7E8210000FFFF06810E
7E822031100DC0BB806
7E82400068610058A00
7E82500177000000000
7E8100A462180200025
7E8210000009E000000
7E8100A46228020001C
7E821000000B8000000
7E8100A46338205551D
7E8210F5EFFFF000000
7E810134635801C002E
7E821000006C435811C
7E82200350000030600
7E810134636801C002A
7E821000006C436811C
7E82200400000030600
7E8101C463A80FEE0DE
7E821E0DE7FFF3A81FE
7E8220000000000003A
7E82382FEE0DE8000E0
7E824DE000000000000
7E8101C463C81FE0000
7E821000000003C82FE
7E8220000000000003C
7E82383030000000000
7E82400000000000000
7E8101C463D80A9F9C0
7E821F0567FFF3D81FE
7E8220000000000003D
7E82382FE0000000000
7E82400000000000000
7E80646800000000001
7E80646A0FE00000000
7E8102E46A180300000
7E821000016DBA18130
7E8220000000002DDA1
7E823823000D8000016
7E824DBA18330000000
7E8250002DDA184161F
7E826DB000024AC0000
7E8102546A20B240000
7E8210000FFFFA20C24
7E82200000000FFFFA2
7E82380300000000016
7E824DBA28130000000
7E8250002DD00000000
7E8102546A30B240000
7E8210000FFFFA30C24
7E82200000000FFFFA3
7E82380300000000016
7E824DBA38130000000
7E8250002DD00000000
7E8102546A40B240000
7E8210000FFFFA40C24
7E82200000000FFFFA4
7E82380300000000016
7E824DBA48130000000
7E8250002DD00000000
7E8102546A50B240000
7E8210000FFFFA50C24
7E82200000000FFFFA5
7E82380300000000016
7E824DBA58130000000
7E8250002DD00000000
7E8102546A60B240000
7E8210000FFFFA60C24
7E82200000000FFFFA6
7E82380300000000016
7E824DBA68130000000
7E8250002DD00000000
7E8102546A70B240000
7E8210000FFFFA70C24
7E82200000000FFFFA7
7E82380300000000051
7E824E9A78130000000
7E8250002DD00000000

 

The interesting thing about this data, is that it seems to be broken up into message chunks. If we remove the header, and rearrange the visual formatting…

101C46 //Initial header
0181 0E 0B35 0654 0ED8 //First message. Mode $06 id 0×01 TID 0×81 response.
0187 10 008A 0000 012C //Mode $06 id 0×01 TID 0×87 response
0188 10 006C 0000 0258
0000000000002546
0201 0A 0E68 0000 FFFF
0281 0E 0311 00DC 0BB8
0285 B1 F7C1 C568 0000
0286 10 04CA 0000 1770
000000001C46
0581 0E 0B08 0654 0ED8
0587 10 006A 0000 012C
0588 10 0073 0000 0258
0000000000002546
0601 0A 0E68 0000 FFFF
0681 0E 0311 00DC 0BB8
0600
0686 10 058A 0000 1770
000000000A46
2180 20 0025 0000 009E
0000000A46
2280 20 001C 0000 00B8
0000000A46
3382 05 551D 0F5E FFFF
0000001346
3580 1C 002E 0000 06C4
3581 1C 0035 0000 0306
001346
3680 1C 002A 0000 06C4
3681 1C 0040 0000 0306
001C46
3A80 FE E0DE E0DE 7FFF
3A81 FE 0000 0000 0000
3A82 FE E0DE 8000 E0DE
0000000000001C46
3C81 FE 0000 0000 0000
3C82 FE 0000 0000 0000
3C83 03 0000 0000 0000
0000000000001C46
3D80 A9 F9C0 F056 7FFF
3D81 FE 0000 0000 0000
3D82 FE 0000 0000 0000
00000000000046
80000000000146
A0FE000000002E46
A180 30 0000 0000 16DB
A181 30 0000 0000 02DD
A182 30 00D8 0000 16DB
A183 30 0000 0000 02DD
A184 16 1FDB 0000 24AC
00002546
A20B 24 0000 0000 FFFF
A20C 24 0000 0000 FFFF
A280 30 0000 0000 16DB
A281 30 0000 0000 02DD
000000002546
A30B 24 0000 0000 FFFF
A30C 24 0000 0000 FFFF
A380 30 0000 0000 16DB
A381 30 0000 0000 02DD
000000002546
A40B 24 0000 0000 FFFF
A40C 24 0000 0000 FFFF
A480 30 0000 0000 16DB
A481 30 0000 0000 02DD
000000002546
A50B 24 0000 0000 FFFF
A50C 24 0000 0000 FFFF
A580 30 0000 0000 16DB
A581 30 0000 0000 02DD
000000002546
A60B 24 0000 0000 FFFF
A60C 24 0000 0000 FFFF
A680 30 0000 0000 16DB
A681 30 0000 0000 02DD
000000002546
A70B 24 0000 0000 FFFF
A70C 24 0000 0000 FFFF
A780 30 0000 0000 51E9
A781 30 0000 0000 02DD
00000000

It seems that the first two bytes are the mode/tid combonation, the third seems to define how the rest is parsed. If it is 0×10, then the rest is parsed fairly simply. The first of the three is the value, second is min, and third is maximum. The other parsing values I’m not entirely sure of yet, but I’m still in the process of trying to parse this out. The point is, I’m making progress and I should be able to input Mode $06 into libobd soon. If anyone has any other ideas, feel free to contact me. libobd is licensed LGPL, so I am always looking for help and input for it.