Mitsubishi MC
The MC module supports Mitsubishi MC Protocol 1E / 3E / 4E for Ethernet-based PLC access. Default mode is 3E Binary; ASCII, 1E, and 4E are also supported. Current coverage includes X/Y/M bit devices, D/W/R/ZR word devices, and 3E/4E random access.
Install
dotnet add package Zeus.Communications
dotnet add package Zeus.Protocols.Mc
Connect to a Real PLC
await using var app = ZeusHost.Create(builder =>
{
builder.AddTcpClient("plc-link", "192.168.1.10", 5000);
builder.AddMitsubishiMc("plc", "plc-link");
});
await app.StartAsync();
var plc = app.Devices.Get<McDevice>("plc");
var d100 = await plc.ReadDataRegistersAsync(address: 100, points: 2);
var y20 = await plc.ReadOutputRelaysAsync(address: 0x20, points: 8);
await plc.WriteDataRegistersAsync(address: 200, values: [123, 456]);
await plc.WriteOutputRelaysAsync(address: 0x20, values: [true, false, true, false]);
Pass Mc3EOptions when frame type, encoding, network number, PC number, I/O number, station number, or monitoring timer differs from defaults.
builder.AddMitsubishiMc("plc", "plc-link", new Mc3EOptions
{
FrameType = McFrameType.Frame4E,
DataEncoding = McDataEncoding.Ascii,
SerialNumber = 0x0001,
NetworkNumber = 0x00,
PcNumber = 0xFF,
IoNumber = 0x03FF,
StationNumber = 0x00,
MonitoringTimer = 0x0010
});
Common Device APIs
var d = await plc.ReadDataRegistersAsync(100, 4);
await plc.WriteDataRegistersAsync(100, [10, 20, 30, 40]);
var m = await plc.ReadInternalRelaysAsync(100, 8);
await plc.WriteInternalRelaysAsync(100, [true, false, true, false]);
var x = await plc.ReadInputRelaysAsync(0x10, 8);
var y = await plc.ReadOutputRelaysAsync(0x20, 8);
await plc.WriteOutputRelaysAsync(0x20, [true, false, true, false]);
var w = await plc.ReadLinkRegistersAsync(100, 2);
var r = await plc.ReadFileRegistersAsync(100, 2);
var zr = await plc.ReadExtendedFileRegistersAsync(100, 2);
Use generic APIs when you want to specify McDeviceCode directly:
var words = await plc.ReadWordsAsync(McDeviceCode.DataRegister, 100, 2);
var bits = await plc.ReadBitsAsync(McDeviceCode.InternalRelay, 100, 8);
Random Access
3E / 4E frames can access non-consecutive devices in one transaction:
var random = await plc.ReadRandomAsync(
wordDevices:
[
new McDeviceAddress(McDeviceCode.DataRegister, 100),
new McDeviceAddress(McDeviceCode.LinkRegister, 10)
],
doubleWordDevices:
[
new McDeviceAddress(McDeviceCode.DataRegister, 200)
]);
await plc.WriteRandomWordsAsync(
wordValues:
[
new McWordWrite(McDeviceCode.DataRegister, 110, 1234)
],
doubleWordValues:
[
new McDoubleWordWrite(McDeviceCode.DataRegister, 210, 0x12345678)
]);
Simulate Without a PLC
var memory = new McSlaveMemory();
memory.DataRegisters[100] = 1234;
memory.InternalRelays[10] = true;
await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("plc-link", new McSlaveResponder(memory));
builder.AddMitsubishiMc("plc", "plc-link");
});
Run sample: samples/Zeus.Samples.Console.Mc.
JSON Configuration
{
"channels": [
{ "name": "plc-link", "type": "tcp", "host": "192.168.1.10", "port": 5000 }
],
"devices": [
{
"name": "plc",
"channel": "plc-link",
"type": "mitsubishi-mc",
"frameType": "4e",
"encoding": "ascii",
"points": [
{ "name": "temperature", "deviceCode": "D", "address": 100, "scale": 0.1, "writable": true },
{ "name": "run", "deviceCode": "M", "address": 10, "writable": true },
{ "name": "ready", "deviceCode": "X", "address": "0x10" },
{ "name": "recipe", "deviceCode": "ZR", "address": 0 }
]
}
]
}
Virtual MC PLC channel:
{ "name": "plc-link", "type": "virtual", "responder": "mc" }
Scope
| Capability | Status |
|---|---|
| 3E / 4E Binary and ASCII | Supported |
| 1E Binary and ASCII | Common batch read/write supported |
| D, M, X, Y, W, R, ZR access | Supported, with ZR on 3E/4E |
| Random read/write | Supported on 3E/4E |
| JSON points, acquisition, write-back | Supported |
| Virtual PLC | Supported |
Next: Modbus or Custom Framing.