From M232 Wiki
Jump to navigation Jump to search


In M2.3.2 LOAD is the injection time in milliseconds to reach lambda 1.
Because rescaling all LOAD on every axis every time you change injectors is an insane amount of work, I took a different approach.
LOAD is stored internally as a 16 bit variable, but the map axes only go up to 255, because they are 8 bit. This does not mean that you will have any issues after going past 255 LOAD. The table lookup will simply read the last column, but because the internal LOAD (that is also reported by the datalogger) is 16 bit and essentially unlimited, all fueling and timing will still be fine. Also do keep in mind that 255 LOAD is roughly 2.7-2.8 bar of boost, and the MPXH6400A starts being insufficient. It is possible to work around this, by rescaling FGAT0 and LOAD, just as it is possible to linearize an 8 bar MAP sensor.


The injection pulsewidth is calculated as follows:
Enrichment calculation works as follows:
What this means is - if the new factor is more than 128, then fuel is enriched. If the new factor is less than 128, fuel is leaned, and if the factor is exactly 128, then nothing happens at all.
The objective is to calibrate the ECU so, that with a hot engine when ENRICHMENT is 128, then lambda = 1. To achieve this:

  • We must pick the correct injector constant (FGAT0)
  • Pick the correct injector deadtime (TVUB)
  • Calibrate the VE so that LOAD is accurate to deliver a lambda = 1 (or 14.7 AFR) mixture when enrichment is 128

You can verify this is the case, when your real AFR matches REQ_AFR. REQ_AFR is nothing other than the sum of all enrichment.

Injector constant FGAT0

The XDF has convenience functions, so you can just edit the value that represents the FPR you are using (3 bar, 3.8 bar, 4 bar), and set injector size in CC.
If you have a FPR with some other pressure, use the 3 bar FPR variant, and multiply the injector size of your injectors in cc additionally by sqrt(YOUR_FPR/3).

Injector latency/deadtime

Injector latency is hopefully provided by the manufacturer. If you have to find it empirically, you can see if it is more or less right, by revving the engine on idle with no load. As RPM rises and load reduces, the AFR_REQ should still match. This assumes a semi-decently calibrated VE map of course.
There is also an injector minimum pulsewidth constant, but 0.5ms should be OK even for huge injectors.

Main fuel enrichment

  • Fuel enrichment P/T - main fuel enrichment map. Target AFR.
  • Fuel enrichment P/T - Race fuel - Map switched fuel map.
  • Fuel enrichment - IATxRPM correction. IAT based correction. Use to enrich at high IAT. This map is also used to compensate for lean conditions due to heat soak when the car has been left for a while, and then restarted with the engine hot and the IAT sensor reading ridiculous numbers. Thus the fueling corrections at 1000 RPM and 45+C IAT.
  • Fuel enrichment - continuous knock. If you have consistent knocking and the total knock correction over all cylinders exceeds a certain number, then the knock/boost chip sends a signal to the I/O extender, which the fuel/ign chip reads, and enriches fuel by the amount in the map. This is used to combat high EGT due to late ignition.

Warmup enrichment

This is done a little bit differently. The formula for the final factor is not <<7 (/128), but <<8 (/256)+128.
The two maps are multiplied between each other, the result is divided by 256 and added to 128. This makes it so, that these maps can only ever be used to add fuel, never to subtract it.
The maps are:

  • Warmup enrichment - Coolant x IAT - temperature based enrichment
  • Warmup enrichment - IDC - RPM by LOAD enrichment

Acceleration enrichment

Working principles

Acceleration enrichment has been rewritten from standard.
The standard enrichment works based on delta MAF, but because the MAP sensor is much slower in reaction than the MAF, the delta MAP enrichment does not really work that well.
So the routine was rewritten to use Delta TPS instead.
The basic principle is that the enrichment event happens on the next injection event after a high TPS delta. If the TPS delta subsides, it tapers off over each injection event, until it is zero. If the TPS delta is still there, it is recalculated again over and over.


  • Load gradient multiplier for wall film - This map is Delta TPS, you can log DTPS to see it. Basically it is an amplification map - the faster and harder you hit the throttle, the more enrichment. The first few values have to be zero, to avoid unnecessary enrichment and jitter. With the values at zero no enrichment is performed.
  • Number of ignition events for wall film enrichment - this is a time component, over how many injections/ignitions the additional enrichment should taper, always use the SD version.
  • Wall film enrichment taper amount per ignition - This gets subtracted per ignition event from the gradient multiplier map.
  • Initial wall film reduction % after ignition events passed - How much to subtract after the ignition events ran out - usually a high enough number to go straight to 0.
  • Wall film enrichment (RPM x LOAD) - RPM x LOAD component of the enrichment amount. Calculated the same way as warmup enrichment, paired with the Coolant x RPM map.
  • Wall film enrichment (Coolant x RPM) - RPM x Coolant component of the enrichment amount. Calculated the same way as warmup enrichment, paired with the RPM x LOAD map.

Overrun cutout

  • Cylinder re-activation start - The RPM where cylinders start to get sequentially phased in.
  • Cylinder re-activation end - The RPM at which RPM all cylinders must be immediately phased in.
  • Cylinder re-activation delta correction - This RPM is added to the fuel resume setpoint. Axis is RPM gradient.

Crank fuel

This is a multiplier for the cranking fuel. Be careful with this, as you can request 25x fuel enrichment here and flood your engine completely if you are not careful. The standard map is pretty good and will work down to -30C.

Closed loop control

Control principles

Fueling is controlled in closed loop by 2 point O2 sensors. The ECU actually differentiates between 5 states:

  • Very rich
  • Rich
  • Stoich
  • Lean
  • Very lean

Based on these states corrective action is applied.
There are short term and long term corrections. They are visible in group 000 in VCDS. Long term trim is disabled in prjmod.
In fast logging, the lambda intervention is visible in AFR_REQ.
Another feature of prjmod is initial delay. If you use a simulated signal, then usually the signal is static during LSU warmup rather than mimicking a real O2 sensor. Thus the ECU algorithm instantly goes into a control mode with the trim running to 25% very quickly. To combat this, after engine startup a roughly 20 second delay has been added before the O2 correction function is allowed to run.
There are a ton of configurable parameters, such as the PI control, all kinds of voltages, trim limits, diagnosis limits and so on, however not much of it is in the xdf because it simply works quite well "as-is".


  • Lambda threshold - this is the maximum load, under which the ECU is allowed to enter closed loop. During initial injector calibration it is a good idea to set this to 0 to prevent any kind of closed loop control.
  • Lambda threshold (cont. knock) - same as above, but with the knock fuel flag set.

Consumption signal

The consumption signal should be corrected whenever the injectors are changed, else you are going to have weird numbers on the consumption display.
There is also a consumption signal multiplier, that multiplies the signal by 2 each time it is incremented.
To recalculate the consumption signal, take the old number, and multiply it by the factor, that your injectors are bigger/smaller than ADU injectors (which are 360cc at 3 BAR and ADU uses a 3.8 BAR FPR).
This should get you in the ball park, but basically you can also eventually just drive and compare actual and reported consumption and then multiply this number by the error you have in %.