Of ECU's and Electronics

Welcome to DiscoTd5.com, a site dedicated to the Land Rover Td5 Engine. The DiscoTd5.com website springs from the interests and experiences of my ownership of a Td5 Discovery which I purchased in May 2011. Since I first set up the site, my interests have become heavily focused on reverse engineering the Td5 ECU firmware, and I'd expect this focus to remain for the foreseeable future.

To thank site donors for their ongoing support, I've decided to give donor account holders "early access" privileges for new tuning and map related content. The content will eventually appear on the site, but there will be delay of around three months. You'll need to be logged in with a donor account to see this "early access" material.

On Td5 map tables

Tuesday, April 23, 2019 - 08:45

How map tables work…

It’s not entirely obvious how the individual tables are used in the Td5 ECU, and I don’t think I’ve explained this anywhere else.

The Basics

All tables are looked up using linear interpolation. This is done by searching along an axis to find the values on each side of the target value.

If the target value is lower than the minimum or higher than the maximum the nearest “edge” is used.

Using a EU3 torque limiter table as an example this would mean an engine speed value of 500 rpm (which would only occur when cranking) would be clamped to the 600 rpm column, while a value of 5500 rpm (possible but unlikely) would be clamped to the 5000 rpm column.

EU3 Torque Limiter

If the target value was within the bounds of the table, say 2400 rpm, the value would determined by finding the axis values immediately above and below - 2200 rpm and 2500 rpm.

The interpolation between column values is done by finding the fraction of the difference between the column values at which the target value falls.

$$\frac{2400 - 2200}{2500 - 2200} = \frac{200}{300} = 0.66666$$

Then the difference between the table value for 2200rpm and 2500rpm is multiplied by the fraction to determine the value off the fraction.

$$(44.25 - 42.53)0.6666 = 1.15$$

And finally the lower column value is added to the fractional value to give the limter value at 2400rpm.

$$42.53 + 1.15 = 43.68$$

Essentially the method assumes there is a straight line (hence the linear) joining the points represented by the x-axis and table values.

Higher Dimensions

The same basic principles are applied to 2 and 3 dimensional tables. With 2 dimensional tables the ECU interpolates on both the x and y axis, with the column and row values representing the four corners of a cell. If you look at the graph view of a 2d table the intersections of grid lines represent cell corners and the flat surfaces that fill the cells are all the possible interpolated values that occur between the corner values.

Two sets of tables are actually 3d tables. These are the fuel temp compensation tables, and the inject duration tables.

With these tables there is a hidden third dimension - rpm in the case of fuel temp, and advance in the case of inject duration.

Using the inject duration table as an example, the ECU first determines which tables are above or below the current advance/retard value in the same was as described above. Then the inject duration interpolated from inject quantity and rpm for the maps on either side of the adv/ret value, and the inject duration values are interpolated to find the fractional duration amount.

duration tables as a cube

In effect the duration table is a cube with inject quantity, rpm and advance/retard as the three axes (please excuse the wonky illustration!). The first and last duration tables are sides of the cube, and the remaining table(s) divides the space between the sides equally.

MSB map switching

Wednesday, April 17, 2019 - 07:00

I was having a look at the MSB diagnostics a couple of days ago and came across the request for switching between maps.
Some MSB ECU's - most often the Auto versions - come with tunes former than one market and the switching function provides a method for selecting the correct tune.

NOSELECT "Tune"

The NOSELECT tune is default on a new spare ECU. The tune provides just enough functionality to start an engine.
The duration maps are 2 x 2 tables that have rows for 0 and 750 rpm, so should allow the engine to idle.

The remaining tunes are full market specific fuel maps.
In this case the ECU is an MSB1011191 and has tunes for European and Japanese Auto D2s.

European Auto Tune

Japanese Auto Tune

With some minor modifications to the .bin this ECU should support at least one additional fuel map.
The NOSELECT "tune" seems to be referenced in several places during startup so possibly needs to be retained as is.

Even so this opens up the possibility of software switching between two or three maps without resorting to additional hardware to perform address line switching hacks.

Data tracing in Tuner Pro...

Tuesday, April 9, 2019 - 08:00

As I posted recently the data logger project has been taking up a lot of my time over the past few months.

The main intention of the logger is to enable faster, configurable data logging which can be saved into either CSV or Tuner Pro XDL formats.

Over the past few weeks I've been doing a bit of work on reverse engineering Tuner Pro's XDL data log format. I got about 95% worked out before I got in touch with Tuner Pro developer Mark Mansur who very kindly pointed out with the parts I'd got wrong and filled in the bits I couldn't figure out.

As a way of developing and testing the ADX writer code on the desktop, I've written a bunch of code that reads in an ADX file and Nanocom log file (from an Nanocom running current firmware) and uses that information to create an XDL log file.

There are some issues like the lack of Throttle % in the EVO logs that makes the convertor less useful than it should be.

As a teaser to show the possibilities ADX logging opens up this screen capture shows TP data tracing a converted Nanocom EVO log.
The MAF airflow calculation is being done in Tuner Pro RT, and a simple monitor setup shows AAP and MAP.

MEMS ain't MEMS

Monday, March 18, 2019 - 18:45

I've been working on a disassembly of a K-Series engine map that runs on an NNN petrol MEMS ECU for last day or so.

While there is a basic level of commonality with the Td5 this is very much restricted to low level drivers and some utility functions, like map lookup and interpolation, basic kline drivers, CANBUS drivers, etc, etc.

It's this type of functionality that accounts for the similar appearance of the ECU fuel maps. The lookup for sensor scaling is pretty much identical, even though the actual processing has significant differences, for example.

Once you move beyond this "housekeeping" code, you are firmly into the realm of engine specifics.

So yes, MEMS are similar up to a point - but this also hides a lot of difference in the actual engine code.

In other words "MEMS ain't MEMS"

Datalogger - the rebooted reboot...

Tuesday, March 12, 2019 - 15:45

While things have been fairly quiet on the site recently, that hasn't really been a reflection of the level of work that has been going on at the DiscoTd5 Lab for last three or four months...

The datalogger had pretty much been dumped in parts bin as the level of work required to get it up to a useful state seemed to be overwhelming. Conversation with an enthusiastic D2 tuner convinced me to take another look - on the basis of build it or bin it for good.

Three months later, and hundreds of hours rewriting the code, it's slowly starting to come together.

The biggest chunk of effort - which has basically eaten the last 4 weeks - has gone into writing a SDCard // FAT32 library from the ground up. This was the obstacle that had resulted in the project being shelved previously so it's been a significant hurdle to overcome. There is still work to do but there is now light at the end of the tunnel.

It might seem a bit bizarre to be writing a FAT32 library from scratch when there are well established products like the ELM Chan FATFs available.
The main issue has been that the logger code is written in a way that requires components to be non-blocking. Blocking code will prevent any other code running while the blocking waits in a loop for something to happen - it literally blocks progress.
ELM Chan's FATFs is blocking in that it waits for SDCards to come out of busy state before proceeding. The issue here is that at times cards can be busy for extended periods - 50ms is not unusual even with a good quality card like a SanDisk Ultra. With poor quality cards wait times of 200ms+ are not uncommon.

Where this becomes a problem for a Td5 data logger is that the default time between an ECU response and the next "tester" request is 25ms.
The Nanocom Evo solves the problem by making a series of requests - one log line of data - then writing that line to file. There is a 600ms+ pause between the end of one block of data, and the start of the next which is plenty of time for even the slowest junk SDCard to finish writing and return to idle state. But this also means that the Nanocom is writing one line of log data every 1.25 seconds. Fine for some purposes but a lot of dynamic behavior "falls through the cracks" - the torque reduction of an auto shift completes in under 300ms for example, so is effectively invisible.

The approach I'm taking here is to use non-blocking code with DMA (direct memory access) transfers of data to the card. The DMA transfers effectively run in the background without processor intervention, so the combination means that the processor only needs to setup the write to the SDCard, and then can resume more important tasks like reading data from the ECU, or other sensors. The issue of wait times is dealt with by buffering the data waiting to be written to card. In theory all this will allow data rates 10-15 times faster than the Nanocom to be written to card without delays caused by slow card writes.

An excuse for new toys

One of the issues I'd have was that my old Saleae Logic - an original and now much cloned 8 channel 24Mhz job - is starting to show it's limitations when trying to capture communication with the SDCard at 20Mhz bus speed. To capture a signal you need at least twice the frequency of the signal - so 40Mhz at least - ideally you oversample at x4 so 80Mhz. With the old Logic I was flying blind.
As much as I love the Saleae and the software, a new Logic 8 Pro which has sufficient speed for this task was prohibitively expensive - 700-800USD.

So I've ended up with an open source design analyser that does either buffered or streaming captures. The buffered captures are made to internal memory, and have fairly limited length of capture. around 1 second @100MHz using 4 channels, and 300ms @ 400Mhz using 4 channels. Streaming captures are sent over usb to an open source, cross platform application based on Sigrok. The buffered captures are limited to 100Mhz with 3 channels, or 50MHz when using 6 channels. For the SDCard work I need 4 channels and long captures so need to use the 50MHz/6 Channel option. So not perfect but it's flexible enough to be quite useful. Best thing was that it's far more affordable at $150USD.

DSLogic Plus vs Saleae Logic original
The Logic is the small black square on the left, the DSLogic Plus on the right is significantly bigger but still fairly compact.

And the DSLogic proved it's worth within an 30 minutes of unboxing. I'd had an issue where the code would run perfectly with the Saleae connected but would then fail as soon as I disconnected.
It's a real catch22 - the bug occurs only when your debugging gear isn't connected... makes troubleshooting fun. The DSLogic has coaxial probe leads which significantly reduce the effect on the signal being monitored compared with the Saleae's flying leads. There is a great comparison of a Saleae clone and DSLogic on the OpenTechLab channel on YouTube - the sims of the effect of flying leads is quite an eye opener.

The video above mentions the probe clip quality. The ones that came with mine seem to be cheap knock-offs of ez-hooks. Not quite as clunky as those seen in the video, but hook wire is pretty flimsy compared with ez-hooks.

The upshot was that even with the DSLogic connected the "undebugable" bug was occurring every time a card was inserted, and it was straight forward to isolate where and why the code was failing.

DSView

The software is fairly good but a bit rough around the edges at least under macOS. I have a bit of trouble with zooming using the trackpad - it's clearly designed for left and right buttons plus scroll wheel. Protocol decoding seems accurate but is slow compared with the Saleae app, although to be fair10 second captures at 20Mhz were regularly bringing that program to the point where a force quit was required, and in one instance a full reboot.

For the money it is pretty decent, and the cross platform software is a big plus in my book.
Worth noting that the DSLogics sold on eBay are not covered by a manufacturers warranty.
I opted to purchase direct.

Donated and didn't get an account?

Tuesday, February 26, 2019 - 11:00

Check your spam folder...

It appears that a couple of webmail services - hotmail.com in particular - are quietly filtering emails from the discotd5.com domain to spam.

Donors will always get a "Thank you for your donation email" from the site within a few minutes of the donation being made, and I try to get donor accounts setup same day, but it can take up to 2-3 days if I'm away, and have limited internet access.

When the account is created an email advise the account has been setup is sent. This contains a one-time login link.

If you have donated and didn't get a "Thank you email", first thing is to check your spam folder.
If 3+ days have passed, and you haven't got an account creation email, first thing to do is check your spam folder.

In particular if you have used a Hotmail account to donate - just check your spam folder for email from @discotd5.com.

EU3 MAF timeout disable

Tuesday, January 8, 2019 - 10:45

I've had a few requests for details on how to disable the timeout on EU3 maps when the MAF sensor is disconnected.
Without this mod the throttle on EU3 maps is unresponsive for 20-30 seconds when the engine is first started.

It's quite simple to do by altering the MAF "out of range" timeout check from a conditional "if timeout branch" to an unconditional "branch".

You'll need to use a HEX editor for this.

First open up you .map file in your favorite hex editor - I use Hex Fiend on macOS for stuff like this.

With the .map open search for a sequence of hex bytes: 66 30 31

Unmodified .map

There should be only one occurrence of this sequence in the .map file at an offset of somewhere around 0xD100 - 0xD400.

Next, change the 66 to 60 - this alters the conditional branch instruction to an unconditional branch, meaning the ECU always executes the "no MAF" code.

Modifed .map file

Save the modified .map file and you are done.

Be aware that this mod “lobotomizes" the EU3 maps to a EU2 style single smoke map configuration.
The ECU will only use the main high range smoke map (map 60).

This should work for all EU3 variants.
If you can't locate the byte sequence let me know which variant you are working with.

Note: The checksum needs to be updated if you are loading the .map using the Nanocom. This can be done by loading the .map file into Tuner Pro with the appropriate XDF and then saving the "bin". The checksum is updated on save. Td5 Map Editor will also update the checksum. If you are using Td5 ME you'll have to either make and the reverse a change to the map so the file is marked as "dirty" then save, or "save as". Thanks to Neil for mentioning this omission.

File under Nanocom Bugs

Monday, December 24, 2018 - 11:00

Is Front Left the new Right Rear?

Getting id of sensor values correct is just so last season...

I've had the 4 amigo's hanging about for a while and finally decided I better fit the replacement sensor that has been kicking around for the last month or two this morning.

Fault codes have been showing an intermittent fault in the right rear sensor.
Usual problem is knowing whether that is right facing the front of the vehicle or right facing the rear.
I'd been assuming right facing the front, but thought I'd double check before replacing.

Logical thing to do is pull the sensor connector and check the voltages with the Nanocom.

So I disconnect the sensor in the rear right wheel arch.
All good - unplugging the sensor is mechanical so Nanocom can't screw this up for us!!

Then check the sensor voltages...

Something doesn't look quite right!

Cyprus, We have a problem..

Fortunately the fault codes are correct, and a quick drive revealed a rear right electrical failure.

XDF progress update

Monday, November 5, 2018 - 11:30

Current Status

I'm currently working on new method for generating XDF's which is providing a chance to streamline the process.

One issue that has been bothering me is that significant portion of the NNN XDF's are redundant. This occurs because the XDF's are currently created based on the variant-fuel map pairs in each .map file.

The reality is that the only difference between the fuel maps in for example swdxe007-swtnp004.map and swdxe007-swtnp006.map is the number of the variant map in the fuel map. The fuel map checksum also changes by the difference between the variant map version numbers.

Neither of these differences have any impact on how the XDF defines the tables and constants within the fuel .map. A small number of NNN EU2 maps have additional differences in 5-6 constant values but again the structure of the fuel map is the same, so one XDF definition can edit both versions.

So the upshot is that the next release of the XDF's will be based on the fuel map identifier only, and this will reduce the number of NNN XDF by about 30-40%.

XDF auto loading

Tuner Pro has the ability to auto load XDF's when a .bin / .map is loaded. Unfortunately this must be manually configured but it saves a bit of messing around once it's configured. It's usable with current versions of the XDFs but will make more sense when the XDFs are consolidated.

The auto loading is configured under Tools > Preferences > Default XDFs by selecting enable default definitions.

XDF auto load

These are the offsets for the current NNN XDFs.

Map Offset ID Byte
svlne004-svtnp003 0x1cfe6 0x8f
swdxe007-swtnp004 0x1cfe6 0x9b
swdxr004-swtnp004 0x1cfe6 0xdf
swdxr004-swtnp006 0x1cfe6 0xdf
swdxe007-swtnp006 0x1cfe6 0x9b
sthdr009-sttdp009 0x1ba26 0x3d
suhde036-sutdp014 0x1ba26 0x44
swdxr002-swtnp004 0x1cfe6 0xb8
svdxe008-svtnp006 0x1cfe6 0x30
suhdr009-sutzp005 0x1ba26 0x3f
svdxe008-svtnp005 0x1cfe6 0x30
suhde036-sutdp012 0x1ba26 0x44
suhdr009-sutzp004 0x1ba26 0x3f
svloe005-svtnp005 0x1cfe6 0xca
svloj002-svtnp006 0x1cfe6 0xbd
svdxe004-svtnp003 0x1cfe6 0xe6
svloe004-svtnp003 0x1cfe6 0xd1
svdxe003-svtnp003 0x1cfe6 0xad
sthle022-sttlp010 0x1b98e 0xee
swdxk001-swtnp004 0x1cfe6 0x33
svloe005-svtnp006 0x1cfe6 0xca
svdxr007-svtnp005 0x1cfe6 0x51
sthde021-sttdp010 0x1ba26 0xa1
svloe002-svtnp003 0x1cfe6 0x8b
svdxr007-svtnp006 0x1cfe6 0x51
svloj002-svtnp003 0x1cfe6 0xbd
svlor005-svtnp005 0x1cfe6 0x9
svlor004-svtnp003 0x1cfe6 0xf
sthde021-sttdp009 0x1ba26 0xa2
svlor002-svtnp003 0x1cfe6 0x10
svdxr005-svtnp003 0x1cfe6 0x4d
svdxr002-svtnp003 0x1cfe6 0x4e
swdxk003-swtnp006 0x1cfe6 0x86
svdxe006-svtnp003 0x1cfe6 0x2c
sthle022-sttlp009 0x1b98e 0xef
svdxg003-svtnp006 0x1cfe6 0x7b
swdxk003-swtnp004 0x1cfe6 0x86
surdk004-sutzp004 0x1ba26 0x3b
svlnr004-svtnp003 0x1cfe6 0x16
svlnr005-svtnp005 0x1cfe6 0xff
swdxe004-swtnp004 0x1cfe6 0x5a
surdk004-sutzp005 0x1ba26 0x3b
svlnr005-svtnp006 0x1cfe6 0xff
svlne006-svtnp003 0x1cfe6 0xd5
sthdr009-sttdp010 0x1ba26 0x3c
svlne007-svtnp005 0x1cfe6 0xbb
svlnr002-svtnp003 0x1cfe6 0x18
svlne007-svtnp006 0x1cfe6 0xbb

Pages

randomness