It’s been quite a while since I’ve worked on the TS7390 and QT but I’m back at it again for other reasons!
I’ve successfully got the latest QT / TSLib and EABI/Lenny distro working on the TS7395. I’ll post a step by step guide soon enough.
My next step is to also get Direct Frame Buffer cross compiled. Technologic Systems already provide Direct FB in the Etch distro and it seems to work quite well.
Over the next few weeks, I’ll put together a full guide. Looking forward to it
When I get a bit of time off over the next few weeks or so, I’m going to give a go compiling QT for EABI.
A lot of discussion on this is active on the mailing lists. Some people are having terrible problems and night mares and some seem to have it done fine.
I’m going to document every step I do fully. Performance on EABI should be a lot better than what I have now. I’m planning on enhancing Automon and perhaps including some media system. Exciting times still ahead.
Scantool.net are one of the biggest distributors of PC-based scan tools based on the ELM327 IC.
They mentioned my project on their website – Thanks! The article is located at
I would like to thank Vitaliy Maksimov from Scantool.net – he kindly arranged the shipment of an ElmScan 5 USB for my project. He also helped me with technical issues – much appreciated!
Their website address is: http://www.scantool.net/
I finally completed the report. It contains quite a bit of detail but all is necessary.
It can be downloaded from: http://automon.donaloconnor.net/files/fypreport.pdf
User Manual is here: http://automon.donaloconnor.net/files/Usermanual.pdf
All that is left now is to print out the testing documentation and get everything ready.
Project demonstrations are Monday! – I have to figure out a way to compress 3 large topics into a single presentation!
So the project is almost at an end. It was a great experience. I learned loads. I will keep this site up as a resource for others as it seems to be helpful.
Thanks everyone for viewing and all the support.
Today I touched up on the test plan I made a few weeks ago and entered the test cases that I completed this week.
A few bugs were found but nothing major.
Today I done a bit of refactoring of code and commented everything I could. Almost drove me insane but got there in end. Final result ended up ~7500 lines of code, not bad! – Couldn’t have made it any more efficient or smaller. And surprizingly, the executable results in a file size of just 800KB including all the graphics and styles! I am very impressed with QT Embedded indeed!
Well not quite, still testing and fixing of a few known bugs. However it really is complete to me. All widgets and functionality is implemented and actually works! Tested it today on my MG and everything worked a charm. I’ve yet to try it on a few more cars but I don’t see why they’d be different since the ELM327 supports all.
Below I’ve included photos of Automon on the TS7390 since it might look a bit more realistic than the screen shots. The camera is years old and my hands arn’t steady so apologies for the quality. It actually looks superb in real life, almost better than the screen shots below. Colors come out great, even though it’s only 15bits.
Today I modified some run level scripts on the embedded Linux. I set up the environment variables and locations of libs in the /etc/rc.local script. This script runs at end of run level 2, in multi user mode and Automon automatically starts. Now all I have to do is connect the TS7390 to the car and turn it on. I also purchased an inverter for the car today that works so no need for DIY circuits at the moment to power the SBC.
Anyways Automon now starts up on start up of the TS7390 so no more need for telnetting into the board.
Today I started on the monitoring side of things. Embedding a rule editor inside the monitoring widget was simply not practical or even possible due to screen real estate issues! Instead I gave it, it’s own dedicated widget. Above is what it looks like. At the moment it only allows you to add two sensors to a rule. The sliders allow you to change the values since no keyboard and I’ve no intention of developing a on-screen virtual keyboard widget with the time frame I have!.
Each since has it’s min and max, for example coolant temp is from -40 to 255 (OBD II limitations). When you select this sensor, the sliders automatically adapt to these ranges making it a bit intelligent! Speaking of intelligent, there are other things for example. Only sensors that the car can support will be listed! The OBD II standard does not force manufacturers to implement all sensors, only the ones they want so Automon will automatically update the supported ones and only give users access to these.
Now for the monitoring widget….
QT provides a very handy widget, QSplashScreen. This allows me to display messages to the users when they wait for Automon to initialize itself, such as serial I/O and the OBD II bus. Here is a little prototype run:
It has being a while now since I’ve touched the project due to being a bit ill.
Nokia/Trolltech released QT 4.5 earlier this month. I decided it would be best to update to this new version for a number of reasons:
- Ensure code compatible with new versions of QT
- Significant Performance improvements with QT 4.5: http://labs.trolltech.com/blogs/2009/03/03/performance-and-qt-45/
- New features will be available
All my code compiled successful, however I didn’t see much increase in performance. I will look into this more in the future.
Compiling and Cross Compiling QT 4.5 was no different than that of QT 4.4.3. I did however encounter one problem when cross compiling, a linker error to a symbol that didn’t exist. I believe this has to do with me using a old cross compiler version of GCC. However, the problem was removed by replacing this function. Can’t remember the name now but it was an exit function, that I simply replaced with exit(0).
This weekend I added the rules functionality. Rules might be something like, alert me when “Coolant Temp < 60 && RPM > 4500″. Each rule is given this logic, but using the commands instead of English meaning. You simply add the sensors you want in your rule and then create the logic using ANDs/ORs and comparison operators.
This is an example:
r1.setRuleName(“You may be wearing your engine. Reving too high and coolant temperature too low”);
r1.setRule(“s010C > 4500 && s0105 < 60″);
QObject::connect(&r1, SIGNAL(sendAlert(QString)), &errorHandler, SLOT(errorslot(QString)));
qDebug() << “Rule Added”;
qDebug() << “Error Adding Rule”;
So now when the Revs goes above 4500 and the coolant temperature is still relatively cool, signal an alert. I’ve it going to my error handler at the moment but this could easily be any GUI element.
That is pretty much all I am going to do for the kernel part of my system now. I just have to implement proper error handling and test it properly. Now using all the functionality it supplies, I must create the main application.
I am finishing up the main parts of the heart of my application now. Currently it has the following functionality:
- Load Sensors, or custom ones that inherit from a main object and implement a conversion.
- Connect sensors to the serial scheduler and set sensor frequencies so some update more often than others.
For example, coolant temperature would need to be updated a lot less than engine RPM.
- Set min and max boundary values per sensors and connect a error handler slot to a signal that occurs when a sensor value goes out of bounds.
- Record average and instantaneous refresh rates of sensors. Helpful for debugging and performance testing.
- Load DTC values, even propitiatory ones from a flat codes CSV file into the system.
- Look up number of DTCs in system and check if Malfunction Indicator Lamp (MIL) is switched on.
- Load in stored codes on ECU and compare against code DB. If found, give english meaning, otherwise english meaning is “Unknown”
- Reset the MIL.
- Get battery voltage of car.
- Get car’s vehicle identification number (VIN).
- Get car’s OBD Protocol.
- Get the OBD standard that the car complies with.
- Automatic pausing of monitoring when command issues. (Slight problems with this however).
- Mutex’s implemented on non re-entrant serial methods. (Need to test).
- Check supported sensors in car and automatically disable sensors that are not supported. A debug message is also presented when a sensor cannot be added due to it being unsupported.
Need to implement a system where a user can dynamically set rules such as “If coolant temp < 40 degrees AND rpm > 4500″, that the rule emits a signal that is caught by a user defined slot. Ideally I’ll have a GUI section that prints an message if rules are satisfied.
This is a very important part of my system, that will provide great functionality to mechanics that need to diagnose or test car tuning changes.
- Freeze Frames
A freeze frame is a collection of all the sensor values during the last time an error occured. These are not actually sensor objects. I have the problem of querying only ones that are supported and storing them as XML and returning the values like this.
So for the moment, that is all the functionality I require for the Kernel. All this functionality is provided via a sort of interface, though technically not as implementation is included in parts.
Next week I am going to spend time testing this properly as I still have problems with the odd timing going wrong and hanging. I am going to investigate QTestLib to see what that has to offer in the line of automated testing but I don’t want to invest too much time into this area. Saying that however, it is essential that this part of the system, the Automon kernel is stable as the result of “Automon” will be built on top of that over the next few months.
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.
qDebug() << “Attempted to get VIN but SerialHelper is currently monitoring. Returning failure message”;
return QString(“Result could not be obtained. You must stop monitoring first!”);
QString returnedBuffer = vinCommand.getBuffer();
/* Remove spaces to make it easier to parse */
QRegExp 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()
for (int i = 0; i < lineList.size(); i++)
QString thisLine = lineList.at(i);
thisLine = thisLine.section(“”,7,thisLine.size());
fullLine += thisLine;
if (fullLine.size() % 2 !=0)
qDebug(“The returned string for VIN was not of equal bytes. Error”);
return QString(“The Returned Number of Bytes for VIN was not even. Read Error”);
for (int i=0; i < fullLine.size(); i += 2)
QString hexByte = fullLine.section(“”,i+1,i+2);
vinNumber += QByteArray::fromHex(hexByte.toAscii());
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.
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.
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”);
sensor2 = new AGenericSensor();sensor2->setEnglishMeaning(“Engine Coolant Temperature”);
connect(sensor, SIGNAL(changeOccured(QString)), this, SLOT(updateLCDText(QString)));
connect(sensor2, SIGNAL(changeOccured(QString)), this, SLOT(updateLCDText(QString)));
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.
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.
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.
I am Donal, a 4th Year software student from the Cork Institute of Technology (CIT). The title of my course is Software Development with Computer Networking so it is pretty much 2 courses in one: Networking/Telecommunications + Software Development.
I am creating this blog to keep track of my daily progress on my final year project (FYP) : Automon.
Think of it as a diary to keep track of daily events, it will make the writing of my final report a bit easier!
Automon will be an embedded ARM touch screen device that will be mounted on the car’s dashboard and connected into it’s ECU reading real time information such as vehicle speed, coolant temperature etc. The device itself will be a TS-TPC-7390 Single Board Computer (SBC). More details can be found at http://www.embeddedarm.com/products/board-detail.php?product=TS-TPC-7390
A quick summary of the device:
- 200Mhz ARM9 CPU
- 64MB SDRAM
- RS232, USB, 10/100 Eth ports
- 7″ Touch Screen
What the project will involve
Automon will be developed using the QT (“Cute”) framework from Nokia (formally Trolltech). This is an open source framework that is quite powerful looking. I have to learn this framework on the fly. A special version of QT, QT/Extended or Qtopia will be what I’ll use on the actual device. This will allow me to write directly to the frame buffer (/dev/fb0) on embedded Linux making my application independent of a window manager such as X11 saving quite a bit of resources!
Communication directly to the ECU would require intermediate hardware and signal processing that I don’t have time to do and plus considering there are multiple OBD protocols (3 main, 5 flavors) it would just not be practical. So instead I will be using the ELM327 IC. Datasheet found here: http://www.elmelectronics.com/DSheets/ELM327DS.pdf. I can communicate with this chip using a serial interface using AT commands.
As stated above the device will be a SBC but since it is ARM driven, cross compiling will have to be done. This can be a tricky process and especially with QT libraries included.
Below is some more details on parts of my project.
Project Background and Introduction
The automotive industry is moving towards more intelligent forms of transport. Currently vehicles are able to sense one another and alert users or even the car’s control system of dangers that may exist ahead. Vehicles use real time sensor data to determine such dangers or failures that may occur. The rationale behind this project is to demonstrate the use and interpretation of these sensor values and display them in a meaningful way. All vehicles must implement a standard form of diagnostic reading, OBD (Onboard Diagnostics) which allows all sort of cars to be communicated with using a standard reading device. In addition to this, cars have their own proprietary protocols as well for communication with expensive diagnostic equipment that usually only services one type of car. Generally these proprietary protocols provide a lot more detailed information of what is happening in the car. This project will not deal with such protocols as this will be a limiting factor to which vehicles AutoMon will be able to communicate with.
Onboard Diagnostics (OBD)
OBD is a term in the automotive industry that refers to a car been able to self diagnose itself and provides users or mechanics with the necessary information to gain an understanding of what is wrong with the engine or its sub systems. In 1996, the OBD specification was made mandatory for all cars sold in the United States. This was in an effort to encourage manufacturers to produce more efficient vehicles reducing emissions. OBD II is an improvement over OBD with better capabilities and standardisation. By 2001, the European Union made OBD II mandatory for all petrol vehicles sold in the European Union.
AutoMon will communicate with the car using OBD II and its connector that is standard across all vehicles. Different protocol implementations are existent, 5 to be precise. Investigations into ways in which to communicate with all 5 protocols together were done, and two solutions exist, both of which are an integrated circuit (IC), the ELM327 and the BR16F84-1.07