Jump to content


Photo

Sniffing Mems 2J


  • Please log in to reply
23 replies to this topic

#1 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 11 April 2018 - 05:19 PM

First, a bit of history…


I’ve owned a Mini, Cooper Sport MPI, for three years now and, as we all have with our Minis, I have had numerous issues. One of the long standing issues is that it always struggles through the MOT emissions but my local Mini mechanic and the tester always prod at it until it passes. I’ve also had other electrical issues with the cooling fan etc. which prompted me to invest in a diagnostic reader. Searching around gave me very few options as no one has reverse engineered the communication for MEMS 2J (and open source it…) so I opted for a Sykes Pickavant ACR4 which was pretty expensive!!!


Whilst the ACR4 has proved useful reading error codes and looking at live information, I feel it lacks things like graphing sensor values over time and for spurious issues, I cannot simply record a drive and then analyse the data later. Recently I’ve seen a few posts for the SPI where people have been using free/open source tools with such functionality and I’m jealous!


So here I embark on equipping all the MPI owners out there with equivalent functionality, aiming to integrate this in to existing tools so that, as a community, we have good, free! and consistent methods of diagnosing our pesky injection Mini’s which we love!


I’m going to write up my story in detail, for two reasons:

  1. So others can understand what’s been done

  2. People can correct me when I’ve done the wrong things :)


Let’s get sniffing….

 



#2 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 11 April 2018 - 07:37 PM

So, I have the ACR4 and an MPI and these work well together but what are they saying to each other?


Looking at the Haynes manual it does look like the OBD2 connector also has the correct wiring, i.e. a single data line (bi directional k-line) to the ECU, to be an OBD2 compliant interface?

 

Taking apart the Sykes Pickavant ACR4 connector shows the following pins connected:

  • Pin 4 - Assuming ground as per Haynes manual
  • Pin 7 - Assuming bi-directional k-line to ECU
  • Pins 14&15 - Tied together and go back to the ACR4 (not sure what these are for…)
  • Pin 16 - Assuming 12V as per Haynes manual

Connecting up a power supply to pins 4 and 16 springs the ACR4 in to life so at least some of the assumptions above are correct.

Now I just need to find out what's going on in Pin 7 but will need something to probe this with. Half expecting a logic analyser to be expensive, I was pleasantly surprised that I could get one from Hobby Components for £10! Bargain!

 

Using the hobby components logic analyser, and assuming the interface to the ECU is in fact a k-line interface (ISO9141) and therefore essentially a bidirectional bus at 10.4kbps, we can see that the ACR4 sends the following bytes in order to initiate a connection:

 

acr4_init.png?raw=1

 

I believe ISO9141 dictates that the final byte of a command is a simple checksum, so let’s see if this is also the case for the MEMS 2J protocol.


Checksum = 0x81 + 0x13 + 0xF7 + 0x81 = 20C

Therefore, yes, it looks like the final byte is a checksum!


At this time I’ve not even gone near the car so we’re not going to see any kind of response from the ECU, instead we just see the above command repeating 5 times before the ACR4 states that communication has failed and beeps at me wildly.


Before getting deeper in to the communication protocol, I wanted to see how easy it would be to tweak librosco to add support for the MEMS 2J protocol. After a little bashing on the keyboard and a similar sniffing test using a VAG-COM ODB2 cable from eBay that is essentially a serial port to k-line converter, we can see that the modified librosco can send the necessary bytes at the correct baud rate:

 

librosco_init.png?raw=1

 

Comparing with the data from the ACR4, the timing appears to be an issue… Looking at the original capture shows data bytes are spaced apart by 4.2ms (start to start)

 

acr4_init_byte_timing.png?raw=1


So let’s try adding a delay in librosco between data bytes to see if that improves the comparison...

 

librosco_init_byte_timing.png?raw=1
 

Great, that’s looking much better! The timing isn’t guaranteed but I hope it’s close enough to where we need to be (if we even need it at all?). We are still missing something when compared to the ACR4 though - the TX line going low prior to the initialisation command:
 

acr4_init_break.png?raw=1

 

Unfortunately, with just an interface to a dummy serial port there is no way to perform this, we’d have to communicate directly with the USB -> Serial converter. This is where I find out the VAG-COM cable I have bought is using a crappy CH340 chip that provides no such functionality, where as an FTDI device would! Another quick order for a new FTDI VAG-COM cable from eBay again (double the price for a decent chip) and some more librosco tweaks will hopefully yield similar results to what the ACR4 does…

 

librosco_init_break.png?raw=1
 

Excellent!

 



#3 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 11 April 2018 - 07:52 PM

I’m now confident with the tools I have to further sniff and try to reproduce the MEMS 2J protocol so let’s try and get more data by seeing what the responses of the ECU are. For this test I am simply initiating communication on the ACR4 but not performing any further action.


Looks like we have lots of data going back and forth!!!


I’ve done three separate runs of the same test (to see if the commands/responses are ever different) and these are the results:

 

Run 1

TX: 81 13 F7 81 0C
RX: 03 C1 D5 8F 28
TX: 02 10 A0 B2
RX: 01 50 51
TX: 02 27 01 2A
RX: 04 67 01 96 A4 A6
TX: 04 27 02 D9 34 3A
RX: 02 67 02 6B
TX: 02 3E 01 41
RX: 01 7E 7F
Command above repeats...

Run 2

TX: 81 13 F7 81 0C
RX: 03 7F 81 10 13
TX: 02 10 A0 B2
RX: 01 50 51
TX: 02 27 01 2A
RX: 04 67 01 00 00 6C
TX: 04 27 02 00 01 2E
RX: 04 67 01 00 00 6C
TX: 02 3E 01 41
RX: 01 7E 7F
Command above repeats...

Run 3

TX: 81 13 F7 81 0C
RX: 03 7F 81 10 13
TX: 02 10 A0 B2
RX: 01 50 51
TX: 02 27 01 2A
RX: 04 67 01 00 00 6C
TX: 04 27 02 00 01 2E
RX: 04 67 01 00 00 6C
TX: 02 3E 01 41
RX: 01 7E 7F
Command above repeats...

As we can see from the three runs, there is a certain degree of variability in the commands and responses - run 2 and 3 happen to match but run 1 is different.

 

There is a distinct pattern in the commands and responses though which will help us understand what’s being sent and responded to. For both the command and response case, the first byte always appears to be the length without the checksum byte. For the response, the second byte always appears to be the second byte of the command + 0x40! This does not ring true for the first command (apart from the length byte) which I imagine is a special initialisation command/response.


As the ACR4 continually repeats the final command shown (02 3E 01 41), I believe this to be a heartbeat command or ping to keep the communications open. My plan is to initially establish comms using librosco and maintain this using the same heartbeat command. As there appears to be no difference in the initial command sent then I will simply use this and ignore the following 3 commands prior to sending the heartbeat. Let’s make some changes to librosco and see if we can communicate with the ECU:

Using MEMS 2J
Running command: heartbeat
mems_read_serial(): read 1 bytes, expected 1: 00
mems_send_command_with_checksum(): sending command...
mems_write_serial(): writing 1 bytes: 81
mems_write_serial(): writing 1 bytes: 13
mems_write_serial(): writing 1 bytes: F7
mems_write_serial(): writing 1 bytes: 81
mems_send_command_with_checksum(): sending checksum...
mems_write_serial(): writing 1 bytes: 0C
mems_send_command_with_checksum(): reading back echoed bytes...
mems_read_serial(): read 1 bytes, expected 1: 81
mems_read_serial(): read 1 bytes, expected 1: 13
mems_read_serial(): read 1 bytes, expected 1: F7
mems_read_serial(): read 1 bytes, expected 1: 81
mems_send_command_with_checksum(): reading back echoed checksum...
mems_read_serial(): read 1 bytes, expected 1: 0C
mems_read_response_with_checksum(): reading length byte...
mems_read_serial(): read 1 bytes, expected 1: 03
mems_read_response_with_checksum(): reading response bytes...
mems_read_serial(): read 3 bytes, expected 3: C1 D5 8F
mems_read_response_with_checksum(): reading checksum byte...
mems_read_serial(): read 1 bytes, expected 1: 28
ECU responded to initialization with: 00 00 00 00
mems_send_command_with_checksum(): sending command...
mems_write_serial(): writing 1 bytes: 02
mems_write_serial(): writing 1 bytes: 3E
mems_write_serial(): writing 1 bytes: 01
mems_send_command_with_checksum(): sending checksum...
mems_write_serial(): writing 1 bytes: 41
mems_send_command_with_checksum(): reading back echoed bytes...
mems_read_serial(): read 1 bytes, expected 1: 02
mems_read_serial(): read 1 bytes, expected 1: 3E
mems_read_serial(): read 1 bytes, expected 1: 01
mems_send_command_with_checksum(): reading back echoed checksum...
mems_read_serial(): read 1 bytes, expected 1: 41
mems_read_response_with_checksum(): reading length byte...
mems_read_serial(): expected 1, got -1
mems_read_response_with_checksum(): failed to read response length byte

It looks like it is working to some extent, at least we’re getting bytes back from the ECU with valid checksums so the communication method appears to be working. Occasionally, we do not read a response though - perhaps something in the timing:

 

acr4_init_first_command_delay.png?raw=1


acr4_init_command_delay.png?raw=1

 

The logic analyser shows that following the last received byte of the initialisation command there is a 100ms pause before the next command and all commands after this there is a 50ms pause between commands. Adding this in to librosco gives reliable comms over 3 separate runs, at least for the heartbeat command!
 

Using MEMS 2J
Running command: heartbeat
mems_read_serial(): read 1 bytes, expected 1: 00
mems_send_command_with_checksum(): sending command...
mems_write_serial(): writing 1 bytes: 81
mems_write_serial(): writing 1 bytes: 13
mems_write_serial(): writing 1 bytes: F7
mems_write_serial(): writing 1 bytes: 81
mems_send_command_with_checksum(): sending checksum...
mems_write_serial(): writing 1 bytes: 0C
mems_send_command_with_checksum(): reading back echoed bytes...
mems_read_serial(): read 1 bytes, expected 1: 81
mems_read_serial(): read 1 bytes, expected 1: 13
mems_read_serial(): read 1 bytes, expected 1: F7
mems_read_serial(): read 1 bytes, expected 1: 81
mems_send_command_with_checksum(): reading back echoed checksum...
mems_read_serial(): read 1 bytes, expected 1: 0C
mems_read_response_with_checksum(): reading length byte...
mems_read_serial(): read 1 bytes, expected 1: 03
mems_read_response_with_checksum(): reading response bytes...
mems_read_serial(): read 3 bytes, expected 3: C1 D5 8F
mems_read_response_with_checksum(): reading checksum byte...
mems_read_serial(): read 1 bytes, expected 1: 28
ECU responded to initialization with: 00 00 00 00
mems_send_command_with_checksum(): sending command...
mems_write_serial(): writing 1 bytes: 02
mems_write_serial(): writing 1 bytes: 3E
mems_write_serial(): writing 1 bytes: 01
mems_send_command_with_checksum(): sending checksum...
mems_write_serial(): writing 1 bytes: 41
mems_send_command_with_checksum(): reading back echoed bytes...
mems_read_serial(): read 1 bytes, expected 1: 02
mems_read_serial(): read 1 bytes, expected 1: 3E
mems_read_serial(): read 1 bytes, expected 1: 01
mems_send_command_with_checksum(): reading back echoed checksum...
mems_read_serial(): read 1 bytes, expected 1: 41
mems_read_response_with_checksum(): reading length byte...
mems_read_serial(): read 1 bytes, expected 1: 01
mems_read_response_with_checksum(): reading response bytes...
mems_read_serial(): read 1 bytes, expected 1: 7E
mems_read_response_with_checksum(): reading checksum byte...
mems_read_serial(): read 1 bytes, expected 1: 7F
mems_send_command_with_checksum(): sending command...
mems_write_serial(): writing 1 bytes: 02
mems_write_serial(): writing 1 bytes: 3E
mems_write_serial(): writing 1 bytes: 01
mems_send_command_with_checksum(): sending checksum...
mems_write_serial(): writing 1 bytes: 41
mems_send_command_with_checksum(): reading back echoed bytes...
mems_read_serial(): read 1 bytes, expected 1: 02
mems_read_serial(): read 1 bytes, expected 1: 3E
mems_read_serial(): read 1 bytes, expected 1: 01
mems_send_command_with_checksum(): reading back echoed checksum...
mems_read_serial(): read 1 bytes, expected 1: 41
mems_read_response_with_checksum(): reading length byte...
mems_read_serial(): read 1 bytes, expected 1: 01
mems_read_response_with_checksum(): reading response bytes...
mems_read_serial(): read 1 bytes, expected 1: 7E
mems_read_response_with_checksum(): reading checksum byte...
mems_read_serial(): read 1 bytes, expected 1: 7F

Looks like we’re getting somewhere! Next step is to actually get some data...

 



#4 Wiggy

Wiggy

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,036 posts
  • Location: Hampshire

Posted 11 April 2018 - 09:28 PM

This is over my head, but very interesting. Nice work.

#5 pete l

pete l

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,358 posts
  • Location: East of France

Posted 17 April 2018 - 08:43 AM

Don't give up, this could be very interesting.



#6 Steve220

Steve220

    Up Into Fourth

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 4,885 posts
  • Location: Shropshire
  • Local Club: RAF Mini Club

Posted 17 April 2018 - 10:32 AM

I was lost after 'I owned a Mini'...



#7 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 21 August 2018 - 07:30 PM

I can't believe it's been over 4 months since I started this!

 

Unfortunately I haven't managed to progress any further but I have finally pushed my code changes so far to my GitHub forks of librosco and memsgauge:

My changes include modifying librosco to use the FTDI drivers directly instead of a virtual COM port. This is required for MEMS 2J. It would be good to know if the library (and readmems.exe) still work for the SPI (MEMS 1.6). As far as I know most people have built a cable using the FTDI chip so hopefully it shouldn't be a problem.

 

The drivers will need to be installed from here: http://www.ftdichip....21228_Setup.zip

 

I've packaged up the memsgauge install directory, including a copy of readmems.exe, for people to try so you don't have to build from scratch. You can find the package here: https://www.dropbox....sgauge.zip?dl=0

 

If anyone is ambitious and would like to help this progress then give it a go, whether you have an SPI or an MPI!

 

SPI Owners

The software should work as before, once the FTDI drivers are installed. It is completely untested though.

 

MPI Owners

The memsgauge application won't do much other than initiate a connection.

The readmems command line application should be able to negotiate a connection and keep it alive with heartbeat commands.

 

 

Meanwhile, I'll try and find some spare time to get some useful data from the MPI so my changes are actually useful  :proud:



#8 Bat

Bat

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 903 posts
  • Location: Bermingum

Posted 21 August 2018 - 09:50 PM

Hi,

Excellent work so far and will be a massive help to everyone on the forum when completed  :D

Cheers  :proud:



#9 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 24 August 2018 - 09:07 PM

I found a little more time last night to look at this and was thinking of how I'm going to determine what the commands that the ACR4 sends to the ECU actually mean. Using the known state of some of the sensors could work but may be difficult!

 

If I could inject custom values for each of the commands, and see which status changes on the ACR4 unit then I can easily work out what each command is used for. So I went off to write a MEMS 2J Simulator which I can plug the ACR4 diagnostic in to and fool it to thinking it's actually talking to an ECU. I've reached a similar point to that of the librosco changes where I can successfully initiate a connection and keep it alive with heartbeat responses. The code I've written for this can be found here: https://github.com/k...mems2jsimulator

 

My plan now is to see what extra commands the ACR4 sends when entering the 'Components' menu and slowly adding these to the simulator to give responses. I can then selectively either set these responses to 0 or a changing value to see which reading is changing on the ACR4.

 

I'll provide another update when I've got some info using the simulator. :D



#10 Bat

Bat

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 903 posts
  • Location: Bermingum

Posted 25 August 2018 - 04:54 AM

Hi,

This reverse engineering caper isn't easy, takes some time and skills.

It's probably why no major company has took it on due to the limited market for it.

As you've already realised what you're doing is the missing link in the diagnostic process at the moment.

Cheers  :proud:



#11 jamesmpi

jamesmpi

    Camshaft & Stage Two Head

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,940 posts
  • Location: Chichester
  • Local Club: Abingdon Mini Owners Club

Posted 05 September 2018 - 12:38 PM

This is fascinating but I’m completely lost....

#12 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 08 October 2018 - 08:30 PM

From an old logic analyser capture I had I have looked at the commands that the ACR4 starts sending when opening up the "Components" section. The following commands and responses are seen:

 

Command: 02 21 06 29

Response: 0C 61 06 26 77 26 9F 02 86 02 D2 00 00 31

 

Command: 02 21 00 23

Response: 16 61 00 0A E5 0A E5 0A E5 08 B8 0A F9 0A F9 02 51 10 88 00 FC 08 B8 B1

 

Command: 02 21 09 2C

Response: 04 61 09 00 00 6E

 

Command: 02 21 01 24

Response: 04 61 01 0A E5 55

 

Command: 02 21 03 26

Response: 04 61 03 0A F9 6B

 

Command: 02 21 07 2A

Response: 04 61 07 26 77 09

 

The last 4 commands are then repeated, I believe each command is for one status value that is shown on the ACR (I have the 4 line version).

 

Plugging these commands in to the MEMS 2J simulator I have written (https://github.com/k...mems2jsimulator) successfully manages to respond status values to the ACR4 and fool it to thinking that it's reading status from a MEMS 2J ECU! Wahoo!

 

However, changing one of the reported status values on the ACR4 away from one of the commands that I implemented above soon makes the communication fall over as we do not respond to the command in the simulator, thus causing the ACR4 to lose comms. This is a pain but it means that I can work out what commands give what status values. i.e. By switching to a new status value on the ACR4 and seeing what the new command sent to the simulator is will give us the correlation between command and status value!

 

Performing the above on all the status values on the ACR4 give the following mapping:

 

Command Byte     Expected Response Bytes     Notes

0x00             20                          ???

0x01             2                           ECT

0x03             2                           IAT

0x06             10                          ???

0x07             2                           MAP

0x08             2                           TPS

0x09             2                           RPM

0x0A             2                           O2 volts bank 1

0x0B             2                           Coil 1 charge time (also coil 2?)

0x0C             2                           Injector 2 pulse width (also injector 1?)

0x0F             2                           Throttle switch = bit 2

0x10             2                           Battery Volts

0x11             2                           CAM Signal = Bit 2, Crank Signal = Bit 3 (also ignition switch and air con req?)

0x12             2                           Stepper position

0x13             2                           E/Back bank 1

 

I've coded these in to the simulator so the ACR4 can be used in the "Components" section with the sim without dropping communications. It doesn't report sane values but it keeps responding to commands! I will try to play with some of the commands so that I can work out the exact format of the data response.


Edited by kangaroomadman, 08 October 2018 - 08:33 PM.


#13 ed4ran

ed4ran

    Cadwell Event organiser

  • TMF+ Member
  • PipPipPipPipPipPipPipPipPip
  • 2,849 posts
  • Location: Stoke On Trent

Posted 28 January 2019 - 02:27 PM

Any update on this, very interesting!!
Ive got an mpi engine to put into my mini after a bit of a refresh and I have another project with a different engine that also uses the ISO9141 protocol so both should benefit from this kind of info / project.
Once I get things setup I wouldn't mind supporting / helping if I can.



#14 kangaroomadman

kangaroomadman

    Stage One Kit Fitted

  • Noobies
  • PipPipPip
  • 66 posts
  • Location: Southampton

Posted 28 January 2019 - 03:12 PM

I've been struggling for spare time recently so have made no progress  O_O

I had been meaning to set up the build on my new laptop so I'll try and at least get that done this week.



#15 pete l

pete l

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,358 posts
  • Location: East of France

Posted 06 January 2020 - 03:01 PM

any update  ???






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users