My16M Communication Protocol

The page documents the communications protocol that My16M uses. This is normally hidden by the use of the ECUControl program or the Optimiser. It would be useful for someone who wants to write their own application that talks directly to My16M.

My16M communicates using a serial connection. The supplied RS232 adapter can be plugged straight into a 9 pin COM port on a PC. Communication is simple 3 wire RS232 with no software or hardware handshaking at 38K, 8 bits no parity.

Below is a list is the commands and response packets that My16M uses. All command and responses are alphanumeric and are terminated with a carriage return - '\r' which has a binary value of 13. Multi-byte values are transferred little endian ( low byte first ).

Memory structure transfer

Many of the packets are used to transfer internal ECU structures. These structures are transferred using a common subroutine. A memory structure is transferred in the flowing format.

<prefix>NND0D1...DnXX

where

NN is the number of bytes in the structure in hex
D0..Dn are the memory bytes of the structure
XX is the checksum


For those interested the following routine is used to do transfer the structure

void TxMem_( uint8_t * Buf, int Cnt, char * Str )
{

int i;
uint8_t Chk = 0;
TxStr_P( Str );
Txu8( Cnt );

for ( i = 0; i < Cnt; i++ )
{

int i;
uint8_t byt = Buf[i];
Txu8( byt );
Chk += byt;

}
Txu8( Chk );
TxStr_P(CR);

}

The Str parameter is used to prefix the memory structure for identification.

Continuous Updates

As soon as the ECU is powered up it begins dumping 3 structures continuously. The rate of transfer is RPM dependant but for all intents and purposes it can be consider realtime ( 5 - 10 times per second ).

The 3 structures are

Timing Info

This structure can be used to determine the engine speed, throttle setting and postion within the map, and the resultant engine pulses

typedef struct

{

FullPulse_t SparkOff; // Position of spark pulse trailing edge - the spark

FullPulse_t SparkOn; // Position of spark pulse leading edge - coil charging

uint16_t PulsePeriod; // The time(us) between engine timing pulses

uint16_t InjDuration0; // Pulse duration in us

uint16_t InjDuration1; // Pulse duration in us

FullPulse_t InjAdvance; // Position of injector

uint8_t MapIdx_; // The index of the map entry being used ( lower left )

uint8_t fy; // The fraction throttle from base map entry

uint8_t fx; // The fraction RPM from base map entry

} TimingInfo_t;

This structure is prefixed with a "=1".

FullPulse_t has the form

typedef struct
{
    uint16_t    TimeWait;        // Time in us after the pulse
    uint8_t     Pulse;            // The pulse number - 0..47 for My16M
}   FullPulse_t;

 

Compensation Info

This structure can be used to determine various corrections being applied to the map

typedef struct

{

uint16_t AirPressure;

uint16_t BaroAdjust; // The correction factor calculated from air pressure and temperature 1024 is 100% - no change from map

uint16_t O2Adjust0:12; // The correction factor being applied to the map ( after baro correction )

uint16_t O2Index0:3;

uint16_t ClosedLoopActive0:1;

int16_t O2Target0;

int16_t O2Target1;

uint16_t CylinderOffSet;

uint16_t InjDuration; // Pulse duration in us

uint16_t O2Adjust1:12; // The correction factor being applied to the map ( after baro correction )

uint16_t O2Index1:3;

uint16_t ClosedLoopActive1:1;

uint16_t InjectorVAdjust;

} CompInfo_t;


This structure is prefixed with an "=3".

Analog inputs

This structure provides the raw analog signals as seen be the ECU


This structure is prefixed with an "=0".

Below is older stuff not yet brought up to date

typedef struct
{
    uint16_t    GasSensor;
    uint16_t    OilTemp;
    uint16_t    AirTemp;
    uint16_t    AirPressure;
    uint16_t    Throttle;
    uint16_t    BatteryVolts;
    uint16_t    2ndGasSensor;
} Analogs_t;

Get Map entry into edit buffer - "gXX\r"

This command is sent to My16M to load the map edit buffer with cell XX from the static map if the edit buffer does not already contain that cell. XX is in hexadecimal representation in upper or lower case and can take a value of 00 to 8F (143 decimal). Two hex digits for XX ARE required. The edit buffer takes precedence over the static map for engine operation and can hence be used to modify the engine timing in real-time.

My16M responds with "gXXMssssddddiiii\r" where

XX is an echo of the request parameter
ssss is a 16 bit hexadecimal number for the spark advance. This can be 0x1600 for TDC down to 0x1200 for 64 degrees advance.
dddd is a 16 bit hexadecimal number for the injector duration. This value is in microseconds and can be 0 to 0x0FFF ( approx 16 ms)
iiii is a 16 bit hexadecimal number for the injector advance. Similar to spark advance, it can take values from 0x2800 down to 0x1C00

Set Map Edit buffer "Mssssddddiiii\r"

This command is sent to My16M to set the map edit buffer that has previously been loaded with the "Get Map entry" command. If the engine is operating near the corresponding area of the map this will have immediate effect on the engine. The format is the same as the previous command. There is no response from My16M to this command.

Program Map Edit buffer "x\r"

This command is sent to My16M to program the map edit buffer into the static map cell that was previously select that was loaded with the "g" command. The entry is now permanently stored in My16M. There is no response from My16M to this command.

Set My16M Configuration "cRRRROOTT\r"

This command is sent to My16M to set the configuration.

RRRR sets the red line RPM. The value is a 16 bit hexadecimal number representing the time in microseconds between engine sync pulses.
OO is the target oxygen sensor value for closed loop operation.
TT is the throttle value with the throttle at the idle stop.

There is no response from My16M to this command.

Query the analog inputs "?\r"

This command is sent to My16M to retrieve all the analog inputs. All analog inputs are 10 bit quantities.
The response from My16M is "aAAAABBBBCCCCDDDDEEEE\r" where

AAAA is a 16 bit hexadecimal number representing the oxygen sensor input
BBBB is a 16 bit hexadecimal number representing the oil temperature input
CCCC is a 16 bit hexadecimal number representing the air temperature input
DDDD is a 16 bit hexadecimal number representing the air pressure input
EEEE is a 16 bit hexadecimal number representing the throttle position input

Query the timing information "?1\r"

This command is sent to My16M to retrieve current timing parameters.
The response from My16M is "tSSSSSSPPPPDDDDIIIIIIMMYYXX\r" where

SSSSSS is a 24 bit hexadecimal number representing the spark advance. The first two digits are the engine pulse, the next four digits is the delay in microseconds from the engine sync pulse to the trailing edge of the spark pulse.
PPPP is a 16 bit hexadecimal number representing the average period in microseconds between engine sync pulses
DDDD is a 16 bit hexadecimal number for the injector duration in microseconds
IIIIII is a 24 bit hexadecimal number representing the injector advance. The format is the same as that for spark advance above.
MM is the map cell number the engine is currently operating in.
YY is the throttle position within the current cell. Its a binary fraction 0 -> 255 is 0 -> 1, used for interpolation
XX is the rpm position within the current cell. Its a binary fraction 0 -> 255 is 0 -> 1, used for interpolation

Query the configuration "?2\r"

This command is sent to My16M to retrieve current configuration parameters.
The response from My16M is the same format as the "c" command above

Query the compensation information "?3\r"

This command is sent to My16M to retrieve current barometric and closed loop compensation parameters.
The response from My16M is "iBBBBOOOO\r" where

BBBB is a 16 bit hexadecimal number representing the barometric compensation multiplier that has been calculated from the temperature and pressure inputs. 0x4000 represent the 100% number.
OOOO is a 16 bit hexadecimal number representing the compensation multiplier being applied to the map by the closed loop software in order to achieve the correct mixture. 0x400 is the 100% number.