-   OpenGauge / MPGuino FE computer (
-   -   Adding ALDL scanner support to MPGuino (

FalconFour 09-29-2010 01:50 AM

Adding ALDL scanner support to MPGuino
Anyone ever thought of this? Pulling in the 160 baud data from the computer and interpreting its sensor and error code data?

I know it'd be a relatively large undertaking, but with the framework already in place in the MPGuino's code (interrupts and such), I think a lot of the work is already done... electronics won't be too complicated since the whole protocol would be implemented in interrupt instead of using a dedicated serial interface (most ALDL interfaces use a complicated signal-conversion to read the non-standard 160 baud data). I think, at least...

I know code is already pretty tight, but maybe more room can be found in a custom firmware by removing some of the personally-unneeded features like metric values and features for other homebrew MPGuinos (I have a prebuilt one bought just a few weeks ago).

Figure it's worth throwing the idea out there, maybe get some input :)

dcb 09-29-2010 08:17 AM

only briefly, seen any source code for a PC based ALDL reader lately?

FalconFour 09-29-2010 05:50 PM

Not exactly, although I can pretty closely theorize as to how the program works. Most of it is putting the data in the GUI, and another good part of it is adapting the broken data from the serial interface running at 9600 baud to the data coming in at 160. I'd take some references to figure out what parameters are what bytes in the stream and how to interpret them, but for the most part it would have to be entirely custom to this Arduino platform.

I'd figure this flow of the system:
In an interrupt, or at some timed part of the program, check that the appropriate timing for 160 baud has passed (count loops based on the system used for injector timing, maybe?). When it has, and a new bit needs to be read, read the bit and add it to the end of the current "data set" stream - the set of parameters that gets looped every second or so by the car's computer. When the data set is completed and it starts to loop again (there's got to be something in the stream that indicates the end?), parse the interesting values in the data stream and move them into their appropriate variables (RPM, temp, error codes, etc). Rinse and repeat. In the routine that interprets data and draws the display, these values would be used.

Oversimplifying? :/

dcb 09-29-2010 06:06 PM

I might start with an arduino and maybe some bitbanging on the aldl port and leave the uart port for debugging w/a laptop. The obduino code has some 300 baud bitbanging (at least for output) in it, fyi.

found a little data here on the aldl protocol:
Information on GM's 160 baud ALDL data stream

160 baud is slow enough that a firmware only solution sounds very possible.

FalconFour 09-29-2010 06:17 PM

That definitely sounds like an idea. I've got a Duemilanove that first got me interested in Arduino projects, that I haven't really done much of anything with. I imagine I can use the same sort of signal-filtering setup used in the MPGuino for VSS to "safe up" the signal? I'm really not that familiar with the electronics side of things, although I've been dinking with electronics projects all my life, I never had any formal education on the matter... I'm more a computer programming/repair kind of guy. So I can probably do the code once I put my nose to the grind-keyboard ;)

But I take it 160 baud ALDL isn't all that popular, even for GM... if I did end up doing it, it might have to be a one-off thing for each car's computer, since the different ECMs put out different bits of data in different ways, and to keep the code small, the value positions and interpretations (such as reading some gibberish integer as 95.4 degrees F) would have to be hard-coded for each system.

Sure would be nice to have, though. Definitely gotta go pick up my Arduino from my friend's place... been sitting in a box over there for months ;)

dcb 09-29-2010 06:43 PM

actually reading looks pretty straightforward. If you use the external interrupts, one on the rising edge and one on the falling edge and keep track of the time between them, the 1's will be short blips and the zeros will be longer, just need to figure out a threshold in between them.

then stream the bits received into some thing to keep track of the messages. It can do things like "oh, I got 9 ones in a row, this must be a new message block"

you can set both pins to input and gang them together and protect with a resister and 5v zener, like the guino.

The output pin basically needs to drive a transistor to toggle 12v to the aldl port.

A timer interrupt to stream the output bits to aldl might simplify timing, or complicate it.

FalconFour 09-29-2010 08:38 PM

Well, the best part is, the computer accepts no inputs, so it's all reading, no writing ;) It just takes a 10K resistor on the "mode" pin to make the computer start rambling 160-baud data, in a simplex stream, then it's up to the receiver to figure out what the gibberish says. That's why I think it wouldn't be too difficult to implement, since it's basically just another timing-and-computation sort of thing, similar to reading the VSS.

Thanks for the tip on the zener, though, that'll definitely help simplify things, I wasn't sure how the system would interpret approximately zero volts for a "low" signal, but a zener sounds like just the trick.

dcb 09-29-2010 11:18 PM

1 Attachment(s)
I'm confused about where 160 baud is used and whom is talking to whom in the aldl exchange. But the attached circuit should be a good starting point, set one pin for the rising trigger and the other for the falling, and manually use a jumper for start the aldl spewing data.

There is also a pulsein function, but I don't know if arduino supports it, or if you can reset it in time. I think it blocks program execution by default as well. arduino programmers are generally not accustomed to the quasi-threaded environment of interrupts.

FalconFour 09-29-2010 11:50 PM

COOL, thanks for the schematic! May sound silly but that really helps, simple as it is.

As for the ALDL data exchange, what I mean is, it's not really so much an "exchange" as much as a simplex data stream that goes on even with nothing plugged in to interact with the computer (as long as that 10k resistor is installed in the "A-B" positions to tell it to start spewing). So there's no data the Arduino needs to send back, it just needs to listen :)

Think I've got all the info I need to get started, at least until I get my Arduino board back. Thanks!!

dcb 09-30-2010 07:18 AM

oops, looks like a 5v signal? use a 10k resistor if it is 5v I guess. Sorry, not the aldl expert :)

according to the connector pics, it looks like 160 baud is australian?
GM 8192/160 Baud ALDL Interface and the 12 pin is US @ 8192 baud? 5 volts?

also: "Early ECUs produced a fixed 8192 ALDL data stream when the user placed a 10k ohm resistor between ALDL connector pins A and B. Later ECUs added internal receive circuitry"

so still some unknowns about baud and voltage levels and the directionality of the exchange in my head.

FalconFour 09-30-2010 07:43 AM

*facepalm* You screwin' with the newbie's head here? Lol...

Okay, let me draw you a picture.

[car computer..] aldl "data" ------- 160 baud stream of info ------- [ arduino ]
or "ECM" ........] aldl "b" [ --v .. 10k .. v ]
....................] aldl "a" [ --^ resistor ^ ]

Rheeeeleeey not as difficult as it's being made to sound. Add 10k resistor to (separate) A and B pins, get 160 baud stream of data from the computer on the "data" pin (just one pin, grounds to car). There are 8192 baud variants, usually OBDII systems I think, but mine is 160 baud.

You mean you've never played with this stuff before, like, at *all*? =o

dcb 09-30-2010 07:51 AM

I am reading some contradictory information on the web is all, nothing insurmountable, might take some trial and error. If you know your vehicle is for sure 160 baud then good on ya :)

toc 01-21-2011 09:00 AM

Did this end up going anywhere?
I'm keen to give this a shot - but the VSS might prove problematic.

FalconFour 01-21-2011 01:24 PM

Not really... I haven't done much Arduino work lately, my half-baked car alarm design is still sitting on my desk at home after I basically got shat on by the Arduino community for posting my work-in-progress. Kind of uninspired to work with anything Arduino after that point. /sigh

toc 01-21-2011 06:04 PM

Ahh from the thread:
"The criticism was not directed at the code or the concept. It was directed at the "I haven't tested this, but I KNOW it will work" attitude."

As always, third parties have an opinion - I won't add one here.
Or will I. I like the idea, I want to do it.

I'll be giving it a go on my Hyundai Sonata, which has a 12 pin connector.
What I'm lost on and can never seem to find an answer to is the conflicting information out there.

This page mmcdlogger. suggests the data is request / response. You must ask for data to get it.

But, I recall reading that there is a data stream, i.e. you simply listen and process the data that comes along the pin 1 - but the baud rate - I've seen 160-baud, 8192-baud and 1953-baud all mentioned as being the rate used.

I'm not sure what to expect - and I want to go to arduino.

Perhaps someone knows the answers ?
- What is the baud rate?
- Is there a data stream, or must all data be requested?
- Does pin 10 and 12 get shorted for data ?

I also did some checking yesterday too with my multimeter:
- Pin 1 and 12 - this bounces around between 11-13V and 0V with key and engine on.
- Pin 11 (Speed) and 12 stays at 4.69V with the engine on. I haven't checked for variations here.

This link mmcdlogger. says the speed can be requested by ECU.
What's the point of the speed sensor PIN in the ALDL circuit? I think it's duplicated if that's the case, the ECU has speed sensor input, as does pin 11.

FalconFour 01-21-2011 07:09 PM

Well I can 110% completely and totally guarantee and verify that the 160-baud ALDL data on my '87 Fiero is a constant receive-only stream, the computer simply chugs out that data whenever a 10k resistor is put across the ALDL mode pin (open = normal operation; 10k = ALDL diagnostic stream; shorted = diagnostic mode, blinks codes & runs engine in timing mode). The ALDL cable used to read this data only uses one serial pin, Rx, and a simple TTL level-converter circuit (to bring it to proper serial signalling voltages). Then software samples the broken data at ~8192 baud (since 160-baud is non-standard), and interprets the data. Since the Arduino impementation would be all software, it would seem to be very simple to read the incoming data stream natively (at 160 baud, or hell, using interrupts, it could be any reasonable data rate) without needing to do any electrical conversions.

So I think that answers all the questions:
1) Baud rate is 160 baud, at least on my old OBD1 car. Yours may be completely different. OBD2 uses a completely different format and nothing about ALDL from OBD1 will be compatible.
2) It's a constant outgoing data stream, no data can be sent back to the computer; the computer doesn't have any facility to receive commands or any sort of data at all.
3) The pins - and I'm not sure what they're named/numbered (I believe they're referred to as "A and B") - need to be shorted with a 10k resistor.

But I think the key here is, what year is your car?

toc 01-21-2011 07:17 PM

1997 here. I was just reading about the 10k resistor requirement.
1997 in USA was definitely OBDii - however my vehicle is from Korea and has the older connector.
The 1995 Sonata seems to be a close match.

Engine in the car is a G4CP which equals a Mitsubishi 4G63 - which from my further reading is a 1G DSM.

Pin 10 - do I short to ground, or place a 10k resistor between it and ground?

toc 01-22-2011 02:04 AM

Digging further and further (and still not on any proven beaten track as yet), I've had a look at pocket logger's DSM cable installation steps where it's plain to see a jumper from 10 to 12 and data on 1.

There's no mention of the baud rate there, so that's still in the wind.

I've got some LCD displays coming, as I can't have the laptop, car and arduino connected at the same time (I think).

When they come, I'll put some code on the arduino to show on the LCD each baud rate and result - thus finding which baud rate is right.

toc 01-23-2011 12:49 AM

I tried to connect and use an arduino library for serial output to some wireless gear I have.

The wireless gear is receiving and sending data fine.

The connection to the car is - Pin1 to Arduino TX.
Pin 10 tied to pin 12 (ground), and this also goes to the arduino for ground (i.e. 10 goes to 12, 12 goes to GND on arduino).

I then set code to loop 30000 times waiting for data to be available on the serial port, so, Serial.begin(160), then loop 30000 times to see if any data came through. None. I tried 160, 8192, 1953, 1960, 1920 - none of these gave out any data.

As a last effort, I added Serial.print(0x21), just before each of the loops, to see if I had to ask for the data, and at the arduino, connected a jumper between TX and RX.

Still nothing.

But I think the problem there is I was using Serial.print, instead of Serial.write

Assuming what I've noted above is correct, then there is no data stream on those baud rates (else I would have got something output).

I'll try serial.write later, in which case, the data must be requested, and not the stream that I'd like to have!

Any recommendations on what else I could try ?

dcb 01-24-2011 10:49 PM


Originally Posted by toc (Post 216371)

But I think the problem there is I was using Serial.print, instead of Serial.write


Perhaps something more like a serial read would be in order?

toc 01-24-2011 11:34 PM

Ahh, but I was, in my loops, I was checking 30000 times for serial.available, and where there was, it was reading the data and sending that out (hence there was none).

I plan to test this circuit, I think:

So, make it RS232, and then take that to either TTL for arduino, or keep it RS232 and get the Laptop listening for data.

I couldn't get it working with just the wires direct to the arduino and those different baud rates - using this cable, I suspect request / response is needed, if no data stream is found.

If so, no problem, the code can adapt to that.

meelis11 01-26-2011 08:47 AM

Here is MMCD opensource code
Unofficial MMCd Project Site

Maybe it is possible to use its logic and some code to make that data to some useful values in MPGuino.

I am also interested because I have Mitsubishi Eclipse with 4G63 engine - I have succesfully made data cable (simpler version - only some resistors and diode, no MAX chip)

cable schematic (used laptop to ECU schematic)
Make a datalogger cable | Galant VR-4 > How To and Info Archive | Mitsubishi Galant VR4 Forum

I did manage to get data on laptop, using TMO Datalogger.


dcb 01-26-2011 10:50 AM

These are some goold aldl technical links. I think it isn't "standard" uart so the port cannot read it right.
Reading GM's 160 baud ALDL Data Stream with a Standard PC Serial Port

I like the idea of using an interrupt, would suggest doing like the guino injector interrupt handling:

int 0 and 1 tied to the input signal just like guino, except maybe with 10k resistor

int 0 is falling interrupt, notes time since last falling interrupt and last rising interrupt, resets timer counter, send the bit out the uart port as a 0 or 1 (or stage the bits to be packed/sent in the main loop)
if the signal was mostly hi, then that indicates a 0, else a 1, baud independant implementation.

int 1 is rising interrupt, notes current timer counter.

hook it up to a laptop and decypher the bitstream in something easier like java for proto-prototype on a laptop

toc 01-29-2011 03:20 AM

I've put together a circuit I believe works.

The baud rate is proving difficult though, I have proven 160-baud is not correct, 8192 baud is incorrect as well.
But, 1920 and 1953 both give replies.

I've been testing with RPM today, and can get varied results from both 1920-baud and 1953-baud, the data seems mostly correct when using both of the baud rates (as I'm taking the byte returned and reading it's hex value and then taking that to read out RPM).

I'm going to need to find something a bit more reliable to measure, something, that perhaps is more accurately measured, to see which of the above two baud rates are correct. Admittedly they are very similar, so the data could be identical at both 1953 baud and 1920 baud.

The list here is where I've tried RPM and battery voltage -

I'm looking for something I can test using the readings via the ALDL interface, and, independently - RPM is too hard to gauge accuracy - I had 2125 and 2180 - something that is hard to read on the RPM gauge. On the other hand, both of those numbers could have been perfectly correct, even at the different baud rates. I'd like to test and confirm it. Any ideas?

toc 01-30-2011 02:53 AM

I'm now trying to figure out why this is happening:

RPM: Result:Dat 0: 39Dat 1: 1A1A|RPM Val: 812
RPM: Result:Dat 0: 39Dat 1: 1A1A|RPM Val: 812

Less than 5 seconds later:

RPM: Result:Dat 0: B9Dat 1: DBDB|RPM Val: 6843
RPM: Result:Dat 0: 39Dat 1: 5B5B|RPM Val: 2843

The both results are taken 50ms apart, I don't see how the car has gone from 6000 RPM to 2000 RPM in a mere 50ms. The similarities in the data are also hard to ignore.

I think it's some sort of interference.

Battery Voltage seems stable, 13 - 14 is the readings I get - they are steady - But I think 12V should be there. Either way, it's not 113, so it is believable.

I guess I could test the far more simpler circuit with the 10k resistor from data to ground, and MAX232 to take it from RS232 to TTL!

Any ideas what is up with RPM?

dcb 01-30-2011 08:47 AM

I'm still stymied by the baud rate selections. It would seem a tricky thing to get right using a serial port. Have you looked at the signal with a scope (or a soundcard scope with a voltage divider on the line in?) Soundcard Scope

Are you getting valid checksums consistently?

toc 01-30-2011 09:36 AM

I'm not doing anything other than read and use the data!

The baud rate is 1920. The code on Source Forge for mmcd shows it as 1920, despite the webpage claiming 1953 - I checked with 1953 anyway.

Perhaps my breadboard, 2 x MAX232 chips, 12 capacitors, resistors, or the chopped cabling is noisy.

Another issue is the arduino might not have finished receiving when i've called (tho I do insist on either 2 bytes or 100ms).

So, there's still some elimination room there which I hope to tackle after work tomorrow maybe.

I haven't done anything with any form of oscilloscope.
I've simply got the MAX232 circuit facing the ALDL port, then another MAX232 taking it to TTL levels, then the arduino processing the data, then a USB -> TTL adapter to the serial monitor.

It is almost certainly, the circuit, or the ECU, or the timing of the arduino, affecting the data I am getting, the coincidence in the data (i.e. a "5A" value instead of "1A").

Below is another example too I guess:
RPM: Result:Dat 0: 39Dat 1: DBDB|RPM Val: 6843
RPM: Result:Dat 0: 39Dat 1: 1B1B|RPM Val: 843

I can only assume (though cannot explain) that '39' is the HEX of the query I sent (0x21).
DB is bad response, 1B is the correct response.
(The doubling up is actually done in code here, the second DB was my initial output to result, before I decided to push out the DAT value from within the function).
The above is the same 0x21 asked twice.

I did start looking at binary for what DB and 1B are - they appear very similar - which is where I thought electrical noise (a 1 being inadvertantly picked up), or, for example, the full data hadn't been received to make a 1B so DB resulted.. somehow...

The simpler circuit (i.e. remove the MAX232 facing the car, use just diode and resistor), might help - it might not.


dcb 01-31-2011 12:36 AM

mkay, made some progress at 160 baud. The code isn't quite ready for 1892 however (never synchs up). Might need to get more specific with the baud rates (or possibly the outbound uart code is piggy or the new arduino timer code is and has to be neutered again).

here is an arduino script that uses an aldl signal tied to pin2 and pin3 and converts it to a byte stream @57600 baud. two bytes per aldl character to preserve the synch character
PHP Code:

//aldl to serial adapter
//converts 9 bit aldl stream to integers over serial port.
extern volatile unsigned long timer0_overflow_count;

volatile byte lastbit=255//positive is a one, negative is a zero, 0 is already processed
volatile long falllength 0;
volatile long riselength 0;

void falling(){ 

void rising(){
falllength timer0_overflow_count;

void setup(){                    // run once, when the sketch starts
attachInterrupt(0falling,FALLING );
attachInterrupt(1rising,RISING );

byte synched 0;
int onecount=0;
int bf=0;
byte bp=8;

void loop(){
byte lb=255;
  while (
lb == 255){
//    cli();
//    sei();
//  cli();
//  sei();
Serial.print((char)1);//repeat the synch sequence for the client
synched==1){//ok, we are synched
bf=bf|lb << bp;
bp ==255){//we have 9 bits worth, send it over the port


Here is the arduino test script (I run it on a second arduino and run its pin 13 to the aldluino's pins 2 and 3), ground pin 12 and reset to simulate 8192-ish baud
PHP Code:

//test script for aldluino
#define sigpin 13
#define baudpin 12

/*   from
 T0-T1 = B = 0.5 mSec.
 T1-T3 = C = 4.75 mSec.
 T3-T4 = E = 1.0 mSec.
 T0-T4 = total = 6.25 mSec 
int low0=500;
int high0=5750;
int low1=5250;
int high1=1000;

void setup(){ 
digitalRead(baudpin)==LOW){//set up 8192

void sendch(int ch){//send out the msb 9 'bits'
for(int p=8;p>=0;p--){
int b=ch&1<<p;
long d b==0?low0:low1;

void loop(){
//cycle through sending 511 (synch), then an ascending odd number followed by a descending even
int x 1;<=255x+=2){

Here is a bit of java to read the serial data and print it in hex format
PHP Code:

public class 
Serial {
InputStream input;
OutputStream output;
    public static 
void main(String[] argsthrows Exception {
CommPortIdentifier portId CommPortIdentifier
SerialPort port = ("serial madness"4000);
input port.getInputStream();
output port.getOutputStream();
int i=0;
        while (
true) {
== -1)
== -1)


Here is a little bit of output from the java program, you can see the synch character 1ff here generated from the test arduino through the aldluino


Test circuit is trying to simulate this

toc 01-31-2011 12:50 AM

Ahh, I've got to request the data I think.
I think the 1920 baud is called MUT ?
It certainly doesn't seem to send the data without asking for it.

ALDL in the reference here appears to be not be targetted at DSM types (i.e. Mitsubishi, Hyundai, perhaps Kia).

dcb 02-01-2011 12:45 AM

mkay, 160 and 8192 are very different protocols, just figuring that out now. Do you have any doc/links on 1920?
Can you grab a couple bytes worth of data using a scope?

toc 02-04-2011 11:26 PM

Just a quick update:
I used the far more simplified circuit, noted here:
Make a datalogger cable | Galant VR-4 > How To and Info Archive | Mitsubishi Galant VR4 Forum

The Laptop version is what I used, not the palm version.

Then, took the RS232 and converted to TTL using the MAX232 (refer to the datasheet, it's very easy).

Then, connected to the arduino, then used the information on MMCD's page (1920 baud, 0x21 for RPM).

RPM values were very consistent and correct.

This tells me that for DSM / Mitsubishi 4G63 / Hyundai G4CP engines, that ALDL works correctly when the circuit for the interface is done correctly.

I can now proceed and take the request / responses and try and push that into the MPGuino code.

I'm waiting on an LCD display to start putting it together, but will start hacking out the code soon.

I can't get reliable readings from speed though!
I queried speed using the value noted online in a few places, and seemingly used by Evoscan (another Mitsubishi data logging / tune up tool).

The responses for speed varied wildly, see below:

Speed: Result: Dat 0: 2FDat 1: 00|Speed: 0
Speed: Result: Dat 0: 2FDat 1: 7777|Speed: 238
Speed: Result: Dat 0: 2FDat 1: D6D6|Speed: 428
Speed: Result: Dat 0: 2FDat 1: 9F9F|Speed: 318
Speed: Result: Dat 0: 2FDat 1: 2B2B|Speed: 86
Speed: Result: Dat 0: 2FDat 1: 7C7C|Speed: 248
Speed: Result: Dat 0: 2FDat 1: DDDD|Speed: 442
Speed: Result: Dat 0: 2FDat 1: ADAD|Speed: 346
Speed: Result: Dat 0: 2FDat 1: CCCC|Speed: 408
Speed: Result: Dat 0: 2FDat 1: 3333|Speed: 102
Speed: Result: Dat 0: 2FDat 1: 1313|Speed: 38
Speed: Result: Dat 0: 2FDat 1: 3232|Speed: 100
Speed: Result: Dat 0: 2FDat 1: CECE|Speed: 412
Speed: Result: Dat 0: 2FDat 1: C8C8|Speed: 400
Speed: Result: Dat 0: 2FDat 1: E6E6|Speed: 460
Speed: Result: Dat 0: 2FDat 1: A8A8|Speed: 336
Speed: Result: Dat 0: 2FDat 1: C3C3|Speed: 390
Speed: Result: Dat 0: 2FDat 1: 2C2C|Speed: 88
Speed: Result: Dat 0: 2FDat 1: 3737|Speed: 110
Speed: Result: Dat 0: 2FDat 1: 5A5A|Speed: 180
Speed: Result: Dat 0: 2FDat 1: 2929|Speed: 82
Speed: Result: Dat 0: 2FDat 1: 2D2D|Speed: 90
Speed: Result: Dat 0: 2FDat 1: 3636|Speed: 108
Speed: Result: Dat 0: 2FDat 1: 3C3C|Speed: 120
Speed: Result: Dat 0: 2FDat 1: 6C6C|Speed: 216
Speed: Result: Dat 0: 2FDat 1: 1E1E|Speed: 60
Speed: Result: Dat 0: 2FDat 1: 7C7C|Speed: 248
Speed: Result: Dat 0: 2FDat 1: 2222|Speed: 68
Speed: Result: Dat 0: 2FDat 1: 1111|Speed: 34
Speed: Result: Dat 0: 2FDat 1: 4B4B|Speed: 150
Speed: Result: Dat 0: 2FDat 1: 8989|Speed: 274
Speed: Result: Dat 0: 2FDat 1: 8686|Speed: 268
Speed: Result: Dat 0: 2FDat 1: 44|Speed: 8
Speed: Result: Dat 0: 2FDat 1: 1B1B|Speed: 54
Speed: Result: Dat 0: 2FDat 1: 66|Speed: 12
Speed: Result: Dat 0: 2FDat 1: 2424|Speed: 72
Speed: Result: Dat 0: 2FDat 1: BABA|Speed: 372
Speed: Result: Dat 0: 2FDat 1: 33|Speed: 6
Speed: Result: Dat 0: 2FDat 1: DEDE|Speed: 444
Speed: Result: Dat 0: 2FDat 1: 8686|Speed: 268
Speed: Result: Dat 0: 2FDat 1: E0E0|Speed: 448
Speed: Result: Dat 0: 2FDat 1: 88|Speed: 16
Speed: Result: Dat 0: 2FDat 1: B1B1|Speed: 354
Speed: Result: Dat 0: 2FDat 1: 2B2B|Speed: 86
Speed: Result: Dat 0: 2FDat 1: 2828|Speed: 80
Speed: Result: Dat 0: 2FDat 1: 9090|Speed: 288
Speed: Result: Dat 0: 2FDat 1: F3F3|Speed: 486
Speed: Result: Dat 0: 2FDat 1: DD|Speed: 26
Speed: Result: Dat 0: 2FDat 1: 2B2B|Speed: 86
Speed: Result: Dat 0: 2FDat 1: EDED|Speed: 474
Speed: Result: Dat 0: 2FDat 1: 5454|Speed: 168
Speed: Result: Dat 0: 2FDat 1: C3C3|Speed: 390
Speed: Result: Dat 0: 2FDat 1: 3C3C|Speed: 120
Speed: Result: Dat 0: 2FDat 1: E0E0|Speed: 448
Speed: Result: Dat 0: 2FDat 1: 6767|Speed: 206
Speed: Result: Dat 0: 2FDat 1: 9F9F|Speed: 318
Speed: Result: Dat 0: 2FDat 1: B4B4|Speed: 360
Speed: Result: Dat 0: 2FDat 1: D6D6|Speed: 428
Speed: Result: Dat 0: 2FDat 1: 1F1F|Speed: 62
Speed: Result: Dat 0: 2FDat 1: 3D3D|Speed: 122
Speed: Result: Dat 0: 2FDat 1: F9F9|Speed: 498
Speed: Result: Dat 0: 2FDat 1: 1E1E|Speed: 60

- My little car couldn't ever achieve speeds of 498km/hr, and if it did, I certainly wasn't being an eco driver - maybe the calculation is wrong.

This gives me solid confirmation that the circuit works tho, this is great.
If it wasn't the circuit that fixed it, it would have been the 10ms delay after the data was requested.

toc 02-05-2011 08:07 AM

There is another random thought here that ought to be tested prior to implementation, that is timing.

Current MPGuino code relies on direct reading of the Injectors and VSS - this is all fine and dandy, does what the ECU does.

When you are using a diagnostic setup, such as ALDL, OBD-II, or the Mitsubishi request / response protocol, the timing of the VSS pulses for example, are just not there (at least I don't think so.. hmm.. maybe that is what my Speed reading above is?) - back to where I was going - when MPGuino is getting the data directly, it has no issue - the current fuel consumption data is being provided to it for it to calculate and display.

When it has to take steps to ask for this information, the delay added would affect the accuracy of the data.

I think of it like this (I'm yet to test, but keen to see what comments appear (i.e. dcb - looking at you!), if the data is requested, and then you open wide throttle, the next update could be many ms away, so use of the MPGuino might ot be suitable for that purpose?

I will try and get some testing done tomorrow to find how long each request roughly takes (I'll remove the 10ms delay and make the code very efficient), and see how many responses to my requests are possible - this would all be without any calculation workload - which would delay updates further.

Are the delays going to be a problem at all??

The data stream for other cars (i.e. 160-baud and 8192-baud appears to be a stream from posts, so even this is delayed by the ECU's choice of when to send the data and in what order).

Am I wrong?

dcb 02-05-2011 10:08 AM


Originally Posted by toc (Post 218735)
Are the delays going to be a problem at all??

It will have an affect on accuracy as the resolution isn't great. Obd II solutions have the same issues, accuracy is limited by how many readings per second you can extract from the cpu (baud/packet size). Over time it should sorta average out, though not entirely, as driving style can affect the readings a bit. I don't have a swag though. But you have "easy" access to other sensors and such.

FalconFour 02-12-2011 04:05 AM

Holy crap, so uhm, apparently I don't have a subscription to this thread for some reason. Hence why I've been MIA here... didn't even know the idea was still active! Wait, yes I do, why haven't I been getting 'em? Ugh. Weird.

Excuse me while I catch up... :P

edit: Hmm, wow, a lot of progress made here, it seems. However, I'm getting a little bit of "protocol error" here myself, in a literary sense. I haven't yet seen anyone share what type of OBD system they're using to test these different baud rates. Even different variations of OBD use different baud rates and different protocols, or not even OBD at all (proprietary diagnostic connectors used in import cars, far as I understand). For example, here is the OBD/ALDL connector on my car:
(10k resistor between "ground" and "diagnostic" = getting 160 baud data on "data"; shorting "ground" and "diagnostic" = flashing error codes using SES light, engine running in timing mode)

Anyone got pictures of their connectors? Or think this is relevant? I just don't think we'll get very far with one guy testing the other guy's code on totally different systems...

toc 02-12-2011 05:10 AM

Ahh, that is why you adapt.

OBDuino for example allows for the ISO and CAN type setup.

My setup will be MUT so it's a fair bit of rewriting and reworking but it's doable - I've got things myside down pretty clear now with exception of speed measurements which must be averaged to be usable - but I have a different calculation I will try there.

If I had things easier, I would have just gone straight to the injector cable - but I want to use the diagnostics instead for different measurements.

It works, you do however need the knowledge to adapt it to differing cars (perhaps, differing variations could all be merged, but the code would expand too much - it wouldn't fit on an Arduino).

e.g I could take OBDuino and add support for MUT to it, but the end result would be fat and full of code not being used.

toc 03-03-2011 01:06 AM

I've tried again to use "Pin 11" of the ALDL connector to form some sort of speed input on it.

On the arduino I have been using this:

#include <LiquidCrystal.h>

int pinTachoInHz = 2; // D2 for Tacho Input - Measuring the Hz
long TachoInHz = 0; // declare this as a byte if the count is always less than 255
// so you don't have to disable interrupts when using in loop
long intTachoInHz_Millis = 0;
long prevTacho;
long readingMillis = 0;
long prevMillis;
float vssPulsesPerKM = 4750.0;

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

void setup() {
// Configure serial output

//Configure pin modes

lcd.begin(20, 4);

pinMode(pinTachoInHz, INPUT);
digitalWrite(pinTachoInHz, HIGH); // Turn on pullup resistor
attachInterrupt(0, count, RISING); // call count when pin 2 goes high


void loop(){
analogWrite(3, 55);
analogWrite(8, 200);
float curSpeed = 0;
long tachDiff = 0;
float dataMillis = 0;
lcd.setCursor(0, 0);
lcd.print("Sensor: ");
long tachoCount = TachoInHz; // get a snapshot of the count
readingMillis = millis();
dataMillis = readingMillis-prevMillis;
tachDiff = tachoCount-prevTacho;
float dataTacho = (tachDiff / dataMillis) * 1000;
lcd.setCursor(0, 1);
lcd.print("Speed: ");
curSpeed = (dataTacho * 60) / vssPulsesPerKM;
prevTacho = tachoCount;
prevMillis = readingMillis;
lcd.setCursor(0, 2);
lcd.print("ODO: ");
float odo = tachoCount / vssPulsesPerKM;
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.print(dataTacho / vssPulsesPerKM);
// count the ms between each update, divide by the total ms (i.e. ms2 - ms1)
// Then, times 1000 to get pulses per second.
// divide by 4750
//times by 3600 and viola that should be very close.

// Else, look into Timer2 as another option.

// this needs to be fixed up!

void count(){

Unfortunately, I'm still seeing inaccurate results.

I had another thought of using PulseIn to time the lengths of the pulses, this might give me something proportional to speed to work with.

Pin 11 of the ALDL connector is apparently, an output of vehicle speed (so the speedo cable goes to the ECU, the ECU puts out a 5V signal proportionate to the speed - and this should get faster as the vehicle is faster is my understanding).

Is there a better way to read that signal with minimal errors?

As you can see, 4750 is what I believe the number of pulses in a km are - but even that could be wrong if there are pulses missing for example - I know something is wrong, as the odo count is out - I drove 2KM according to the car ODO, this did not replicate to the odo count.

oldskool 02-08-2012 09:53 PM

Hi Toc,

I'm Rizal and I'm from Malaysia. I'm so interested about your project on communication between arduino and Mitsubishi ecu. I have read your post from beginning but until now i still can not connect to my 4g91 ecu.

For your information, i have successfully connect to my ecu using Plam (MMCd)

Can you help me how are you doing this. Maybe some electrical circuit and arduino source code may help.

toc 02-09-2012 01:49 AM

I ended up building something similar to this circuit to get communicating:

Then in Arduino, the program was similar to:

With these:
wireless.print("Battery: Result:");
temp_val = fetch_data(0x14);
temp_real_val = temp_val * 0.0733;
wireless.print(temp_val, HEX);
wireless.print("|Bat Val: ");

wireless.println("Testing at 1920bps");
wireless.print("RPM: Result:");
temp_val = fetch_data(0x21);
temp_real_val = temp_val * 31.25;

The fetch data function:

int fetch_data(byte cmd) {
int dat[3];
int temp;
int i;
starttime = millis();
while ((Serial.available()<2) && ( (millis() - starttime) < MAX_WAIT_TIME) ) {
//do nothing
if (Serial.available()<2) {
wireless.print("Error - 2 Bytes not found - We did get:");
wireless.println(, HEX);
} else {
i = 0;
while (Serial.available() > 0) {

temp =;
wireless.print("Dat ");
wireless.print(": ");
wireless.print(temp, HEX);
dat[i] = temp;
//dat[0] should be the cmd we sent
//dat[1] should be the result of the cmd.
return dat[1];


You can find a full list here;
MUT Requests - EvoEcu

I never did finish testing for adequate programming though I do know I was receiving correct data for RPMs and Battery Voltage and some other parameters - but I ended up selling the Hyundai so never finished it off.

Now I'm trying to do it with a Nissan (Damned lack of OBDII support!!!)

oldskool 02-09-2012 05:42 AM

Hi.. Toc,

Thanks a lot for sharing the source code... really appreciate it.. I will run the source code and give the feedback once it can connect.

oldskool 03-06-2012 04:22 AM

Dear Toc,

I have tried your source code and get so many incorrect response from the ecu. May i know what is the value for MAX_WAIT_TIME


All times are GMT -4. The time now is 06:04 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2022, vBulletin Solutions Inc.
Content Relevant URLs by vBSEO 3.5.2
All content copyright