Archive for February, 2009

Checking Memory and CPU Consumption on TS7390

Today I decided to place my new updated code on the ARM device and measure CPU and memory consumption.
I used the top command to investigate the consumptions. Running the program with continuous querying 3 sensors and updating them on the GUI resulted in 10% CPU consumption and 19.3% memory consumption. The processor on this device is a 200Mhz ARM and the memory is only 64MB ram so only 12.35MB of RAM is used but most of this is the actual QT framework. Normally however, there is only about 19MB RAM free out of the 64 before actually loading the program but a lot of this is cache ram that can be removed by executing: echo 1 > /proc/sys/vm/drop_caches. This provides about 40% RAM free so this is a big improvement. I decided to remove the whole kernel feature out and do no monitoring, just load the GUI components and leave them blank. CPU consumption is almost 0% and RAM usage is still as high as 14% (8.96MB). So the kernel part of my system with all few hundred DTCs codes loaded in memory only consumes about 3MB of RAM. This is good news. However I still don’t know how adding more GUI components will affect it yet. I have to be careful with my memory consumption.

DTC Parts Implemented including Reset MIL

Over the past 2 days I successfully implemented the checking and loading of DTCs. I have used the Scantool.net’s code database file for all the codes. This is loaded into my program. I can then do something as simple as:

qDebug() << automonApp.getMilStatus();
qDebug() << automonApp.getNumberOfCodes();

This will let me know if the MIL is on and the number of DTCs currently stored on the ECU. There are 4 types or categories of codes:

  • Powertrain Codes – eg. P0133
  • Chassis Codes – eg. C0100
  • Body Codes – eg. B0200
  • Network Codes – eg. U0122

The most common codes are the Powertrain codes. A code starting with P0 is SAE defined, while P1, P2, P3 are manufacturer defined, SAE defined, jointly defined respectively. It is a similar naming scheme with the C,B and U codes.

My simulator gives 6 DTCs if you press the malfunction button. This also illuminates the MIL. Reading these codes was a little difficult as there are 3 ECU’s in the simulator, ECU, ABS and Transmission unit. So I ended up getting codes from other ECUs as well but knowing where the delimiter was, proved to be difficult. The response to a 03 mode command responds with 43, but 43 can be a valid code as well. The 4 represents a chassis code so 43 00 would be C0300. I could not use 43 as a delimiter so I turned headers on using the ATH1 option and this gave back the sender/receiver/priority and CRC header bits. Using this information I successfully interpreted the correct bytes.

Resetting the MIL is very simple, just a matter of sending a mode 04 command.

Saturday, February 28th, 2009 ELM327 Interface, Onboard Diagnostics (OBD) No Comments

Sensor signal/slot mechanism implemented

I set up a handy way of connecting sensor’s to GUI elements. They don’t necessarily have to be GUI elements, just as long as you have an Object derived from the QObject base class and implement the following slot:

void mySlot(QString resultChange);

I created a method in my Automon kernel interface class called RealTimeSensor * Automon::getSensorByPid(QString pid). This will return either a valid pointer if the sensor pid such as “010C” was found in the sensor list or it will return null. This will come in handy for finding sensor objects.
I created another method that accepts a Sender object of type RealTimeSensor and a receiver object of QObject (Has to be a derivative of QObject). The method prototype is: Automon::connectSensorToSlot(RealTimeSensor * sender,QObject * receiver). So now in my main I can simply connect the signals of the sensors like this:

automonApp.connectSensorToSlot(automonApp.getSensorByPid(“010C”),lcdNumber1);
automonApp.connectSensorToSlot(automonApp.getSensorByPid(“0105″),lcdNumber2);

I’ve it implemented so a sensor only emits a signal when its value change. This will provide a little bit more efficiency. I tested this and got two LCDs updating according to as the sensors update. I set it so the coolant temp sensor “0105″ had a frequency of 10, so this didn’t get updated as much. However the RPM “010C” got updated about 4 times a second.

Tuesday, February 24th, 2009 QT Embdedded Programming No Comments

Getting Places Slowly…

This evening I managed to successfully create a command and parse the result to come up with a nice ASCII string of the vehicle’s identification number (VIN). The VIN will allow Automon to know what car it is plugged into and if it is a new car. This will allow me to create a profile for each car, and if necessary keep statistics of it. Of course this requirement may never be implemented with the tight time constraints associated with the project but it is an essential part of the Automon kernel nevertheless.

I also successfully implemented the sensor monitoring architecture. I can now create a “RealTimeSensor” by inheriting this class and overriding the convertResult formula as every sensor handles the hex response in its own way. These¬† real time sensors can easily be added to the monitoring system. eg: automonObj.addActiveSensor(CoolantTempSensor). I can also set the sensor’s frequency. This sensor for example should not be updated every cycle as it doesn’t change that quick. RPM on the other hand needs much higher priority. This system is also proven to work.

I can also pause monitoring by going to sleep, I can stop it by terminating the thread. These functions will be very important further down the line. I’m quite happy with the way my kernel’s archiecture is going now. Below is a code snippet of sending the VIN command and parsing a response. Of course this is still just quick code, all will be cleaned up before final release.

QString Automon::getVin()
{
if (m_serialHelper->isRunning())
{

#ifdef DEBUGAUTOMON
qDebug() << “Attempted to get VIN but SerialHelper is currently monitoring. Returning failure message”;
#endif

return QString(“Result could not be obtained. You must stop monitoring first!”);
}
else
{
Command vinCommand;
vinCommand.setCommand(“0902″);

m_serialHelper->sendCommand(vinCommand);

QString returnedBuffer = vinCommand.getBuffer();

/* Remove spaces to make it easier to parse */
QRegExp rx( ” “ );
returnedBuffer.replace(rx, “”);

/* Split each Line */
QStringList lineList = returnedBuffer.split(\x0D”);

/*
Next for each line, we will cut out the "49020n" so simply a
sub string from 6 to line.size()
*/

QString fullLine;

for (int i = 0; i < lineList.size(); i++)
{
QString thisLine = lineList.at(i);
thisLine = thisLine.section(“”,7,thisLine.size());
QRegExp nullFinder(“00+”);
thisLine.replace(nullFinder,“”);
fullLine += thisLine;
}

if (fullLine.size() % 2 !=0)
{

#ifdef DEBUGAUTOMON
qDebug(“The returned string for VIN was not of equal bytes. Error”);
#endif
return QString(“The Returned Number of Bytes for VIN was not even. Read Error”);
}

QString vinNumber;

for (int i=0; i < fullLine.size(); i += 2)
{
QString hexByte = fullLine.section(“”,i+1,i+2);
vinNumber += QByteArray::fromHex(hexByte.toAscii());
}

return vinNumber;
}
}

Random Pauses on SBC

So it was time to cross compile the Automon project to my ARM board. It starts fine but after a while, it appears that the serial reading misses an important delimiter character ‘>’. This results in a loop to infinity searching for this character. This is obviously a very serious problem. This is my theory: Debian Etch is currently running off an SD card. At times, writes have to occur to the SD card but these writes hang the whole system. The terminal connection to it, don’t even respond at these times. So I’m guessing this happens and some how the > gets discarded or losed in the serial I/O buffer. I would have thought that the buffer would still accept characters at a hardware level but it appears not. The ELM327 sends the ‘>’ character but when a SD write occurs, this character gets refused and is dropped. Eventually my system will be running of NAND on-board flash and I don’t think this will be a problem at all, but a temporary solution will be to implement a timeout feature when searching for the > character. This may require another thread however. I’ll look into this later on.

Some Kernel Framework/Structure Done

Today I created most of the necessary classes that will be involved with the low level ELM327 communication. (Implementation coming soon!) My real time sensor objects are going to be intelligent in that when their value changes they will emit a signal. This will be useful when using the kernel as I can simply tell Automon to add some sensor to the monitoring queue and then connect its signal to a user defined slot so once the signal value changes (only when it changes), it emits a signal that will call my slot and handle any GUI updating etc. This posed a problem in that my sensor’s had to be a derivative of QObject. In multiple inheritance, QObject’s must be the first in the list of base classes. This is a limitation in QT. My structure got a little complicated ending up with the Diamond Problem – http://en.wikipedia.org/wiki/Diamond_problem. The solution to the Diamond problem is to use virtual public inheritance but QObject doesn’t support this. So instead I derived my top most base class, “Command” to be of type QObject…so all my sub classes end up QObjects. This allows me to use signals/slots where I please while also allowing multiple inheritance and abstract types further down the line. It a bit of a mess to explain, I might throw up diagrams later.

Applying Rules to Automon

Today I came up with the idea of creating a monitor type thread in Automon’s kernel. This should allow me to create ‘Rules’ that can be added to the monitor and if the rules are satisfied, they emit a signal. For example, I could make a rule “If CoolantTemp < 50 degree C && RPM > 4000″ or “If carOnTime < 5mins && RPM > 4000″, these state that the car is not warm enough to do such reving, resulting in engine wear. If these signals were to emit, I could have them connected to say a GUI warning slot, that will alert the user/driver of the car that such a state has being satisfied.

However this causes a little problem, how can I make dynamic savable rules like this? Coming from a PHP and Javascript background, I’m well familiar with the eval function. This would be useful as I could pass a string “%1 < 5 && %2 > 6″ and replace the %’s with the sensor’s pointer address, then feed this in as an eval to evaluate the code dynamically. Unfortunately, C++ doesn’t seem to support such a construct. I then realised QT comes with a scripting module, QtScript. This will allow me to create dynamic variables and evaluate a condition. Scripting objects can be connected to real QObjects so this should solve the problem. Hopefully!

Automon Kernel Considerations

Automon Architecture

Automon Architecture

The Automon kernel will be responsible for all the lower level ELM327 serial communication. It will provide a easy to use interface to communicate with any ECU encapsulating all ELM327 commands.

One of the design issues problems I am encountering is that not all responses from the ELM327 are “simple”.¬† Most sensor commands result in a few bytes represented in hexadecimal and you apply a formula to get the actual human result in volts, rpm, degrees etc. Some results however are bit encoded. For example a request to Mode 3 of “03″ without a Pid results in a stream of bytes, with the first byte meaning how many DTCs are present and the remaining types of DTCs, where each is encoded to a special type, P, U, B codes etc and which are pending or not is also encoded into the bytes. I wanted to create a generic PID base class but the complications is causing problems. I want to allow the user to provide proprietary codes as well. To do this I would read the codes from a file but how do I specify the formula and the logic in the formula if it exists? – For example, some formula’s have, If Byte B == 0xFF (all 1s), then it means this, other wise take byte A and do something else. One solution would be to using scripting. QT provides a useful scripting engine in the QScript module. I might look into this and get a better understanding of it.
Alternatively, if I want to make my system less flexible, I could create a Sensor class and derieve each sensor over writing a “convert formula” method so each class of sensor has its own defined formula.
Since the data structure holding these is so vague and none standard across all sensors, I thought XML would be a great way of representing this data for parsing later.

Today I managed to convert my GUI prototype app into one that can handle a QList<Sensor> of sensors. I also implemented a way of how frequent sensors get updated. For example, RPM,MPH are the main ones that change down in milliseconds but something like coolant temperature would only need to be checked maybe every few sensor cycles. A sensor cycle is where my serial comm thread iterates through a list of sensors. Every time it comes to a sensor, it evaluates if it time to check that sensor, otherwise skip to next. This makes adding sensors quite handy. I also created signals in my sensors, so once their value changes, they automatically emit a signal with the new value. This is very useful since I can connect sensors to GUI slots very simply. Here is an example:

sensor = new AGenericSensor();
sensor->setEnglishMeaning(“Engine Revolutions per minute”);
sensor->setMode(“01″);
sensor->setPid(“0C”);
sensor->setExpectedBytes(2);

sensor2 = new AGenericSensor();sensor2->setEnglishMeaning(“Engine Coolant Temperature”);
sensor2->setMode(“01″);
sensor2->setPid(“05″);
sensor2->setExpectedBytes(1);
sensor2->setFrequency(10);

serialThread->addSensor(sensor);
serialThread->addSensor(sensor2);

connect(sensor, SIGNAL(changeOccured(QString)), this, SLOT(updateLCDText(QString)));
connect(sensor2, SIGNAL(changeOccured(QString)), this, SLOT(updateLCDText(QString)));

Automon Design

I decided it was time to actually start designing Automon and stop playing around with proof of concepts. The way I am going to approach this project is to develop a library separate from the GUI that will act as the kernel so to speak. It will provide an object oriented interface to the ELM327.

I spent a while writing down what methods would be needed and soon realised that this project might be a lot bigger than thought! However, it should be do-able. It will be a soft real time system, where timing will be down to milliseconds.

Here is an idea of a class to interface Automon. Just very basic idea at moment. It will probably change quite a bit from this.

Interface Class Diagram

Interface Class Diagram

Received my EOBD Simulator

ElmScan and Simulator

ElmScan and Simulator in Action

KWP2000 Simulator

KWP2000 Simulator

Today I received my ECU EOBD simulator from Turkey. It only took a day to get here! – very fast delivery.
It didn’t come with a transformer to plug it in so I looked up the data sheet for the power specifications. It requires a 12VDC supply with 500mA current. I purchased one in my local electrical store and this done the trick grand.

The device works great. It has 5 variable sensor values, RPM, MPH, Coolant Temp, o2 Sensor Voltage and MAF. Other PIDs are also on board with fixed values. It includes a DTC switch that allows you to turn on the MIL along with logging a few DTCs. It even includes freeze frame data and a VIN. Resetting the MIL and erasing the DTCs works perfectly by sending down a mode 4 request.

This should make life a lot easier now as I won’t have to be in the car much. But when I get into a proper testing phase, I’ll do weekly tests on my car and maybe another OBD II standard car to ensure that it works on them.

The device is one version of the OBD II protocols, KWP2000 (Keyword Protocol). It is in a lot of European Cars including my MG. Ideally I should probably have chosen a board that had a different protocol. The ELM327 can handle all.

Tuesday, February 10th, 2009 ELM327 Interface No Comments

First GUI Prototype using ElmScan 5 & QT/E 4

GUI Prototype

GUI Prototype

So today I finally decided to create a GUI application that would display the revs. The photo above is taken of the TS7390 connected to the ElmScan 5 USB and my car’s DLC. Even though it is USB, it actually creates a virtual com port so my code didn’t need to be changed from past code. The chip that does this virtual com port emulation is the FT232RL from FTDI. This is supported in Linux kernels > 2.6.9 which mine satisfies. More information from: http://www.ftdichip.com/Drivers/VCP.htm
The code took me about and hour or two, but I did have the QT serial stuff already done so that would have taken quite a bit more. This is only a prototype and cannot be used in any way in the final product. I am only doing proof of concept that I can in fact read from serial while updating a GUI.

Constraints
I noticed that if I reduced the refresh rate to 1/4 of a second, things got funny, it was missing bytes etc so the revs were all over the place. It seem to be perfect at about 300ms but that means refresh rate is only ~3Hz. This is actually quite noticeable when you rev up high quickly in neutral but on the road I’m guessing as you rev gradually in normal driving circumstances that it won’t look so bad.
However, the product is not a problem with my program to the ELM327, the serial part is fine. It is a limitation of the OBD side and my car is using KWP2000/ISO 14230 so I will have to figure out more timing details on this protocol. Other protocols such as CAN should be OK speed wise but I will have to investigate more into that.

MGs/Rovers – Not 100% EOBD/OBD II Compliant

The ElmScan 5 tool I received a few days ago from scantool.net seemed a little strange. I attempted to connect it to my laptop and the car and communicate with it but I kept getting interface not found.
I tried hooking it up with hyper terminal to the virtual USB com port and as soon as I made a connection, the power LED on the scantool would go.
I found it quite strange that none of the other LEDs were even attempting to light. Doing some research, I discovered that when you plug the scantool into the ECU, that a LED sequence should occur to show correct operation of it.

I spoke to one of the main guys at scantool.net and he was quite surprised since each tool is tested fully before it leaves the warehouse (excellent QA from that company).

So the ElmScan was not getting power, but how is it that my other ‘fake’ ELM327 device gets power and my hand held fault code reader gets power. I was told by the guy I was talking to that the ElmScan uses pin 5 of the DLC connector as ground and pin 16 to get power. Doing more research into the pin outs, it appears Pin 16 is Battery power and Pins 4 & 5 are grounds, chassis ground and signal ground respectively. I had a +12 voltage across Pins 16 and 4 but nothing across 16 and 5. This clearly was the problem.

EOBD DLC Connector

EOBD DLC Connector

So then I got out my volt meter and investigated. I had a +12 voltage across Pins 16 and 4 but nothing across 16 and 5. This clearly was the problem.

Voltmeter used

Voltmeter used

The guy I was speaking to from Scantool.net kindly gave me a hint suggestion to short jumper 1 on the ElmScan. This means that it will take Pin 4 as the ground which is all my car will offer as ground. Opening the tool was surprizingly simple, no glue or anything. I took the circuit board out and grabbed a jumper from old computer parts and placed it on the create the short.

ElmScan 5 USB with JP1 set

ElmScan 5 USB with JP1 set

Alternatively if you don’t have a spare jumper, you can soldier the pins together with a piece of wire.

I hooked it up to my OBD connector on the car and it worked instantly. I loaded up the software and connected USB just to be sure and it connected fine. The tool was sending out 4 samples a second which isn’t too bad. When I revved the engine, the response time was satisfactory. As far as I know the more parameters that I add to request, the slower the response will be but I’ll have to investigate that over the next few weeks.

So in fact MGs/Rovers don’t seem to be 100% EOBD/OBD II compliant – only on a physical level though. Most scanning hardware would work but some don’t and the reason is that pin 5 is not used by MGs/Rovers.

ECU/EOBD Simulator

KWP2000 Simulator

KWP2000 Simulator

Today I decided to look for a proper OBD II/EOBD simulator. This would save so much hassle as I wouldn’t have to be going out to the car every second checking if a change made works. Further more, currently my SBC is plugged into a mains so it awkward getting it powered up in the car.

I decided to go with the KWP2000 protocol simulator as this is the same one in my car. I guess I really should pick another one and get tested on both types but I can simply just plug into another car later on anyways.

The one I went with cost 99 euro and is on this page: http://www.ozenelektronik.com/?s=products2&group=eobd-obdii-ecu-simulators

This project is costing me a fortune! – Hopefully everything will pay off in the end now.

Scantool.net and their ElmScan 5

ElmScan5 Serial Version

ElmScan5 Serial Version

Today I received a genuine ELM327 Tool (ElmScan 5 ) from Scantool.net. These guys kindly offered me a free one worth 130 dollars since I was doing it for my final year project. Unfortunetely they sent me the USB version and I wanted the RS232 serial version so I may send this back. Technically though it should work away by using /dev/ttyUSB0 since the kernel is 2.6 and supports the FT232RL chip that is in the USB version that gives a virtual USB com port.

Anyways I think I’ll be better off going with all serial at this stage just incase it causes problems down the line so might send it back to them. Thanks Vitaliy!

Scantools are located here: http://www.scantool.net/scan-tools/. It is important to buy the ELM327 Scantools from here as ones on ebay and other places are generally fake replicas and do not work fully. Poor quality etc. I know myself since I bought one for 50 euro and it gives up randomly.

Tested Console Program to Read Revs on TS7390

Reading RPM Successfully!

Reading RPM Successfully!

In MG with Automon

In MG with Automon

It worked!

First of all I had to cross compile QExtSerialPort for ARM Linux. To do this I downloaded the tarball, unzipped it to my home directory. I set my PATH variable to point to qmake in QTEmbedded-4.4.3-arm. Then I ran qmake and make and it successfully compiled for ARM. In the build folder there is a libqextserialport.so.1.0.0 and libqextserialport.so.1 and few more. I copied all up to /usr/local/lib on my Device.

Next I ftp’d my project from windows to vmware, the one I discussed previously. I had to modify the .pro project to the new location of qextserialport libraries (in my home directory) and I had to add an extra line: libs += /home/donal/qextserialport/build -lqextserialport. I also had to modify the main.c file to point to /dev/ttyAM1 which is COM1 on the board. Then I navigated to my test folder and done a qmake followed by make and resulted in a automon binary. Doing file automon , I confirmed that it was an ARM binary. I ftp’d this up to my device.

I set the whole lot up in my car as you can see in the pictures above. Connecting the ELM327 to COM1. I ran the automon program off the device redirecting the output to the screen by doing

$ cd /home/eclipse
$ ./automon > /dev/tty0

And out comes the revs in the car perfect. It only does a snapshot every 1/2 second but it is enough for me now. Now I have done all my proof of concepts. Just to build the project now in QT!