UGTuner

Work in progress

Dev
blog

What is being built, how it works, and — the part most tuning pages leave out — what has not been proven yet. Nothing here is a product until it says it is.

Written as the work happens · Bench results included, good and bad

24 September 2026 On the bench Not in a release

Flex fuel for ME7.5: fuelling, ignition and cold start

Running E85 on an ME7.5 car usually means picking a blend and tuning for it. Put something different in the tank and the calibration is wrong until someone edits it again. A flex setup reads what is actually in the fuel and adjusts as it goes — which on these ECUs means adding code, not just changing maps.

This is the state of that work. It runs on the bench. It has not run on an engine.

Reading the sensor

A standard GM-style flex sensor sends ethanol content as a frequency and fuel temperature as a pulse width. An ESP32 converts that to a voltage the ECU can read on the downstream oxygen sensor input — an input most tuned cars have already stopped using.

The mapping from that voltage to what the ECU actually sees was measured rather than assumed: a stepped sweep through the whole input range, logged from inside the ECU, giving a straight line with under one count of scatter and no hysteresis. The converter is then calibrated against that, not against a meter reading at the pin.

Fuelling

Ethanol needs roughly half again as much fuel as petrol for the same air. The patch scales the ECU's own fuel constant continuously with ethanol content — 1.00× on pump gas up to 1.49× at E100.

That 1.49 is the real stoichiometric ratio, 14.70 against 9.86. The 1.40 figure often quoted is right for E70, which is what winter pump E85 frequently turns out to be — and not depending on what the pump claims is the entire point of fitting a sensor.

If the sensor fails, the patch holds the last good reading rather than reverting to petrol. Reverting is the common approach and it is backwards: the fuel in the tank does not change composition when a sensor dies, so fuelling for petrol with E85 in the tank runs 33% lean. The filter is asymmetric for the same reason — rising ethanol tracks quickly, falling ethanol lags, so it errs rich in both directions.

Ignition

Ethanol resists knock, so it will take more advance — but how much more is not a constant, it varies across the whole load and rpm range. The approach here is the one GM used on its own flex calibrations: two complete timing tables and a blend between them.

The stock tables stay exactly as they are and become the petrol tables. Two new E85 tables are added, and timing is blended between them by ethanol content along a ramp the tuner sets — typically nothing extra below E20, full advance by E70, since ignition stops changing much past the middle of the range.

The new tables are written as copies of the stock ones, so a freshly patched file behaves identically to an unpatched one at every ethanol content until someone calibrates them on a dyno. Nothing happens by accident.

An earlier version reused the ECU's existing optimum-spark tables instead of adding new ones, which is tempting because it needs no extra space. It was dropped: the torque model reads those tables to work out how much torque the engine is making, so filling them with E85 numbers quietly shifts throttle response, idle control and the torque figure sent to the gearbox. Separate tables leave all of that alone.

Cold start

This is the part everyone warns about, and the old threads all describe the same failure: the engine fires cleanly, then dies the moment the throttle is touched in the first minute.

The cause is not a shortage of fuel. Ethanol barely vaporises when cold, so it needs far more enrichment than the stoichiometric difference — but enrichment that is not cleared again builds up in the intake and drowns the engine on the first throttle opening. So the patch scales both: the enrichment the calibration already has, and the rate at which it decays.

It scales what the factory maps already describe rather than adding new tables, so the temperature shape a tuner has already dialled in is kept, and it switches itself off the moment the ECU enters closed loop — no fighting with the fuel trims.

What the bench says

A fifteen-minute logged sweep across the whole ethanol range, checked against what the code should produce in every cell:

fuel constant tracked ethanol exactly — every plateau matched
base ignition moved −1.5° to +10.5° as ethanol rose
sensor disconnected → fuelling held, timing fell back to the petrol map
no faults, no dropouts, across 3,500 samples

Along the way the bench also caught a bug worth mentioning: the first version stored its state in a byte of RAM that the factory code reads a flag out of. It worked on the bench and would have quietly interfered with something else on a running car. It was found by checking every instruction in the firmware that touches that address, not by testing.

What is not done

  • No engine has run it. Everything above is bench work.
  • Cranking fuel is still stock; the after-start and warm-up phases are the ones handled so far.
  • Boost is untouched — ethanol will usually take more, and that is the next piece.
  • The E85 tables need calibrating on a dyno with knock monitoring. The patch provides the mechanism, not the numbers.

The editor side is already in place: the E85 tables, the blend ramp, the cold-enrichment scaling and the sensor window all live on their own tab, with the ramp's internal constant derived automatically so it cannot be set inconsistently.

23 September 2026 Published

Motronic M5.9 checksums, worked out and given away

Older Motronic ECUs — M5.9 and M3.8, the 1990s VW and Audi stuff — have a checksum layout that has never been properly documented in public. Tools that correct them exist, but nobody says how.

Starting from a controlled experiment rather than guesswork: take a stock file, change a known set of bytes across the calibration, correct it with a known-good tool, and compare. What the difference proves:

the three stored words are not independent — the first is the sum of the other two
the calibration word is a plain byte sum of a fixed range, no clever arithmetic
the code word covers the area below the calibration, and WinOLS never corrects it

That last point matters to anyone patching code rather than editing maps: nothing is fixing that word for you.

The scripts — a verifier and corrector, plus the probe method used to work it out — are on GitHub, with the reasoning written out so it can be checked rather than trusted. One region is still open, and what would settle it is written down there too.

22 September 2026 On the bench Not in a release

Speed density: running ME7.5 without a MAF

The air meter is the limit on a lot of built engines. Past a certain airflow it reads flat, and no amount of rescaling fixes a sensor that has run out of range. The usual answer is to delete it and work out the air from manifold pressure, rpm and temperature instead — speed density.

ME7 makes this awkward, because the manifold pressure the ECU uses is not measured on most of these cars. It is modelled: the ECU runs an internal estimate of manifold pressure, corrected by what the air meter reports. Delete the meter and the correction has nothing to work from.

The approach

Rather than replacing the model, the patch feeds it. A 3-bar pressure sensor goes where the air meter was, and the patch replaces the ECU's own pressure-correction step with one driven by the real sensor — writing the correction, not the pressure itself.

That matters. An early version wrote the pressure directly as well, which double-counted: in simulation the modelled pressure jumped from 500 to 2000 mbar in a single step. Feeding the existing correction path keeps the model's own filtering and limits doing their job.

The sensor's transfer function did not have to be guessed either. The factory calibration already contains the gradient and offset for the 1.8T boost sensor, because the ECU has always known how to read one — so the patch uses Bosch's own numbers rather than a bench calibration of a sensor that is already characterised.

When the sensor fails

A pressure sensor that fails on a speed density car is not a check-engine light, it is an engine that has no idea how much air it is breathing. The patch detects an out-of-range reading and falls back to the ECU's existing throttle-angle-based air estimate — a path that is already in the firmware for exactly this kind of failure, and is being reused rather than reinvented.

Where it stands

patch written, assembled and simulated instruction by instruction
sensor scaling taken from the factory calibration, not bench-fitted
failure path falls back to throttle-angle air, not to nothing
never started an engine

The remaining work is a filter that varies with rpm and load rather than a single constant, a limit for real transients, and the part no bench can do: a first crank. The code that does the work runs on the crank-synchronous task, which does not run at all with the engine stopped — so unlike the flex work, there is no half-measure available here. It either goes in a car or it stays theoretical.

A VR6 port is planned. The structure is the same but every address differs, so it is a separate piece of work rather than a recompile.

20 September 2026 In the VR6 beta

Watching the ECU read a map

Everyone tuning ME7 has had the same argument with a map: you change a cell, drive the same road, and nothing happens. Either the ECU was not using that cell, or it was not using that map at all.

The VR6 build answers it by replaying a log against the binary. The axis channels come off the wire, the breakpoints and cells come out of the file, and the tool works out exactly what the ECU was reading, cell by cell, as the log plays back.

Four corners, not one

Most tools that do this show a single active cell. That is wrong almost all of the time: unless the engine is sitting exactly on a breakpoint, the ECU is interpolating between four cells, and naming one of them leads you straight into the trap — you edit a cell that contributed a fifth of the output and conclude the map does nothing.

So all four corners are shown, with the weight each one carried. There is a single-cell view on top for convenience, and it is labelled the dominant corner rather than the active one, because that is what it is.

Proving it is right

A trace that looks plausible and is wrong is worse than no trace. The check is that the ECU publishes the output of the very maps being traced — base ignition, optimum ignition, target lambda — so the trace can be compared against what the ECU said it did.

replay the log, compare the traced result to the ECU's own output
matching to within the map's own 0.75° quantisation proves the addresses, the axes and the interpolation
a mismatch means a wrong axis, a wrong breakpoint table — or a different map in force

That last case is the useful one. The two base ignition maps differ in 107 of their 192 cells on a stock file, so comparing both traces against what the ECU actually did identifies which map is in force far more reliably than reading the selection logic and hoping.

Dwell, not just position

Playback runs at adjustable speed with a scrub bar, and cells accumulate a dwell shade as the log plays — so a drive leaves a heat map of where the engine actually spent its time. That is usually more useful than any single frame: it shows which cells are worth tuning and which have never been visited.

None of it changes anything in the ECU. It is a host-side tool: the ECU is logged, not modified, and nothing is written to the car.

Next

The obvious companion is editing a map and seeing the effect without a flash cycle each time. That is in progress and not in a build yet — tracing came first because a live editor that writes to the wrong cell is a considerably worse idea than a viewer that reads one.

UGT Performance