ECU Diagnostics – part 13.3 : MBE-ISOTP

SUMMARY

We now understand the communications protocol used by Easimap and can use it to ask the ECU for whatever data the car has to offer. We can then manipulate the responses we get back from the car and format them to make sense to us.

TL;DR

I’ve got to a point now where I think we understand how Easimap is talking to the car and how it formats the data fields it gets from the car. And therefore we can just do the same to get whatever data the car has to offer.

What I haven’t looked at yet is how Easimap can set parameters in the car’s ECU. I will take a look at that at some point but for the moment my interest is in creating some sort of Linux tool that can extract data from the car and display it. I may also have a look at whether the mappings on the ECU can be changed, though the general consensus is that the ECU’s are locked, and I have no reason to change that theory at the moment. I’m not sure how that locking occurs or whether it can be circumvented. At the moment I’m not interested in that side of things and have no intention of looking at it – at least at the moment.

So, to that end… here’s what I understand now about what I call the “MBE-ISOTP” protocol used by MBE in their Easimap software and the ECU’s.

Firstly, this protocol is a multi-layered protocol. It’s a bit like Russian Dolls, the actual data packets used by MBE are a couple of layers deep inside the doll. In order to look at the data the way that the ECU does we have to capture the data from the OBD port CAN bus and then unpack it a couple of times to get at the real data.

The unpacking layers in this case are CAN, ISOTP (ISO-15765) and a proprietary MBE layer.

Lets dig into the various layers and explain what’s going on, hopefully this will help future developers.

CAN LAYER

Here’s a refresher on the CAN bus layer…

The OBD-II port (on my car (2017 420R) and most modern-ish Caterhams) connects to the ECU by way of a two wire differential voltage protocol. It uses CAN-H and CAN-L to signal 1s and 0s on the CAN bus.

There are two critical things here in each CAN packet… firstly there’s the CAN ID (identifier) and then there’s the Data. The CAN ID can be either 11bits long or 29bits long. On my car with the MBE 9A4 ECU, it uses 29bit IDs. But other Caterhams also seem to use 11bit, probably with unlocked ECUs.

Secondly, the CAN packet contains up to 8 bytes of data. The CAN standard does allow for more than 8 bytes but it doesn’t seem as though our cars don’t use that version of the protocol.

Other than the ID and data, the CAN packet also contains lots of start bits, CRC (cyclic redundancy check) error checking, data length parameters and an ACK section. The ACK section is perhaps worth a few words: a sending device on the network only knows if “something” has received it’s CAN packet if a receiver sets the ACK bit when it received the data.

Anyway, on to the more interesting stuff.

The 29bit CAN IDs are used as payload type identifier – When a device sending on the bus sets a particular ID, it is telling any receiver what sort of protocol to expect in the packet.  I’ll talk more about the specifics of the IDs used in our cars when I get onto the ISOTP layer below.

So, at a high level view of each CAN packet, there are the two things we’re interested in, the CAN ID and the Data. For our cars the IDs are 29bit and the data can be up to 8 bytes.

And a packet looks like this when we’ve captured it from the CAN bus:

#   Time        Prot Len Info CAN ID       Data
168 1.612770860 CAN  32  XTD: 0x0cbe1101   10 08 01 00 00 00 00 f8
169 1.613462515 CAN  32  XTD: 0x0cbe1101   21 7c 7d 00 00 00 00 00
170 1.614548554 CAN  32  XTD: 0x0cbe0111   03 81 34 12 00 00 00 00

This data is laid out in columns by the packet sniffing tool I’m using (Wireshark/tshark). 

  • # = Frame Number
  • Time = number of seconds since the packet capture started
  • Prot = Protocol (CAN)
  • Len  = Length of the capture packet. This is not the CAN data length, that’s always 8 for us
  • CAN ID = 29bits (shown as hexadecimal in this example)
  • Data = Data in the CAN frame, shown as hexadecimal bytes

You’ll see why I picked those particular frames a bit later.

From the three packets above we can see that in order to talk to the ECU using this protocol you need to set any request packets with a CAN ID of 0x0cbe1101
and expect a response from 0x0cbe0111.

So, to recap… when we put a packet sniffer (Raspberry Pi with PICAN2 interface in my case) and watch (sniff) the CAN bus, we see a succession of lines of output from our packet sniffer like above.

ISOTP

Ok. So lets look at one level of Russian Dolls down (smaller doll).

As you can see from the example above, our particular implementation of the CAN protocol allows the car and any other device on the CAN bus to talk in chunks of 8 bytes at a time.

Now, this is quite restrictive for a modern car. The communication between Easimap and the car ECU might need to send all sorts of data that is longer than 8 bytes. For instance a 2 dimensional engine fueling map that might be hundreds of bytes long.

The MBE ECU and Easimap get over this problem by adding another protocol on top of the CAN bus interface (another Russian Doll). This protocol is called ISO-15765 or ISO-TP. By formatting the data in the CAN bus frames we can send one ISO-TP “packet” across multiple CAN bus frames – allowing us to send more than 8 bytes in a frame.

Here’s the same 3 CAN packets from above, but this time we looking at it through an ISO-TP dissector (its dissecting the packet stream and viewing it as though it is formatted in accordance with the ISO-TP protocol).

#   Time        Proto    Len Info                     Data
168 1.6127708 ISO15765 32 First Frame(Frame Len: 8) 01 00 00 00 00 f8
169 1.6134625 ISO15765 32 Consecutive Frame(Seq: 1) 7c 7d
170 1.6145485 ISO15765 32 Single Frame(Len: 3)      81 34 12

Packets 168 and 169 are actually a single ISO-TP frame. The “First Frame” and the “Consecutive Frame” are “fragments” of a whole frame and can be joined together to form an ISO-TP frame with the following data:

  01 00 00 00 00 f8 7c 7d

The “Frame Len: 8” in the First Frame tells us there are 8 bytes of data at the ISO-TP protocol layer.

Now, you might say… but hang on, we could send 8 bytes of data with just CAN frames. Well, that’s true in this particular example but for more complex examples we can send over 4000 bytes of data in a single ISO-TP packet (using many CAN frames).

One significant departure that MBE seem to make from the ISO-TP standard is that they do not implement flow-control in the protocol. We don’t need to go into that here, but if anyone is trying to talk to an MBE ECU using their own software, then they’ll need to remove any notion of flow control from the ISO-TP layer they use.

Right, so now we’ve used up two layers of the Russian Doll. The CAN layer and the ISO-TP layer. In the third layer (I’ll call it the MBE layer) we see exactly what the ECU and Easimap are really saying to each other.

MBE LAYER

The data we extracted using the ISO-TP dissector has given us the following (same as above):

  01 00 00 00 00 f8 7c 7d

What does that mean to the ECU?

Well, this took a bit of figuring out. We don’t have MBE’s complete rule-book for decoding this layer of the communications. But what we do have is their Easimap software. That helps us in two ways. Firstly, we can watch Easimap and the ECU talking to each other. That’s how we got these sample packets. But that just looks like random data at the moment. Secondly, we have the EC2 data files that Easimap loads when it discovers what ECU its talking to. MBE supports a whole raft of ECU’s and each seems to communicate with Easimap in a different way. MBE could have coded each of those protocols into Easimap but that would mean that they needed to update the Easimap software whenever they make a new ECU for a customer (Caterham or whoever).

So, MBE wrote Easimap to discover what ECU its talking to and then load the correct EC2 file for that ECU. Fortunately for us the EC2 files are easily found in the Easimap installation.

A DIGRESSION INTO EC2 FILES

The EC2 files are worth a whole post in themselves. And we had to write scripts to decode them and give us the keys to unlock the MBE layer.

In simple terms though, the EC2 files set up a lot of “variables”. Each variable is a type of data that Easimap can extract from the ECU. The 9A4 EC2 file that Easimap uses for our cars has over 2000 variables defined. It turns out that over half of them are “disabled” but that still leaves over 900 to work with. I suspect that many of these 900 don’t actually do anything with our cars but I’m planning to go and check which are “active” and which are not.

For each variable in the EC2 file there are definitions for things like, the number of bytes of data each variable takes up in the MBE communications layer, the short and long description of the variable that Easimap uses when showing the data on the screen and crucially it also has entries for what it calls a “page” and an “address”.

This information for each variable is spread all over the EC2 file and the scripts we wrote had to find each variable and pull the respective information together to build a picture of how each variable works.

{'address': '0x237c',
 'bytes': '2',
 'display_interval': '1000.000000',
 'display_maximum': '12000.000000',
 'display_minimum': '0.000000',
 'long_desc': ' Engine Speed in rpm as measured by the crankshaft sensor. This '
              'is the primary input for the fuel and ignition maps',
 'name': 'RT_ENGINESPEED',
 'page': '0xf8',
 'scale_maximum': '65535.000000',
 'scale_minimum': '0.000000',
 'short_desc': ' Engine Speed',
 'units': 'RPM'}

[ You can read the info as address=237c etc. ]

Once we’d decoded the EC2 file we could start to try and guess on the protocol used in this MBE layer.

BACK TO THE MBE LAYER

I picked all this example data and info for a reason. I had suspected ever since looking at the EC2 files for the first time a few weeks ago that the page and address info was important. And I had one of those Eureka moments when I looked at the output of the ISO-TP layer and realized from:

  01 00 00 00 00 f8 7c 7d

The f8 looked like a page from the EC2 file (see ‘page’ : ‘0xf8’ above) and the 7c looked like part of the address. So, I went away and hand decoded a bunch of messages from the ECU and low and behold it seemed to match up. So page=f8 and address Low-Byte (the 7c bit of the address) meant RT_ENGINESPEED – the engine RPMs.

The next thing was to figure out what the rest of the packet means.

And so I wrote a bunch more code and started to test out my theories.

After the [01 00 00 00 00 f8 7c 7d] message is sent by Easimap, the ECU responds with:

  0x81 0x34 0x12

One of the ways that we saw both OBD-II and ISO-TP communicate was to send a “command” or “service request” in the first couple of bytes of the packet/frame. And for the response to have a similar format but with one or more other bits in the response byte being set.

So, it seemed to make sense that the initial 0x01 byte in the frame from Easimap was responded to by the ECU with a response byte of 0x81 (0x81 in hexadecimal is 0x01 with the top bit set). This was starting to add up and so the request [01 …. 7d] was a data request for RT_ENGINESPEED and the ECU responded with 0x3412 (after the 81).

Now I’ve connived to make the data here readable. When I was first testing I didn’t have the car running and so the ECU was responding with 81 00 00… meaning 0 RPM. But when I started up the car the responses turned into real engine rev data.

Turns out that the [0x3412] is sent in reverse order and the bytes need to be swapped, making the engine revs 0x1234, which in decimal are 4660. That’s revving the car a little highly in a test, but you can see how the data works.

ADDRESSES ARE WEIRD

One of the complications around access to the ECU seems to be some weird mapping going on between the EC2 file and the address requests going to the ECU. For instance, if we take our RT_ENGINESPEED variable then the EC2 address is 0x237c.

But what Easimap sends to the ECU is a request for two bytes, a Lowest Significant Byte (LSB) and a Most Significant Byte (MSB) or 0x7c and 0x7d in our RT_ENGINESPEED example.

Having tried this out with a few dozen different variables it seems that Easimap takes the LSB of the Easimap address (0x7c in this example) and increments (adds one) for each extra byte it wants from the ECU. 

Easimap sometimes asks for 4-byte data and so this incrementing can be seen here, for example, with RT_ENGINERUNTIME…

This is the variable info for RT_ENGINERUNTIME:

{'address': '0xcfcecdcc',
 'bytes': '4',
 'display_interval': '10000.000000',
 'display_maximum': '1193046.500000',
 'display_minimum': '0.000000',
 'long_desc': ' Engine Run Time',
 'name': 'RT_ENGINERUNTIME',
 'page': '0xe2',
 'scale_maximum': '1250999.875000',
 'scale_minimum': '0.000000',
 'short_desc': ' ERT',
 'units': 'Hours'}
RT_ENGINERUNTIME=3.9094e+04 Hours ( ERT ) [0x07ffffff=134217727, Scale:1250999.875, Div:4294967295, Offset:0.0]

But that’s a bit weird too, because the EC2 address (‘0xcfcecdcc’) is the actual series of requests sent to the ECU. I’m a little baffled at the moment about when Easimap uses the EC2 address and when it makes one up. I suspect there are rules depending on how many bytes are being asked for. But obviously the sharp whitted amongst you will have realised that 0xcfcecdcc is in the correct LSB, LSB+1, LSB+2, LSB+3 order. But I’m still not sure when I have to believe in what the EC2 file has for the address and when I have to calculate it myself… I default to doing it myself and that seems to work.

COMPOUND DATA REQUESTS

Lets talk about another twist to the tale. In order that Easimap can talk to the ECU in an as-efficient way as possible. It batches up requests to pages inside the ECU and asks for a bunch of data results in one go. A request and response will therefore look like this at the CAN layer:

46 0.353164720 CAN 32 XTD: 0x0cbe1101   10 23 01 00 00 00 00 f8
47 0.353978868 CAN 32 XTD: 0x0cbe1101   21 30 31 36 37 44 45 4c
48 0.354710862 CAN 32 XTD: 0x0cbe1101   22 4d 4e 4f 50 51 5a 5b
49 0.355482989 CAN 32 XTD: 0x0cbe1101   23 5c 5d 64 6a 6b 7c 7d
50 0.356219206 CAN 32 XTD: 0x0cbe1101   24 9e 9f a0 a1 d8 d9 da
51 0.356950718 CAN 32 XTD: 0x0cbe1101   25 db 9f a0 a1 d8 d9 da
52 0.358137040 CAN 32 XTD: 0x0cbe0111   10 1e 81 4e 39 c7 47 e0
53 0.358462988 CAN 32 XTD: 0x0cbe0111   21 54 d4 83 3a 85 4e 39
54 0.358805252 CAN 32 XTD: 0x0cbe0111   22 a8 0d a2 a0 00 b0 4f
55 0.359140831 CAN 32 XTD: 0x0cbe0111   23 00 00 7a 9c 68 08 00
56 0.359467705 CAN 32 XTD: 0x0cbe0111   24 80 00 80 a1 d8 d9 da


Which then looks like this at the ISO-15765 layer:

46 0.3531647 ISO15765 First Frame(Frame Len: 35) 01 00 00 00 00 f8
47 0.3539788 ISO15765 Consecutive Frame(Seq: 1)  30 31 36 37 44 45 4c
48 0.3547108 ISO15765 Consecutive Frame(Seq: 2)  4d 4e 4f 50 51 5a 5b
49 0.3554829 ISO15765 Consecutive Frame(Seq: 3)  5c 5d 64 6a 6b 7c 7d
50 0.3562192 ISO15765 Consecutive Frame(Seq: 4)  9e 9f a0 a1 d8 d9 da
51 0.3569507 ISO15765 Consecutive Frame(Seq: 5)  db 9f a0 a1 d8 d9 da
52 0.3581370 ISO15765 First Frame(Frame Len: 30) 81 4e 39 c7 47 e0
53 0.3584629 ISO15765 Consecutive Frame(Seq: 1)  54 d4 83 3a 85 4e 39
54 0.3588052 ISO15765 Consecutive Frame(Seq: 2)  a8 0d a2 a0 00 b0 4f
55 0.3591408 ISO15765 Consecutive Frame(Seq: 3)  00 00 7a 9c 68 08 00
56 0.3594677 ISO15765 Consecutive Frame(Seq: 4)  80 00 80 a1 d8 d9 da

Which is a request like this at the MBE layer:

01 00 00 00 00 f8 30 31 36 37 44 45 4c 4d 4e 4f 50 51 5a 5b 5c 5d 64 6a 6b 7c 7d 9e 9f a0 a1 d8 d9 da db

Followed by a response of this:

81 4e 39 c7 47 e0 54 d4 83 3a 85 4e 39 a8 0d a2 a0 00 b0 4f 00 00 7a 9c 68 08 00 80 00 80

Or once the MBE layer is decoded it’s a request for:

This is a command request for data in page: f8 ...
[{'bytes': '2', 'name': 'RT_THROTTLEANGLE1(RAW)'},
 {'bytes': '2', 'name': 'RT_AIRTEMP1(LIM)'},
 {'bytes': '2', 'name': 'RT_COOLANTTEMP1(LIM)'},
 {'bytes': '2', 'name': 'RT_COOLANTFUELFACTOR'},
 {'bytes': '2', 'name': 'RT_AIRTEMPFUELFACTOR'},
 {'bytes': '2', 'name': 'RT_THROTTLEANGLEINCREASING'},
 {'bytes': '2', 'name': 'RT_TPSFUEL+TRIMBANK1'},
 {'bytes': '2', 'name': 'RT_TPSVSSPEEDIGN+TRIM1'},
 {'bytes': '1', 'name': 'RT_THROTTLESITE1'},
 {'bytes': '2', 'name': 'RT_BAROSCALEDLIM'},
 {'bytes': '2', 'name': 'RT_ENGINESPEED'},
 {'bytes': '2', 'name': 'RT_BATTERYVOLTAGE(LIM)'},
 {'bytes': '2', 'name': 'RT_BATTERYVOLTAGECOMP'},
 {'bytes': '2', 'name': 'RT_MAPPINGPOT1LIM'},
 {'bytes': '2', 'name': 'RT_MAPPINGPOT2LIM'}]

and a response with these values:

RT_THROTTLEANGLE1(RAW)=1.1192 V ( Throttle Angle 1 (Raw) ) [0x394e=14670, Scale:5.0, Div:65535, Offset:0.0]
RT_AIRTEMP1(LIM)=14.862  ( Air Temp ) [0x47c7=18375, Scale:160.0, Div:65535, Offset:-30.0]
RT_COOLANTTEMP1(LIM)=23.048  ( Coolant Temp ) [0x54e0=21728, Scale:160.0, Div:65535, Offset:-30.0]
RT_COOLANTFUELFACTOR=105.98  ( Coolant Fuel Factor ) [0x83d4=33748, Scale:400.0, Div:65535, Offset:-1e+02]
RT_AIRTEMPFUELFACTOR=4.0848  ( Air Temp Fuel Factor ) [0x853a=34106, Scale:200.0, Div:65535, Offset:-1e+02]
RT_THROTTLEANGLEINCREASING=1.1192 V ( Throttle Angle Increasing ) [0x394e=14670, Scale:5.0, Div:65535, Offset:0.0]
RT_TPSFUEL+TRIMBANK1=5.6013 ms ( TPS Fuel + Trim ) [0x0da8=3496, Scale:105.0, Div:65535, Offset:0.0]
RT_TPSVSSPEEDIGN+TRIM1=4.7022  ( TPS vs Speed Ign + Trim ) [0xa0a2=41122, Scale:-120.0, Div:65535, Offset:80.0]
RT_THROTTLESITE1=0.0 Site ( Throttle Site 1 ) [0x00=0, Scale:16.0, Div:255, Offset:0.0]
RT_BAROSCALEDLIM=1.04 Bar ( Baro Pressure ) [0x4fb0=20400, Scale:6.5535, Div:65535, Offset:-1.0]
RT_ENGINESPEED=0.0 RPM ( Engine Speed ) [0x0000=0, Scale:65535.0, Div:65535, Offset:0.0]
RT_BATTERYVOLTAGE(LIM)=12.225 V ( Battery Voltage ) [0x9c7a=40058, Scale:20.0, Div:65535, Offset:0.0]
RT_BATTERYVOLTAGECOMP=0.43116 ms ( Battery Voltage Comp ) [0x0868=2152, Scale:13.13, Div:65535, Offset:0.0]
RT_MAPPINGPOT1LIM=0.0015259  ( Mapping Pot 1 ) [0x8000=32768, Scale:200.0, Div:65535, Offset:-1e+02]
RT_MAPPINGPOT2LIM=0.0015259  ( Mapping Pot 2 ) [0x8000=32768, Scale:200.0, Div:65535, Offset:-1e+02]

All those results are what you get back from the car after sending one ISO-TP request frame and getting one response frame. That’s way more efficient than either the MBE-Broadcast or OBD-II protocols.

RESULTS

Most of the variables have scale and offset factors that have to be applied, but initial results give the following for the default Easimap screen…

RT_CURRENTFAULTSB=3.2769e+04 - ( Current Faults B ) [0x8001=32769, Scale:65535.0, Div:65535, Offset:0.0]
RT_ENGINE_CONFIG=176.0 - ( Eng Cnfg ) [0xb0=176, Scale:255.0, Div:255, Offset:0.0]
RT_MEMORYCONFIG=64.0 - ( Memory Configuration ) [0x40=64, Scale:255.0, Div:255, Offset:0.0]
RT_IGNITIONADVANCEBANK1=23.691  ( Ignition Advance ) [0x7820=30752, Scale:-120.0, Div:65535, Offset:80.0]
RT_BAROFUELCOMP=3.5294  ( Barometric Pressure Fuel Compensation ) [0x84=132, Scale:200.0, Div:255, Offset:-1e+02]
RT_CRANKCOUNT=463.0 - ( Crank Count ) [0x01cf=463, Scale:65535.0, Div:65535, Offset:0.0]
RT_ENGINERUNTIME=3.9094e+04 Hours ( ERT ) [0x07ffffff=134217727, Scale:1250999.875, Div:4294967295, Offset:0.0]
RT_THROTTLEANGLE1(RAW)=1.5767 V ( Throttle Angle 1 (Raw) ) [0x50ba=20666, Scale:5.0, Div:65535, Offset:0.0]
RT_AIRTEMP1(LIM)=14.615  ( Air Temp ) [0x4762=18274, Scale:160.0, Div:65535, Offset:-30.0]
RT_COOLANTTEMP1(LIM)=23.121  ( Coolant Temp ) [0x54fe=21758, Scale:160.0, Div:65535, Offset:-30.0]
RT_COOLANTFUELFACTOR=22.719  ( Coolant Fuel Factor ) [0x4e8a=20106, Scale:400.0, Div:65535, Offset:-1e+02]
RT_AIRTEMPFUELFACTOR=4.0848  ( Air Temp Fuel Factor ) [0x853a=34106, Scale:200.0, Div:65535, Offset:-1e+02]
RT_THROTTLEANGLEINCREASING=1.5767 V ( Throttle Angle Increasing ) [0x50ba=20666, Scale:5.0, Div:65535, Offset:0.0]
RT_TPSFUEL+TRIMBANK1=4.5887 ms ( TPS Fuel + Trim ) [0x0b30=2864, Scale:105.0, Div:65535, Offset:0.0]
RT_TPSVSSPEEDIGN+TRIM1=24.32  ( TPS vs Speed Ign + Trim ) [0x76c8=30408, Scale:-120.0, Div:65535, Offset:80.0]
RT_THROTTLESITE1=8.2824 Site ( Throttle Site 1 ) [0x84=132, Scale:16.0, Div:255, Offset:0.0]
RT_BAROSCALEDLIM=1.04 Bar ( Baro Pressure ) [0x4fb0=20400, Scale:6.5535, Div:65535, Offset:-1.0]
RT_ENGINESPEED=2400.0 RPM ( Engine Speed ) [0x0960=2400, Scale:65535.0, Div:65535, Offset:0.0]
RT_BATTERYVOLTAGE(LIM)=13.087 V ( Battery Voltage ) [0xa782=42882, Scale:20.0, Div:65535, Offset:0.0]
RT_BATTERYVOLTAGECOMP=0.33138 ms ( Battery Voltage Comp ) [0x0676=1654, Scale:13.13, Div:65535, Offset:0.0]
RT_MAPPINGPOT1LIM=0.0015259  ( Mapping Pot 1 ) [0x8000=32768, Scale:200.0, Div:65535, Offset:-1e+02]
RT_MAPPINGPOT2LIM=0.0015259  ( Mapping Pot 2 ) [0x8000=32768, Scale:200.0, Div:65535, Offset:-1e+02]
RT_SOFTCUTTIME=7800.0 RPM ( Soft Cut ) [0x1e78=7800, Scale:65535.0, Div:65535, Offset:0.0]
RT_HARDCUTTIME=7900.0 RPM ( Hard Cut ) [0x1edc=7900, Scale:65535.0, Div:65535, Offset:0.0]
RT_INJECTIONTIMEA=7.2051 ms ( Final Injection Time ) [0x1191=4497, Scale:105.0, Div:65535, Offset:0.0]
RT_DUTYCYCLEA=14.51  ( Duty Cycle ) [0x25=37, Scale:100.0, Div:255, Offset:0.0]
RT_HAVESPEEDS=169.0 - ( RT_HAVESPEEDS ) [0x00a9=169, Scale:65535.0, Div:65535, Offset:0.0]

What I don’t know

This whole discussion has unfortunately only been about a small part of what Easimap can do when talking to an MBE ECU. I’ve concentrated on the sensor data that can be extracted from the car. These data values/variables in the EC2 file all start with “RT_”, and I guess that stands for “real time” or something similar. 

There’s a whole bunch of data around the 1D, 2D and 3D maps that Easimap can in theory extract and write to the car. However, with a locked ECU I’m not sure how much of this I’ll be able to get access to. So for the moment I’m concentrating on the RT_ stuff and will come back to the rest at a later date.

That’s the MBE-ISOTP protocol. Now how do we make some use of it…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.