Inside_MNET_01
Inside_MNET_01
by Len Shustek
V1.0, 6 April 2015
V1.1, 12 April 2015
For decades Mitsubishi heating and heating and air conditioning units have been
interconnected with a propriety network called M-NET. The company doesn't publicly
document anything about it: the electrical signals, protocols, packet formats, or command
sequences.
In an attempt to understand our HVAC system, I recreated my experience from 30 years ago as
the designer of the first Sniffer™ at Network General for local area network protocol analysis. I
figured out how the M-NET signaling works, built a Sniffer to record and decode the
communications, and have made good progress on understanding the operation at the
command level.
This is reverse engineering based solely on observations and experiments. I have no access
whatsoever to Mitsubishi proprietary or confidential documents.
I have only examined our system, which consists of two MXZ-4B36NA outdoor heat pumps, four
SEZ-KD18N14 indoor fancoil units attached to MAC-333F-E System Control Interfaces, and a
CoolMaster 4000M that connects the M-NET to the Control4 home automation system.
Clearly they are trying to accomplish two things: (1) avoid common-mode noise by using
differential transmission on the two wires, and (2) avoid voltage build-up by using a bipolar
code of some kind.
The classic bipolar encoding (see https://en.wikipedia.org/wiki/Bipolar_encoding) is alternate
mark inversion, where a binary 0 is encoded as zero volts -- no pulses -- and a binary 1 ("mark")
is encoded alternately as a positive or negative voltage, with the opposite polarity on the return
wire.
The "just longer than 50 microseconds" pulses that are always followed by a rest afterwards
was a hint that they are transmitting serially at the traditional 9600 baud, which has a bit time
of 104 microseconds. So each non-zero bit cell starts with a half-baud pulse of 52 microseconds.
If it were traditional serial communication, it would have to begin with a "start" bit, which is a
"space", not a "mark". So this variation of bipolar coding must be alternate space inversion. And
since RS232 serial communication traditionally uses "space" as a 0-bit and "mark" as a 1-bit, the
alternating "space" pulses probably represent 0s within the data, and the 1s are the quiet
times.
The was confirmed by manually writing down long strings of the pulses from the oscilloscope
screen and noticing the following pattern on a 104 microsecond timeline: a start (space) pulse,
followed by 8 data bits with a pulse representing 0 and no pulse representing 1, followed by an
even parity bit, and then a single stop (mark) bit. It is a variation of standard serial
communication!
The logical next step in building a Sniffer was to design a circuit that converts this bipolar signal
into RS232 serial communications. All it takes is four op-amps for differential decoding and
level conversion, and a monostable timer that produces 104-microsecond baud levels from the
52-microsecond pulses.
Using a terminal emulator, I began to examine the communications I saw on our M-NET, now
decoded into a series of bytes. Unfortunately the traffic doesn't use characters encoded as
either ASCII or EBCDIC; it is a binary code.
But it was divided into small packets with 8 to 12 bytes, followed by a rest time. Although I can't
tell electrically who is transmitting, each packet ends with a binary 06, which is the ASCII code
for "ACK", or "acknowledge". So that must be transmitted by the unit receiving the packet.
I reasoned that there must be some "longitudinal" error checking of the packet in addition to
the "vertical" parity on each byte, so I tried interpreting the byte before the ACK as a checksum
using various algorithms. It turns out to be a modulo-256 negative sum of all the preceding
bytes, so that the packet sums to zero.
A typical packet thus looks like this:
BD FB 02 3F 03 35 03 22 AA 06
The checksum AA is the last byte sent by the transmitter, followed by the 06 ACK that the
receiver uses to indicate that the packet was received with a correct checksum.
There must be identification within the packet of the sender and receiver unit numbers. I knew
from the CoolMaster display that our internal fancoil units are numbered from 01 to 04, and I
could see that the 02 in the example packet alternates with the FB in subsequent packets. So
the 02 must be the destination, and the FB the source address – in this case our CoolMaster's
address. The initial byte, which I've only seen as BD or BE, must be the packet type – perhaps
indicating a command vs a response.
There must be an internal encoding of the packet length, and the first 03 in the example packet
above is the count of the remaining data bytes before the checksum. This packet's data payload
is thus 35 03 22.
So the general format of a packet is:
desti- check-
type source flags? length data… ACK
nation sum
The next step was to write a protocol interpreter program to separate and decode the packets.
Gradually, as I did experiments and examined the network traffic that they provoked, I was able
to create decoded displays of the packets. It's a program written in C, and is currently about
500 lines long. I've posted the code (and all the other documentation) as open source at
https://github.com/LenShustek/M-NET-Sniffer.
At this point I've identified the basic format of all the packets I've seen on our system. There are
bits and bytes within the packets whose meaning I don't know, and there are surely other
packet types I haven't yet seen.
Clearly more experiments are needed to expand our knowledge of the packet formats and the
protocol. But the necessary tools are now at hand.