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.

Serial communication methods by ECU
MEMS 1.3 and 1.6
Connect at 9600 Baud rate, 8 bits, 1 stop bit, NO parity
"Normal" serial communication - ECU has a TX and RX pin, plus a signal ground

MEMS 1.9
ISO 9141 5-baud wake up with ECU address 0x16, then invert second byte in ECU reply
Connect at 9600 Baud rate, 8 bits, 1 stop bit, NO parity
K-line communication over a single wire
You literally get your own transmissions as echos on K-line

MEMS 2J
5-baud wake up
Connect at 10400 Baud rate, 8 bits, 1 stop bit, NO parity
K-line communication over a single wire
You literally get your own transmissions as echos on K-line
Optional 9600 baud mode for "factory" functions (work in progress)

MEMS 3
No wake up needed for 9600 baud
Optional 10400 baud
Connect at 9600 Baud rate, 8 bits, 1 stop bit, EVEN parity
K-line communication over a single wire
You literally get your own transmissions as echos on K-line


Talking to the ECU
MEMS 1.3, 1.6, 1.9
Send single bytes (commands) at a time, ECU echos your command back to you, and will respond with more data if it is an acceptable command

MEMS 2J
Always send data with a data length byte (data length only) prepended, and a SUM checksum byte appended
The checksum is a SUM of all data bytes and the length byte, then cropped to 1 byte in case it has spilled over 255 (AND it with 0xFF)
Partial/early UDS

MEMS 3
Always start data packets with header 0xB8, 0x13, 0xF7 (format, destination, source)
Reply packets will always start with header 0x13, 0xB8, 0xF7 (format, destination, source)
After the header, add a length byte (data length only), followed by the data, followed by a XOR checksum
The checksum is a XOR of all bytes apart from the checksum byte itself, cropped to 1 byte (AND it with 0xFF)
ECU response checksums are sometimes AND, sometimes XOR
Partial/early UDS


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.9
Send byte 0x16 at 5 baud rate, then swap back to 9600 baud rate treat it like a 1.3/1.6 ECU including doing the 1.3/1.6 init sequence
Most serial cables won't do 5 baud rate so you can use breaks to do this, only some cables allow breaks to be used in this way
5V TTL level must be used or the ECU will not respond

MEMS 2J
Send a 25ms break followed by a 25ms non-break
Then send bytes to the ECU: 0x81, 0x13, 0xF7, 0x81, 0x0C
ECU should reply 0x03, 0xC1, 0xD5, 0x8F, 0x28
Only some cables allow breaks to be used properly
You need to now authenticate with the ECU - see authentication section below

MEMS 3
No "wake up" or init signal is needed, but you do need to authenticate with the ECU - see authentication section below


Authenticating with ECUs
MEMS 1.3, 1.6, 1.9
No auth beyond the init sequence

MEMS 2J, 3
See ISO 14229-1/ISO 14230-3 (KWP)
Seed/key auth
Ask for seed - send 0x27, 0x01
ECU should reply with 0x67, 0x01, [seed byte 1], [seed byte 2]
Compute the key to reply
Send the key - 0x27, 0x02, [key byte 1], [key byte 2]
ECU should accept if correct - 0x67, 0x02

A 0x7F response is a failure


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 fuel trim setting and returns the new value0x7B, [new value]
0x7CDecrements 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?
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