Technical info

Main portion of the PC application code is here: https://github.com/james-portman/rover-mems-agent/
This may mean absolutely nothing to most people.
I am trying to catalogue information about how to communicate with these ECUs for anyone who wants to know more, or join in with the development work.
There is a lot of very good information out there already but it is all a bit disjointed or only applies to certain ECU versions.

Wake up/initialize ECU
MEMS 1.3 and 1.6
Send bytes 0xCA, 0x75, 0xD0
ECU should reply 0xCA, 0x75, 0xD0, then 4 more bytes which is the ECU ID
5V TTL level must be used or the ECU will not respond


MEMS 1.2, 1.3, 1.6, 1.9 "Data packets"
These ECUs respond to the commands 0x80 and 0x7D with data packets, which have multiple data points in
The (single plug?) 1.2 ECUs do not respond with a 0x7D packet at all
Each version replies with a slightly different amount of data
The first byte of the packet (ignoring the echo/command reply) is the length, so that should be used to wait for the rest of the data packet to be received

Information is a bit vague/mixed but here is the best explanation I can get so far for the data points:

Data packet 0x7D
0x00 Size of data packet, including this byte
0x01 Ignition switch - 0 for off (does comms even work with ignition off?)
0x02 Throttle angle - divide by 2 for degrees throttle open
0x03 Unknown
0x04 Sometimes documented to be air/fuel ratio, but often observed to never change from 0xFF
0x05 DTC byte
   bit 3 - lambda heater (relay)
   bit 4 - crank shaft sync
   bit 5 - fan 1 control
   bit 7 - fan 2 control
0x06 Lambda sensor voltage, 0.5mv per LSB
0x07 Lambda sensor - 0=off, greater=on
0x08 Lambda sensor duty cycle?
0x09 Lambda sensor status? 0x01 for good, any other value for no good
0x0A Loop indicator, 0 for open loop and nonzero for closed loop
0x0B Long term trim? Injector dead time (-1024 to 1016)?
0x0C Fuel correction, 1% per LSB, 100 is normal, could be 100-[this value]?
0x0D Carbon canister purge valve duty cycle?
0x0E DTC
   bit 1 - cam shaft sync
0x0F Idle position - 0 to 255 steps
0x10 Unknown
0x11 DTC
   bit 6 - RPM gauge circuit
0x12 Unknown
0x13 Unknown
0x14 Idle error?
0x15 Unknown
0x16 DTC
   bit 1 - injector 1/4 driver
   bit 2 - injector 2/3 driver
   bit 3 - engine bay ventilator warning light
   bit 4 - engine bay ventilator relay
   bit 5 - hill assist
   bit 6 - cruise control
0x17
0x18
0x19
0x1A
0x1B
0x1C
0x1D
0x1E
0x1F - Crank counter?


Data packet 0x80
0x00 Size of data packet, including this byte
0x01-2 Engine speed in RPM (16 bits)
0x03 Coolant temperature in degrees C with +55 offset and 8-bit wrap
0x04 Computed ambient temperature in degrees C with +55 offset and 8-bit wrap
0x05 Intake air temperature in degrees C with +55 offset and 8-bit wrap
0x06 Fuel rail temperature in degrees C with +55 offset and 8-bit wrap. This is not supported on the Mini SPi, and always appears as 0xFF.
0x07 MAP sensor value in kilopascals
0x08 Battery voltage, 0.1V per LSB (e.g. 0x7B == 12.3V)
0x09 Throttle pot voltage, 0.02V per LSB. WOT should probably be close to 0xFA or 5.0V.
0x0A Idle switch. Bit 4 will be set if the throttle is closed, and it will be clear otherwise.
0x0B Unknown. Probably a bitfield. Observed as 0x24 with engine off, and 0x20 with engine running. A single sample during a fifteen minute test drive showed a value of 0x30.
0x0C Park/neutral switch. Zero is closed, nonzero is open. Air con switch?
0x0D Fault codes. On the Mini SPi, only two bits in this location are checked:
   Bit 0: Coolant temp sensor fault (Code 1)
   Bit 1: Inlet air temp sensor fault (Code 2)
   bit 3: turbo overboosted
   bit 4: ambient temp sensor
   bit 5: fuel rail temp sensor
   bit 6: knock detected
0x0E Fault codes. On the Mini SPi, only two bits in this location are checked:
   bit 0: (coolant?) temperature gauge
   Bit 1: Fuel pump circuit fault (Code 10)
   bit 3: air con clutch
   bit 4: purge valve
   bit 5: map sensor
   bit 6: boost valve
   Bit 7: Throttle pot circuit fault (Code 16)
0x0F Idle setpoint - 0 to 1556 RPM (6.1x this value)
0x10 Idle HotBDPos, steps?
0x11 Unknown
0x12 Idle air control motor position/steps. On the Mini SPi's A-series engine, 0 is closed, and 180 is wide open.
0x13-14 Idle speed deviation (16 bits)
0x15 Ignition Advance offset - 0 to 159.38 degrees
0x16 Ignition advance, 0.5 degrees per LSB with range of -24 deg (0x00) to 103.5 deg (0xFF), -30 to 129.38 degrees?
0x17-18 Coil charge/dwell time, 0.002 milliseconds per LSB (16 bits) - 0 to 130.56 microseconds


MEMS 1.3, 1.6, 1.9 "Commands"
Still being tidied/updated
CommandInfoResponse
Stop/Disable commands (match the Start/enable commands but swap 0/1 at start)
0x00Coolant gauge0x00, 0x00
0x01Fuel pump relay0x01, 0x00
0x02PTC (inlet manifold heater) relay0x02, 0x00
0x03Air Conditioning relay0x03, 0x00
0x04Idle solenoid
0x05ORFCO solenoid
0x06Pulse air valve
0x07EGR valve
0x08Purge valve0x08, 0x00
0x09O2 heater relay0x09, 0x00
0x0AEmissions fail lamp
0x0BWastegate
0x0CFuel used
0x0DFan 1
0x0EFan 2
0x0FVariable valve timing
Start/Enable commands (match the open commands but swap 0/1 at start)
0x10Coolant gauge0x10, 0x00
0x11Fuel pump relay0x11, 0x00
0x12PTC (inlet manifold heater) relay0x12, 0x00
0x13Air Conditioning relay0x13, 0x00
0x14Idle solenoid
0x15ORFCO solenoid
0x16Pulse air valve
0x17EGR valve
0x18Purge valve0x18, 0x00
0x19O2 heater relay0x19, 0x00
0x1AEmissions fail lamp
0x1BWastegate
0x1CFuel used
0x1DFan 1 relay0x1D
0x1EFan 2 relay0x1E
0x1FVariable valve timing
End of Start/Stop grouped commands (there are some more later)
0x20Engine bay temperature warning light off20 00
0x21Cruise control disable relay21 00
0x30Engine bay temperature warning light on30 00
0x31Cruise control disable relay off31 00
0x60Test RPM gauge stop / Exhaust backpressur valve test60 00
0x61Variable intake test61 00
0x63Test RPM gauge63 00
0x64Test Boost gauge64 00
0x65S/W Throt S.W65 00
0x67Fan 3 (engine bay) off67 00
0x6BTest RPM gauge start6B 00
0x6D?6D 00
0x6FFan 3 (engine bay) on6F 00
0x79Increments fuel trim setting and returns the new value0x79, [new value]
0x7ADecrements fuel trim setting and returns the new value0x7A, [new value]
0x7BIncrements second fuel trim setting and returns the new value0x7B, [new value]
0x7CDecrements second fuel trim setting and returns the new value0x7C, [new value]
0x7DRequest data packet 0x7D0x7D, [data packet]
0x7E? Used as part of (auto?) idle adjustment7E 08
0x7F? Used as part of (auto?) ignition adjustment7F 05
0x80Request data frame 80, followed by 28-byte data frame
0x81? Used at end of idle/ignition/clearing (auto?) adjustments0x81, 0x00
0x82?82 09 9E 1D 00 00 60 05 FF FF
0x89Increments idle decay setting and returns the new value0x89, [new value]
0x8ADecrements idle decay setting and returns the new value0x8A, [new value]
0x91Increments idle speed setting and returns the new value0x91, [new value]
0x92Decrements idle speed setting and returns the new value0x92, [new value]
0x93Increments ignition advance offset and returns the new value0x93, [new value]
0x94Decrements ignition advance offset and returns the new value0x94, [new value]
0x9EAlternate first byte of init (different diag mode/security level?)9E
0xC4Swap to diagnostic mode 4 (only from mode 3)C4 xx
0xCAFirst byte of "normal" initCA
0xCB?CB 00
0xCCClear fault codesCC 00
0xCDDebug? Read RAM?CD 01
0xCEAlternate first byte of init (different diag mode/security level?)CE
0xCFAlternate first byte of init (different diag mode/security level?)CF
0xD0ECU/Software IDD0 99 00 03 03
0xD1ECU/Software IDs 1x integer, 1x AsciiD1 41 42 4E 4D 50 30 30 33 99 00 03 03 41 42 4E 4D 50 30 30 33 99 00 03 03 41 42 4E 4D 50 30 30 33 99 00 03 03
e.g. integer: 99 00 03 03
e.g. string/Ascii: 41 42 4E 4D 50 30 30 33 = ABNMP003
0xD2Read security statusD2, followed by 02 01, 00 01, or 01 01
0xD3Recode ECUD3, followed by 02 01, 00 02, or 01 01 (reply needs checking)
0xDATest injector 1 (mems 1.9)DA, 01?
0xDBTest injector 2 (mems 1.9)DB, 01?
0xDEAlternate first byte of init (different diag mode/security level?)DE
0xE0Alternate first byte of init (different diag mode/security level?)E0
0xE5Alternate first byte of init (different diag mode/security level?)E5
0xE7?E7 02
0xE8?E8 05 26 01 00 01
0xE9Clear faults 2nd? needs ignition cycle?
0xEA
0xEB
0xEC
0xED?ED 00
0xEE?EE 00
0xEFActuate fuel injectors? (MPi?)EF 03
0xF0Check current diagnostic modeF0 14 - mode 3 (default), 1E - mode 4, 50 - mode 5 or 6 (you should know which)
0xF1
0xF2Swap to diagnostic mode 6 (only from mode 4)F2 xx
0xF3Swap to diagnostic mode 4 (from mode 5,6)F3 xx
0xF4Swap to diagnostic mode 5 (from mode 3)F4 xx
0xF5Swap to diagnostic mode 3 (from mode 4,5,6)F5 xx
0xF6Disconnect/Reset diagnostic session
0xF7Actuate fuel injector (SPi?)F7 03
0xF8Fire ignition coilF8 02
0xF9Adjust main map? 2 bytes input also?0x00 on success
0xFAClear all adaptations0xFA, 0x00
0xFBRequest current IAC position0xFB [IAC position XX]
0xFC?FC 00
0xFDOpen IAC by one step and report current positionFD, [IAC position]
0xFEClose IAC by one step and report current positionFE, [IAC position]
0xFFRequest current IAC position?


Diag mode 4 commands - factory programming

Some commands will only work if the ECU is in development mode,
for the 2J ECUs this means they need to have additional RAM installed.
The byte/word reads only work in certain locations on stock ECU.
CommandInfoResponse
0x00-0x7FRead a byte/word from RAM/ROM, command is offset (block set by 0xDC command)
0x80-0x9FIncrease value by 1 in selected cal (0x80 == 0x00 offset) (block set by 0xC1,0xC2,0xC3 commands)
0xA0-0xBFDecrease value by 1 in selected cal (0xA0 == 0x00 offset) (block set by 0xC1,0xC2,0xC3 commands)
0xC1Clears the block number for writes (blocks of 0x20 bytes)
0xC2Increase the block number for writes (blocks of 0x20 bytes)
0xC3Decrease the block number for writes (blocks of 0x20 bytes)
0xC5Choose RAM bank 1 for data loads0xC5
0xC6Choose RAM bank 2 for data loads0xC6
0xC7Set cal pointer to normal ROM
0xC8Set cal pointer to RAM bank 1
0xC9Set cal pointer to RAM bank 2
0xD1Write both RAM cal banks to ROM banks
0xD3Write single cal from RAM -> ROM (use C5/C6 to choose bank)
0xD4Write single cal from ROM -> RAM (or ROM -> ROM if bank not set) (use C5/C6 to choose bank)
0xDC, 0x__Sets the block number for reads (blocks of 0x80 bytes)0xDC, 0x__
0xF7Reads out the running calibration in full0xF7, ...full calibration is streamed out
0xF8Write full calibration (only where ECU is in development mode) - follow with full cal data0xF8



Contact: email me
Disclaimer: This website is not associated with Rover in any way. This exists because there is no support for these older cars/ECUs
Privacy: Privacy policy

Built 20240618104505