S7-1200 Modbus TCP to COM800: Polling 3VA Breakers

David Krause22 min read
ModbusSiemensTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

S7-1200 Modbus TCP to COM800: Polling 3VA Breakers

The COM800 communication module (Siemens part number 3VA9987-0TA10) is the gateway that brings 3VA molded case circuit breakers into a Modbus TCP supervisory network. Each COM800 aggregates up to eight 3VA breakers on an internal RS-485 (Modbus RTU) bus and presents them as a single Modbus TCP server on Ethernet. The proprietary T-Connect bus allows up to eight COM800 modules to be daisy-chained with RJ45 patch cables, so a single Ethernet port on a controller can poll up to 64 breakers. This reference documents the field-proven architecture and code for a Siemens SIMATIC S7-1200 CPU acting as a Modbus TCP client that polls sixteen 3VA breakers distributed across two COM800 units.

Topology constraint: The T-Connect RS-485 link between COM800 modules is half-duplex. The client cannot issue requests to multiple COM800s simultaneously; it must sequence requests per server. However, each COM800 manages its internal RS-485 bus to the eight 3VA breakers autonomously, so the application code only manages two concurrent TCP connections - one per COM800 - even with 16 breakers.

1. System Overview

The 3VA molded case circuit breaker family supports an electronic trip unit (ETU) that exposes breaker status, current, voltage, power, and energy over a serial link. To bring that data into an Ethernet supervisory network, Siemens offers two communication modules:

Module Description Use Case
COM800 3VA communication module with Ethernet (Modbus TCP) and T-Connect Aggregates up to 8 3VA breakers into one Modbus TCP server
COM100 3VA communication module with USB and T-Connect Local commissioning and diagnostics via TD500 or PC tool

The COM800 is the focus of this article. It exposes a single Modbus TCP server endpoint and forwards each request to the 3VA breaker whose Modbus RTU address (1-8) matches the Unit_ID in the incoming request. The COM800 itself is transparent in the Modbus transaction: the client sees the COM800's IP address, but the Unit_ID selects the breaker inside. For the 16-breaker use case, two COM800 units are deployed:

  • COM800 #1 - IP 192.168.0.10, T-Connect address 1, hosts 8 breakers with Unit_ID 1-8
  • COM800 #2 - IP 192.168.0.11, T-Connect address 2, hosts 8 breakers with Unit_ID 1-8

The two COM800s are daisy-chained via T-Connect cables. The S7-1200 reaches both over a single Ethernet switch using the standard Modbus TCP port 502. The full Modbus TCP instruction set is part of the S7-1200 system manual collection, which covers MB_CLIENT, MB_SERVER, and the underlying TCON/TDIS/TSEND/TRCV blocks; see the TIA Portal Modbus TCP instructions reference.

2. Hardware Architecture and T-Connect Topology

The following diagram shows the physical network. The S7-1200 sits on the Ethernet segment with two COM800 modules; each COM800 has its own RS-485 bus to its eight 3VA breakers.

S7-1200 to COM800 T-Connect Network S7-1200 CPU 1214C 192.168.0.1 Switch Industrial COM800 #1 T-Connect Addr: 1 192.168.0.10 8 Breakers (UID 1-8) COM800 #2 T-Connect Addr: 2 192.168.0.11 8 Breakers (UID 1-8) T-Connect RS-485 half-duplex 3VA #1 (UID 1) 3VA #2 (UID 2) 3VA #3 (UID 3) 3VA #4 (UID 4) 3VA #5 (UID 5) 3VA #6 (UID 6) 3VA #7 (UID 7) RS-485 3VA #9 (UID 1) 3VA #10 (UID 2) 3VA #11 (UID 3) 3VA #12 (UID 4) RS-485 Modbus TCP (Ethernet) T-Connect RS-485 RS-485 to 3VA

The T-Connect bus is terminated on the first and last COM800 in the chain via DIP switches on the underside of the module. The maximum T-Connect cable length between modules is 10 m, with a total chain length of 80 m. The T-Connect bus carries both data and 24 V DC power for the COM800 modules, eliminating the need for separate power wiring on intermediate modules. The T-Connect port uses standard RJ45 connectors but is not Ethernet - it is a Siemens proprietary RS-485 signaling.

DIP switch settings on the COM800: Switches 1-3 set the T-Connect address (1-8). Switch 4 enables the terminating resistor (must be ON at both ends of the chain). Switch 5 is reserved. The COM800 ships with T-Connect address 1 and termination enabled; both must be reconfigured when adding a second module.

3. Prerequisites and Components

The following components are required for a 16-breaker implementation:

Component Part Number Notes
S7-1200 CPU 6ES7214-1AG40-0XB0 (CPU 1214C DC/DC/DC) Firmware V4.2 or later recommended for 16 OUC support
COM800 communication module 3VA9987-0TA10 Firmware V1.4 or later for stable daisy-chaining
3VA molded case circuit breaker 3VA11/3VA12/3VA13/3VA14/3VA20/3VA21/3VA22/3VA23/3VA24/3VA25 ETU 5-series, 6-series, or 8-series required for Modbus data
24 V DC power supply SITOP 6EP1332-3BA10 or equivalent 2.5 A minimum for 2x COM800 plus 3VA ETUs
TIA Portal 6ES7822-1A.04 (V16) or later Required for current MB_CLIENT block and library
Industrial Ethernet switch SCALANCE XC-100 or equivalent Unmanaged switch acceptable; 100 Mbit/s sufficient

The S7-1200 CPU must be at firmware V4.0 or later for full Modbus TCP support with the per-request MB_UNIT_ID parameter. Earlier firmware versions do not support the dynamic Unit_ID input; the Unit_ID is then set as a static property of the connection configuration, which prevents cycling through multiple Unit_IDs on a single TCP connection. The COM800 firmware V1.4 is required for stable T-Connect daisy-chaining; V1.0 and V1.1 had timing issues under heavy load. Each 3VA breaker must have an ETU that supports Modbus communication. The ETU 3VA 5-series, 6-series, and 8-series all support Modbus data. The ETU 3VA 3-series (thermal-magnetic) does not provide measurement data and only supports trip status flags via discrete inputs, not holding registers.

4. Modbus Address Map and Unit_ID Strategy

The 3VA register map is documented in the 3VA Communication System Manual (Siemens document number 3ZW1012-3VA00-0AA0). The exact register layout depends on the ETU type, but the following subset is common to ETU 5-series and higher and is read in a single FC 03 transaction:

Modbus Address Description Access Unit / Scale
40001 Status word (breaker state, trip indicators) R bitmask
40002 Trip history (most recent trip cause) R bitmask
40003 Alarm flags (overcurrent, ground fault, voltage) R bitmask
40005 Phase A current (L1) R 0.1 A
40006 Phase B current (L2) R 0.1 A
40007 Phase C current (L3) R 0.1 A
40008 Neutral current (computed) R 0.1 A
40010 Line-to-line voltage Uab (L1-L2) R 0.1 V
40011 Line-to-line voltage Ubc (L2-L3) R 0.1 V
40012 Line-to-line voltage Uca (L3-L1) R 0.1 V
40013 Average line-to-line voltage R 0.1 V
40015 Active power total (32-bit, registers 15-16) R 0.1 kW
40017 Reactive power total (32-bit, registers 17-18) R 0.1 kvar
40019 Power factor R 0.01
40020 Frequency R 0.01 Hz
40021 Active energy total (32-bit, registers 21-22) R 0.1 kWh
40023 Reactive energy total (32-bit, registers 23-24) R 0.1 kvarh
Register map caveat: The address offsets shown are typical for ETU 5-series. ETU 6-series and 8-series extend the map with harmonic distortion (THD per phase), demand values (15-min sliding window), and per-phase energy. Always consult the specific ETU register map in the 3VA Communication System Manual for the exact address assignments on the installed hardware.

The Unit_ID in a Modbus TCP request selects the 3VA breaker on the COM800's internal RS-485 bus. The COM800 itself is transparent: it accepts any Unit_ID 1-255, but the breakers must be configured to Unit_ID 1-8. The Unit_ID is set on each 3VA breaker via the ETU display (Parameters -> Communication -> Modbus Address) or through the COM800's web interface. The 3VA's display shows the address in the same menu and the COM800 web page lists the breakers it has discovered on its RS-485 bus.

COM800 IP T-Connect Address 3VA Breaker Modbus Unit_ID
192.168.0.10 1 3VA #1 1
192.168.0.10 1 3VA #2 2
192.168.0.10 1 3VA #3 3
192.168.0.10 1 3VA #4 4
192.168.0.10 1 3VA #5 5
192.168.0.10 1 3VA #6 6
192.168.0.10 1 3VA #7 7
192.168.0.10 1 3VA #8 8
192.168.0.11 2 3VA #9 1
192.168.0.11 2 3VA #10 2
192.168.0.11 2 3VA #11 3
192.168.0.11 2 3VA #12 4
192.168.0.11 2 3VA #13 5
192.168.0.11 2 3VA #14 6
192.168.0.11 2 3VA #15 7
192.168.0.11 2 3VA #16 8

The Unit_ID is local to each COM800: COM800 #1 and COM800 #2 both use Unit_IDs 1-8 because the IP address selects the COM800. There is no global Unit_ID scheme across the entire network, and Unit_ID 0 (broadcast) is reserved by Modbus and is not supported by the COM800.

5. S7-1200 MB_CLIENT Configuration

The S7-1200 uses the MB_CLIENT instruction from the TIA Portal Modbus TCP library to act as a Modbus TCP client. The instruction is part of the standard library and requires no additional license for CPU firmware V4.0 and later. The block interface is shown below.

Parameter Direction Type Description
REQ Input BOOL Rising edge triggers a new Modbus request
DISCONNECT Input BOOL TRUE drops the TCP connection; FALSE keeps it open
CONNECT_ID Input UINT Unique connection identifier (1-255). Must be unique per MB_CLIENT instance
IP_OCTET_1..4 Input USINT Target IP address octets (e.g., 192, 168, 0, 10)
IP_PORT Input UINT TCP port (502 for standard Modbus TCP)
MB_MODE Input USINT 0=Read, 1=Write, 2=Read/Write (FC 23)
MB_DATA_ADDR Input UDINT Modbus start address (e.g., 40001 for holding register 1)
MB_DATA_LEN Input UINT Number of registers to read/write (max 125 per FC 03/04, max 123 per FC 16)
MB_UNIT_ID Input USINT Modbus Unit_ID (1-255). V4.0+ only. Sets per-request Unit_ID
DATA_PTR InOut VARIANT Pointer to data buffer (DB, UDT, or tag)
DONE Output BOOL Request completed successfully (one-shot pulse)
BUSY Output BOOL Request in progress
ERROR Output BOOL Error occurred
STATUS Output WORD Status or error code (see Section 11)

The S7-1200 has hard limits on the number of Open User Communications (OUC) connections, which MB_CLIENT uses internally. These limits are firmware and CPU dependent:

CPU Firmware OUC Connections PG / HMI / S7 Connections
V4.0 - V4.3 8 (most CPUs) 1 PG + 1-4 HMI + 8 S7 (CPU-specific)
V4.4 16 (CPU 1215C, 1217C); 8 (1214C) Same as above
V4.5+ 16 (most CPUs) Same as above

For the 16-breaker use case, the 8 OUC limit on V4.0-V4.3 firmware makes a "one MB_CLIENT per breaker" architecture infeasible. The recommended pattern uses two MB_CLIENT instances (one per COM800) and cycles the Unit_ID, MB_DATA_ADDR, and DATA_PTR between transactions. This keeps the OUC connection count at 2 and scales to any number of breakers. If the application is upgraded to a CPU 1215C or 1217C with firmware V4.4 or later, the per-breaker architecture becomes possible with up to 16 MB_CLIENT instances.

6. TIA Portal Project Setup

Configure the S7-1200 project as follows:

  1. Open TIA Portal and create a new project. Select the project view (not the portal view).
  2. Add the S7-1200 CPU to the project: Devices & Networks -> Add new device -> SIMATIC S7-1200 -> CPU 1214C DC/DC/DC (6ES7214-1AG40-0XB0).
  3. Configure the PROFINET interface of the CPU with IP address 192.168.0.1 and subnet mask 255.255.255.0. Disable PROFINET device mode if not used.
  4. Add a new global DB named "DB_Breakers" with the data structure shown in Section 8. Use the UDT_3VA_Breaker type for each element.
  5. Add two MB_CLIENT instances:
    • MB_CLIENT_1 (instance DB 100) for COM800 #1
    • MB_CLIENT_2 (instance DB 101) for COM800 #2
    The block is found in Instructions -> Communication -> Modbus TCP -> MB_CLIENT. Drag it into the project twice and assign unique instance DBs.
  6. Create a cyclic OB (OB1) and add the polling logic from Section 7.
  7. Compile the project, then download to the S7-1200. Select "Download to device -> Extended download" and check the action "Download hardware configuration".

The MB_CLIENT block does not require a separate connection configuration in the Devices & Networks editor; the block manages the TCP connection internally using the IP_OCTET inputs. However, the CPU's PROFINET interface must be configured with a valid IP address on the same subnet as the COM800 modules.

CPU firmware check: Confirm the CPU firmware in TIA Portal (Online -> Accessible devices -> Module information -> Firmware). The MB_UNIT_ID parameter requires V4.0 or later. Older firmware versions expose the Unit_ID as a property of the connection configuration rather than as a per-request input. If the firmware is below V4.0, an upgrade is required - the MB_CLIENT on older firmware does not support dynamic Unit_ID cycling.

7. Sample SCL Code for Two COM800s

The following SCL code in OB1 polls all 16 breakers in a round-robin sequence. Each MB_CLIENT block handles one COM800; the Unit_ID is rotated per breaker. A 200 ms timer drives the state machine, giving a full poll cycle of approximately 3.2 seconds for 16 breakers (16 x 200 ms).

// OB1 - Cyclic polling of 16 3VA breakers
// Two MB_CLIENT instances, one per COM800
VAR
    pollState  : INT;          // 0=idle, 1..16=poll index
    pollTimer  : TON;          // 200 ms interval timer
END_VAR

BEGIN
    // 200 ms tick - advance state on every cycle
    pollTimer(IN := NOT pollTimer.Q, PT := T#200ms);
    IF pollTimer.Q THEN
        pollState := pollState + 1;
        IF pollState > 16 THEN
            pollState := 1;
        END_IF;
    END_IF;

    // State 0: idle, wait for next tick
    IF pollState = 0 THEN
        RETURN;
    END_IF;

    // States 1..8: poll COM800 #1, breakers 1-8
    IF pollState >= 1 AND pollState <= 8 THEN
        "DB_MB1".REQ          := TRUE;
        "DB_MB1".DISCONNECT   := FALSE;
        "DB_MB1".CONNECT_ID   := 1;
        "DB_MB1".IP_OCTET_1   := 192;
        "DB_MB1".IP_OCTET_2   := 168;
        "DB_MB1".IP_OCTET_3   := 0;
        "DB_MB1".IP_OCTET_4   := 10;
        "DB_MB1".IP_PORT      := 502;
        "DB_MB1".MB_MODE      := 0;       // Read holding registers (FC 03)
        "DB_MB1".MB_DATA_ADDR := 40001;
        "DB_MB1".MB_DATA_LEN  := 16;
        "DB_MB1".MB_UNIT_ID   := INT_TO_USINT(pollState);
        "DB_MB1".DATA_PTR     := "DB_Breakers".COM800_1[pollState];

        IF "DB_MB1".DONE THEN
            "DB_MB1".REQ := FALSE;
            "DB_Breakers".COM800_1[pollState].LastUpdate := CURRENT_TIMESTAMPS;
            "DB_Breakers".COM800_1[pollState].CommStatus := 0;
        END_IF;
        IF "DB_MB1".ERROR THEN
            "DB_MB1".REQ := FALSE;
            "DB_Breakers".COM800_1[pollState].CommStatus := 1;
            "DB_Breakers".COM800_1[pollState].LastStatus := "DB_MB1".STATUS;
        END_IF;
    END_IF;

    // States 9..16: poll COM800 #2, breakers 1-8
    IF pollState >= 9 AND pollState <= 16 THEN
        "DB_MB2".REQ          := TRUE;
        "DB_MB2".DISCONNECT   := FALSE;
        "DB_MB2".CONNECT_ID   := 2;
        "DB_MB2".IP_OCTET_1   := 192;
        "DB_MB2".IP_OCTET_2   := 168;
        "DB_MB2".IP_OCTET_3   := 0;
        "DB_MB2".IP_OCTET_4   := 11;
        "DB_MB2".IP_PORT      := 502;
        "DB_MB2".MB_MODE      := 0;
        "DB_MB2".MB_DATA_ADDR := 40001;
        "DB_MB2".MB_DATA_LEN  := 16;
        "DB_MB2".MB_UNIT_ID   := INT_TO_USINT(pollState - 8);
        "DB_MB2".DATA_PTR     := "DB_Breakers".COM800_2[pollState - 8];

        IF "DB_MB2".DONE THEN
            "DB_MB2".REQ := FALSE;
            "DB_Breakers".COM800_2[pollState - 8].LastUpdate := CURRENT_TIMESTAMPS;
            "DB_Breakers".COM800_2[pollState - 8].CommStatus := 0;
        END_IF;
        IF "DB_MB2".ERROR THEN
            "DB_MB2".REQ := FALSE;
            "DB_Breakers".COM800_2[pollState - 8].CommStatus := 1;
            "DB_Breakers".COM800_2[pollState - 8].LastStatus := "DB_MB2".STATUS;
        END_IF;
    END_IF;
END_ORGANIZATION_BLOCK

The state machine increments pollState on every 200 ms tick, triggering a new request to the appropriate COM800 and breaker. The DATA_PTR is updated each cycle to write the response into the correct slot of the structured DB. After 16 ticks (3.2 s), the cycle repeats. The MB_CLIENT call from a single OB1 cycle is non-blocking: the block sets BUSY = TRUE and continues in subsequent cycles until DONE or ERROR fires.

REQ pulse handling: The MB_CLIENT requires a rising edge on REQ to start a new request. Setting REQ := TRUE every cycle and clearing it when DONE or ERROR fires is the standard pattern. Failing to clear REQ causes the block to re-trigger immediately and may produce overlapping transactions that the COM800 will reject.

8. Data Block Layout for Breaker Data

Define a UDT for the 3VA breaker data and instantiate it in a global DB:

// UDT_3VA_Breaker - 16 holding registers (32 bytes)
TYPE UDT_3VA_Breaker :
STRUCT
    StatusWord      : WORD;    // 40001 - breaker state, trip flags
    TripHistory     : WORD;    // 40002 - most recent trip cause
    Alarms          : WORD;    // 40003 - alarm word
    Spare1          : WORD;    // 40004 - reserved
    CurrentA        : INT;     // 40005 - Phase A current, 0.1 A
    CurrentB        : INT;     // 40006 - Phase B current, 0.1 A
    CurrentC        : INT;     // 40007 - Phase C current, 0.1 A
    CurrentN        : INT;     // 40008 - Neutral current, 0.1 A
    Spare2          : WORD;    // 40009 - reserved
    VoltageAB       : INT;     // 40010 - Uab, 0.1 V
    VoltageBC       : INT;     // 40011 - Ubc, 0.1 V
    VoltageCA       : INT;     // 40012 - Uca, 0.1 V
    VoltageAvg      : INT;     // 40013 - Uavg, 0.1 V
    Spare3          : WORD;    // 40014 - reserved
    ActivePower     : DINT;    // 40015-40016 - active power, 0.1 kW
    ReactivePower   : DINT;    // 40017-40018 - reactive power, 0.1 kvar
    PowerFactor     : INT;     // 40019 - power factor, 0.01
    Frequency       : INT;     // 40020 - frequency, 0.01 Hz
    ActiveEnergy    : DINT;    // 40021-40022 - active energy, 0.1 kWh
    ReactiveEnergy  : DINT;    // 40023-40024 - reactive energy, 0.1 kvarh
    LastUpdate      : DTL;     // PLC timestamp of last successful read
    CommStatus      : INT;     // 0=OK, 1=timeout, 2=protocol error
    LastStatus      : WORD;    // MB_CLIENT STATUS word on error
END_STRUCT
END_TYPE

// Global DB for 16 breakers
DATA_BLOCK "DB_Breakers"
STRUCT
    COM800_1 : ARRAY[1..8] OF UDT_3VA_Breaker;
    COM800_2 : ARRAY[1..8] OF UDT_3VA_Breaker;
END_STRUCT
BEGIN
END_DATA_BLOCK

The UDT contains the first 16 holding registers (32 bytes), which include the most critical data: status, currents, voltages, power, and energy. The MB_DATA_LEN := 16 reads all 16 registers in a single Modbus FC 03 transaction. The Spare1-Spare3 WORDs are reserved for the 3VA Communication System Manual's per-ETU register gaps and are intentionally placed so the UDT matches the Modbus data layout byte-for-byte.

Byte order: The MB_CLIENT stores multi-byte values in big-endian (Modbus standard). The S7-1200 is little-endian, so DINT and DWORD values appear with bytes swapped. A 32-bit active power read from registers 40015-40016 will have the high register in the low word of the DINT and the low register in the high word. Use the SWAP instruction, the CAW/CAD swap functions, or define a separate "swapped" UDT and apply a block-move with byte reversal in OB1 before scaling and display.

9. Sequential Polling with Clock Memory

The 200 ms poll interval balances update latency against bus load. Each Modbus TCP transaction takes 30-100 ms over a 100 Mbit Ethernet segment; 16 transactions at 200 ms intervals yield a full update cycle of 3.2 seconds. This is acceptable for monitoring and trending but not for fast protection or control. For faster updates, the interval can be reduced to 100 ms (1.6 s cycle for 16 breakers), but the COM800's internal RTU bus becomes the bottleneck: each breaker request takes 20-50 ms on the half-duplex RS-485 link, and the COM800 serializes up to 8 incoming TCP requests before forwarding them to the RTU bus. Under heavy load, requests queue and the COM800's response time can exceed 1 s.

The recommended approach for predictable latency is to use clock memory (available in the CPU properties under System & Clock Memory) to drive the state machine. The S7-1200 supports clock bytes at MB0-MB7, with MB0 typically used as a 10 Hz pulse:

// Alternative: drive polling with 10 Hz clock memory
VAR
    pollTick  : BOOL;       // 100 ms pulse from MB0.5
    pollTickOld : BOOL;     // edge detection
END_VAR

BEGIN
    pollTick := "Clock_10Hz";  // MB0.5 if 10 Hz configured in CPU properties

    IF pollTick AND NOT pollTickOld THEN
        // Rising edge - advance state
        pollState := pollState + 1;
        IF pollState > 16 THEN
            pollState := 1;
        END_IF;
    END_IF;
    pollTickOld := pollTick;
END

For deterministic behavior, an IEC timer in a cyclic OB is preferred over clock memory, since the OB1 cycle time is consistent and the timer can be reset on a known boundary. Use a 100 ms or 200 ms TON instance and check its Q output for the state advance, as shown in the OB1 code in Section 7. For ultra-low-latency polling, consider using an OB35 (cyclic interrupt) with a 50 ms execution interval, but verify that the COM800 can sustain that request rate without queue overflow on its internal RTU bus.

10. Verification and Diagnostics

After downloading the program, verify communication with the following checks:

  1. Online watch table. Open the watch table in TIA Portal and monitor "DB_Breakers".COM800_1[1]. The status word, currents, and voltages should update every 3.2 seconds. The LastUpdate timestamp should be recent. If CommStatus stays at 1, the breaker is not responding.
  2. COM800 web interface. Each COM800 exposes a web server on port 80. Navigate to http://192.168.0.10/ to see the device status, the eight 3VA breakers connected, and the most recent Modbus transaction counters. The "Last Error" field on the diagnostics page reveals which Unit_ID failed and why.
  3. MB_CLIENT STATUS word. If a breaker is offline, the MB_CLIENT returns a non-zero STATUS. Common values: 0x80C8 (connection timeout), 0x80C9 (connection error), 0x8380 (invalid Unit_ID). The STATUS code persists until the next successful transaction.
  4. Wireshark capture. Filter on "modbus" or "tcp.port == 502" to see the request/response pairs. Each transaction should show a 12-byte MBAP header followed by the function code and data. Verify the Unit_ID byte matches the expected breaker.
  5. 3VA ETU display. The breaker's display can show the assigned Modbus address and the most recent communication timestamp, useful for confirming that the COM800 is reaching the breaker. Navigate to Parameters -> Communication -> Diagnostics on the ETU.

Capture a single Modbus TCP request to verify the Unit_ID and address are correct. A read-holding-registers request for 16 registers starting at 40001 looks like this on the wire:

00 01 00 00 00 06 01 03 9C 41 00 10
TxID  PID  PDULen UID FC  StartAddr Qty
0x0001 0x0000 0x0006 0x01 0x03 0x9C41  0x0010

The bytes decode as: Transaction ID 0x0001, Protocol ID 0x0000 (Modbus), PDU length 0x0006, Unit ID 0x01 (breaker 1), Function code 0x03 (read holding), Start address 0x9C41 (40001 in big-endian), Quantity 0x0010 (16 registers). The corresponding response is 0x0001 0x0000 0x0023 0x01 0x03 0x20 <32 bytes of data>. The PDU length grows to 0x0023 (35 bytes) to accommodate the function code (1), byte count (1), and 32 data bytes.

11. Troubleshooting Matrix

Common faults and their resolution:

Symptom STATUS Code Root Cause Resolution
All MB_CLIENT calls return timeout 0x80C8 COM800 not reachable; wrong IP, wrong subnet, switch port down, or 24 V missing Ping the COM800 from a laptop on the same subnet; verify the IP and subnet mask in the COM800 web interface; measure 24 V at the COM800 terminals (must be >22 V under load)
Specific breaker returns protocol error 0x8380 Wrong Unit_ID; breaker offline; 3VA ETU does not support Modbus (e.g., ETU 3-series) Verify the breaker's Modbus address in the ETU display under Parameters -> Communication; check that an ETU 5-series or higher is installed
Reading returns wrong values (currents off by factor 10) 0x0000 (no error) Byte order mismatch; MB_DATA_ADDR off by 1; wrong scaling applied Confirm the start address; check that MB_DATA_ADDR matches the manual (some ETU manuals use 0-based offsets); apply 0.1 A scaling explicitly
First read works, subsequent reads fail 0x80C9 REQ not cleared after DONE; overlapping transactions on the same connection Reset REQ on DONE and ERROR; add a guard to prevent REQ := TRUE while BUSY = TRUE
Communication works in WinCC but not in PLC 0x80D0 CPU firmware does not support MB_UNIT_ID parameter; Unit_ID was set in WinCC's driver config Upgrade CPU firmware to V4.0+; or configure Unit_ID in the connection properties instead of as a per-request input
Some breakers on T-Connect chain not visible 0x80C8 Duplicate T-Connect address; missing termination on chain ends; bad cable Verify DIP switches on each COM800 (addresses must be unique 1-8); check termination on first and last module; swap T-Connect cables to isolate the fault
Read takes >1 s to complete 0x0000 COM800 RTU bus saturated; too many concurrent TCP connections from PLC or HMI Reduce number of simultaneous MB_CLIENT blocks; cycle through breakers sequentially rather than in parallel; check that no other client is hammering the COM800
Intermittent failures, especially at startup 0x80C8 / 0x80C9 COM800 not finished booting; PLC starts polling before COM800 accepts TCP Add a 5 s startup delay at the beginning of OB1 before triggering the first REQ; check the COM800's RUN LED is solid green
Energy counters do not increment 0x0000 ETU only updates energy registers on a metered interval; or the values are read from a different register range Wait 60 s and re-check; refer to the 3VA Communication System Manual for the energy register base address on the installed ETU version
Power supply warning: The COM800 requires 24 V DC at 250 mA per module. Under-voltage causes intermittent communication failures that look like timeout errors. Measure the voltage at the COM800 terminals under load; it must be 22 V or higher. The T-Connect bus carries 24 V to downstream COM800 modules; a missing terminator or a reversed RJ45 cable on T-Connect can cut power to subsequent modules silently.

12. Frequently Asked Questions

How many COM800 modules can an S7-1200 poll on a single Ethernet port?

Physically, the T-Connect bus supports up to 8 COM800 modules, giving a theoretical 64-breaker maximum. In practice, the S7-1200 OUC limit caps the number of simultaneous MB_CLIENT connections at 8 (firmware V4.0-V4.3) or 16 (firmware V4.4+ on CPU 1215C/1217C). Use one MB_CLIENT per COM800 and cycle through Unit_IDs to scale beyond 8 or 16 breakers.

Can the S7-1200 poll all 8 breakers on a single COM800 simultaneously?

No. The COM800's internal RS-485 bus is half-duplex, so only one Modbus RTU request can be on the wire at a time. The COM800 serializes incoming TCP requests and forwards them to the breakers sequentially. Use the cycling pattern from Section 7 to poll breakers in round-robin order; expect 30-100 ms per breaker on the TCP side plus 20-50 ms on the internal RTU bus per breaker.

What is the difference between T-Connect address and Modbus Unit_ID?

T-Connect address (1-8) is the COM800's position on the proprietary T-Connect daisy-chain bus, set by DIP switch. Modbus Unit_ID (1-8) is the 3VA breaker's address on the COM800's internal RS-485 bus, set on the breaker's ETU. The two are independent: the IP address selects the COM800, and the Unit_ID selects the breaker inside.

Does the S7-1200 require a license for Modbus TCP communication?

No. Modbus TCP is built into the S7-1200 firmware V4.0 and later. The MB_CLIENT and MB_SERVER instructions are part of the standard library that ships with TIA Portal. No additional license or hardware is required, but the per-request MB_UNIT_ID input is only available on firmware V4.0 and later.

Why do my DINT power and energy values read backwards?

Modbus is big-endian; the S7-1200 is little-endian. The MB_CLIENT places the Modbus bytes into the destination buffer in the order received, so a DINT read as registers 40015-40016 appears with the high and low words swapped. Use the SWAP instruction, or define a separate swap UDT with word pairs reversed, and convert before scaling and display on the HMI.

What happens if the T-Connect cable between two COM800 modules is disconnected?

Downstream COM800 modules lose both data and 24 V power. The upstream COM800 continues to operate and respond to Modbus TCP requests for its own eight breakers. PLC-side, only the upstream COM800's Unit_IDs return data; requests to the downstream COM800's IP timeout. Check the upstream COM800's T-Connect LEDs and the downstream module's power LED before swapping cables.

Back to blog