Configuring Modbus RTU Master on ET200SP CM PtP for Energy Meters

David Krause18 min read
Serial CommunicationSiemensTutorial / How-to
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

System Architecture and Communication Path

Reading data from a KLEFR 6934 three-phase energy meter over Modbus RTU requires three distinct layers to be correctly aligned: the physical RS-485 bus, the serial protocol framing (Modbus RTU), and the application layer that maps raw holding registers to engineering values. This article walks through the complete path from the ET200SP CPU to the energy meter using the CM PtP communication module 6ES7137-6AA00-0BA0, including hardware wiring, TIA Portal device configuration, the Modbus master parameterization, and SCL code that converts raw registers into 32-bit IEEE 754 floats in ABCD (big-endian, MSB first) byte order.

The reference hardware set used in this article is:

  • CPU: SIMATIC ET 200SP CPU 1510SP-1 PN (6ES7 510-1DJ01-0AB0, firmware V2.9 or higher recommended for full Modbus RTU master block support)
  • CM PtP: SIMATIC ET 200SP CM PtP (6ES7137-6AA00-0BA0) installed on a Type A0 BaseUnit such as 6ES7193-6BP00-0DA0 or 6ES7193-6BP00-0BA0
  • Energy meter: KLEFR 6934 three-phase direct energy meter, Modbus RTU slave over RS-485, 8 data bits / no parity / 1 stop bit or 8E1 (consult KLEFR operating instructions for the variant ordered)

RS-485 is the electrical layer, not a protocol. On top of RS-485 the meter uses Modbus RTU. The PLC must therefore be configured as a Modbus master and the meter as a Modbus slave with a unique address between 1 and 247. The CM PtP is the serial interface that converts the CPU's internal data buffers into differential A/B signals on the bus.

Important distinction: The CM PtP module is not plug-and-play Modbus. The Modbus RTU master protocol is implemented by the CPU's library blocks MB_COMM_LOAD and MB_MASTER (or MB_MASTER_PN for S7-1500 PN CPUs). The CM PtP itself is configured as a serial "freeport" interface; the higher-level Modbus state machine runs in the CPU's cyclic OB.

Prerequisites: Hardware, Firmware, and Software

Before commissioning, verify the following prerequisites.

Item Required value / version Notes
CPU firmware V2.5 or higher (V2.9+ recommended) Older firmware does not support the MB_MASTER instruction for ET200SP; use MB_MASTER_PN only with PN CPUs.
TIA Portal V17 or higher (V18/V19 recommended) Adds the latest Modbus RTU library and module HSP for ET200SP CM PtP.
CM PtP firmware Update to latest available via TIA Portal / SIMATIC Automation Tool Older FW has known issues with 19200/38400 baud stability on RS-485.
BaseUnit 6ES7193-6BP00-0DA0 (BU15-P16+A0+2D) or -0BA0 (BU15-P16+A0+2B) Type A0 BaseUnit required for the CM PtP.
RS-485 cable Twisted pair, shielded, characteristic impedance ~120 ohm Use LiYCY or Profibus cable (purple) as low-cost alternative.
Termination 120 ohm resistor at both bus ends CM PtP has internal switchable termination; KLEFR meter usually has a DIP switch or jumper.
KLEFR 6934 manual Operating instructions with Modbus register map Registers 5000 to 6006 (0-based) carry 32-bit float measurements.

Download the CM PtP manual from the official Siemens support page to keep the parameter list, diagnostic events, and error codes on hand during commissioning: ET200SP CM PtP manual (PDF).

Hardware Wiring: CM PtP to RS-485 Energy Meter

The CM PtP exposes the serial interface on the BaseUnit terminals. For RS-485, the relevant terminals are:

Terminal Signal (RS-485 half-duplex) Wire to KLEFR terminal
RxD/TxD-P (A) Non-inverting line D+ / A / T/R+ on meter
RxD/TxD-N (B) Inverting line D- / B / T/R- on meter
GND (reference) Signal ground Reference terminal on meter (do not connect shield to this)
Shield Cable shield Ground bar at cabinet entry, low-impedance

Steps to wire the bus:

  1. Disconnect the ET200SP station power and the 24 V supply to the BaseUnit.
  2. Connect terminal A of the CM PtP BaseUnit to terminal A of the KLEFR meter, and B to B. Polarity must match across the entire bus; reversing one device puts the slave in an indeterminate state.
  3. Connect the cable shield at one end only (cabinet PE bar) to avoid ground loops; leave the meter end floating or use a small capacitor (10 nF / 100 V) for HF grounding.
  4. Enable the CM PtP internal bus termination by setting the DIP switch on the back of the module to ON, but only if the CM PtP is physically the last device on the bus segment. Disable termination on all intermediate devices.
  5. If the KLEFR meter is the other bus end, enable its 120 ohm termination (typically a 2-pin jumper labeled "TERM" or a 120R DIP switch on the meter PCB).
  6. Power up the station and observe the LEDs on the CM PtP: a green PWR and a steady or slow-blinking DIAG indicate the module is ready for cyclic operation.
Topology: RS-485 is a bus, not a star. Run the cable in a daisy chain; stubs must be kept shorter than ~30 cm. Maximum bus length at 19200 baud is 1200 m, at 38400 baud is 600 m (per EIA-485). The KLEFR 6934 default baud is typically 9600 or 19200, which comfortably supports runs of 100 m inside a cabinet.

TIA Portal Device Configuration

After physically installing the CM PtP next to the CPU on the ET200SP rack, configure the module in the TIA Portal device view.

  1. Open the project and select the ET200SP station in the project tree.
  2. Drag the CM PtP (6ES7137-6AA00-0BA0) from the hardware catalog onto the slot next to the CPU. The order is fixed: CM PtP must be plugged into a BaseUnit directly adjacent to the CPU; it cannot be skipped.
  3. In the module's Properties > General, switch the operating mode from Freeport (RS232/422/485) to Freeport protocol; the Modbus RTU master is a CPU-side library, so the module must be in freeport mode.
  4. Set the Interface field to RS485 (half-duplex) and enable the internal termination if this module is the end of the bus.
  5. Set the diagnostic behavior: enable hardware interrupts on wire break, only if you want a fast reaction to a disconnected cable; otherwise leave at default for commissioning.
  6. Compile the hardware configuration and download it to the CPU.

The CM PtP must be assigned a hardware identifier (HW ID) by TIA Portal; this HW ID is later required by the MB_COMM_LOAD instruction. Note the HW ID (for example, 271) from the module's Properties > System constants tab.

Modbus Master Parameterization

Two function blocks implement the Modbus RTU master: MB_COMM_LOAD for one-time configuration of the serial port, and MB_MASTER for each request transaction. Both are part of the standard Modbus library that ships with every TIA Portal installation.

Block Called in OB Frequency Purpose
MB_COMM_LOAD OB100 (startup) and on parameter change Once per port configuration Initializes baud, parity, flow control on the CM PtP.
MB_MASTER OB1 (cyclic) One instance per concurrent transaction Issues a single Modbus request and waits for the response.

MB_COMM_LOAD parameters:

Input Data type Typical value for KLEFR Description
REQ BOOL TRUE on startup pulse Trigger to (re)load configuration.
PORT HW_IO (WORD) HW ID of CM PtP (e.g. 271) Identifies the serial port.
BAUD DINT 9600 or 19200 Baud rate. KLEFR default: 19200 8E1.
PARITY DINT 2 (even) or 0 (none) 0=none, 1=odd, 2=even.
FLOW_CTRL DINT 0 No RTS/CTS handshake on RS-485 half-duplex.
RTS_ON_DLY DINT 0 Delay before transmit, in ms.
RTS_OFF_DLY DINT 0 Delay after transmit, in ms.
RESP_TO DINT 1000 Response timeout in ms (slave must reply within this time).
DONE BOOL output Configuration loaded successfully.
ERROR BOOL output TRUE if configuration failed.
STATUS WORD output Detailed status / error code.

MB_MASTER parameters:

Input Data type Typical value Description
REQ BOOL Rising edge per request Trigger to start transaction.
MB_ADDR UINT 1 Modbus slave address (1 to 247).
MODE USINT 0 (read) / 1 (write) 0=FC03 read holding, 1=FC06 write single, 2=FC16 write multiple, etc.
DATA_ADDR UINT 5000 Modbus register start address (0-based inside the instruction).
DATA_LEN UINT 2 (per float) Number of 16-bit words to read.
DATA_PTR VARIANT Pointer to data buffer Source/destination slice, e.g. P#DB1.DBX0.0 BYTE 4 for 2 words.
DONE BOOL output Request completed without protocol error.
BUSY BOOL output Transaction in progress.
ERROR BOOL output TRUE if transaction failed.
STATUS WORD output Modbus error / status code.

MB_COMM_LOAD and MB_MASTER Function Blocks: Call Order and Timing

Follow this sequence when calling the two blocks:

  1. Call MB_COMM_LOAD in OB100 (startup OB) with a rising edge on REQ. Wait until DONE=TRUE and ERROR=FALSE before continuing. The block disables itself internally once the port is configured; further calls do nothing until REQ toggles again.
  2. Call MB_MASTER in OB1. It must be called cyclically, but the REQ input should be pulsed with a rising edge to start each new transaction. If BUSY=TRUE, do not trigger a new request on the same instance.
  3. Evaluate DONE and ERROR on each cycle. On ERROR=TRUE, read the STATUS word for the Modbus exception code (0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x90) or the CM PtP-specific error.
  4. Chain requests with a small inter-frame delay. With KLEFR 6934 at 19200 baud, a typical 8-word read takes ~25 ms; allow at least 50 ms between consecutive REQ pulses on the same instance to avoid overlapping transactions.
Single-instance limit: One instance of MB_MASTER handles one transaction at a time. To poll multiple ranges without serialization, declare multiple instance DBs (e.g. MB_MASTER_5000, MB_MASTER_5002), one per request, and trigger them with a state machine on a 100 to 200 ms cycle.

SCL Program: Reading KLEFR Registers 5000-6006

Registers 5000 to 6006 (per KLEFR documentation) hold 32-bit floating-point measurements such as voltage, current, power, frequency, and energy. Each float occupies two consecutive 16-bit holding registers. With Modbus function code 03 (read holding registers) the master requests N consecutive 16-bit words and the slave returns them in big-endian order.

The following SCL example shows a cyclic state machine that reads the entire 5000-6006 range in chunks of 32 registers (16 floats) and converts each pair of words into an IEEE 754 float with byte order ABCD (big-endian, MSB first). The conversion is necessary because the S7-1500 stores REAL in little-endian (DCBA) order.

// DB "KlefrModbusData"
// State constants
CONST
    ST_IDLE      : INT := 0;
    ST_REQ_CHUNK : INT := 10;
    ST_WAIT      : INT := 20;
    ST_NEXT      : INT := 30;
    ST_DONE      : INT := 99;
END_CONST

DATA_BLOCK "KlefrModbusData"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
  STRUCT
      state        : INT;          // current state
      chunkIndex   : INT;          // 0..(n-1)
      chunkCount   : INT := 4;     // (6006 - 5000 + 2) / 32 = 4
      regStart     : ARRAY[0..3] OF UINT := [5000, 5032, 5064, 5096];
      reqPulse     : BOOL;
      rawBuffer    : ARRAY[0..63] OF WORD;   // 32 words = 16 floats per chunk
      floatBuffer  : ARRAY[0..15] OF REAL;
      lastError    : WORD;
      lastStatus   : WORD;
  END_STRUCT;
END_DATA_BLOCK

// FB "KlefrPoll" (SCL)
FUNCTION_BLOCK "KlefrPoll"
VAR
    mbLoad  : MB_COMM_LOAD;     // single instance, called from OB100
    mbMaster: MB_MASTER;        // one instance per chunk
    instData: "KlefrModbusData";
    tPulse  : TON;
END_VAR

BEGIN
    // State 0: idle, request next chunk
    IF instData.state = ST_IDLE OR instData.state = ST_NEXT THEN
        instData.chunkIndex := instData.chunkIndex + 1;
        IF instData.chunkIndex >= instData.chunkCount THEN
            instData.chunkIndex := 0;
        END_IF;
        instData.state := ST_REQ_CHUNK;
    END_IF;

    // State 10: fire REQ pulse, then move to wait
    IF instData.state = ST_REQ_CHUNK THEN
        mbMaster(
            REQ      := instData.reqPulse,
            MB_ADDR  := 1,                                     // KLEFR slave address
            MODE     := 0,                                     // FC03 read holding
            DATA_ADDR:= instData.regStart[instData.chunkIndex],// start register
            DATA_LEN := 32,                                    // 32 words = 16 floats
            DATA_PTR := P#DB "KlefrModbusData".rawBuffer,
            DONE     => _,
            BUSY     => _,
            ERROR    => _,
            STATUS   => instData.lastStatus
        );
        instData.reqPulse := FALSE;
        // Re-arm REQ for next cycle using a one-shot pulse
        instData.state := ST_WAIT;
    END_IF;

    // State 20: wait for DONE/ERROR
    IF instData.state = ST_WAIT THEN
        mbMaster(
            REQ      := FALSE,
            MB_ADDR  := 1,
            MODE     := 0,
            DATA_ADDR:= instData.regStart[instData.chunkIndex],
            DATA_LEN := 32,
            DATA_PTR := P#DB "KlefrModbusData".rawBuffer,
            DONE     => _,
            BUSY     => _,
            ERROR    => _,
            STATUS   => instData.lastStatus
        );
        IF mbMaster.DONE THEN
            instData.state := ST_NEXT;
        ELSIF mbMaster.ERROR THEN
            instData.lastError := instData.lastStatus;
            instData.state := ST_NEXT;   // skip and retry next cycle
        END_IF;
    END_IF;
END_FUNCTION_BLOCK
Pulse generation: The example shows REQ toggled once per request. In production, drive a short one-shot (for example, a 50 ms TON that resets REQ) on the rising edge of a state transition; this guarantees the MB_MASTER block starts a fresh transaction exactly once.

Float ABCD Byte Order and Data Conversion

The KLEFR 6934 returns floats in ABCD byte order, which is the standard big-endian / network byte order. The S7-1500 stores REAL in DCBA order (little-endian). The conversion is therefore a two-step byte swap per word pair:

Meter register Byte order on the wire S7-1500 memory layout (little-endian) Required transformation
Register N (high word) MSB, LSB byte 3, byte 2 Swap bytes within the word (16-bit byte swap)
Register N+1 (low word) MSB, LSB byte 1, byte 0 Swap bytes within the word

The SCL snippet below converts the raw 16-bit word array into REAL values. It can be placed in the same FB or a separate FC called from the DONE branch of the poll state machine.

// FC "KlefrConvertABCDFloat" (SCL)
// Input:  pRaw  = P#DB "KlefrModbusData".rawBuffer (32 WORDs)
//         pReal = P#DB "KlefrModbusData".floatBuffer (16 REALs)
FUNCTION "KlefrConvertABCDFloat" : VOID
VAR_IN_OUT
    pRaw  : VARIANT;   // 32 WORDs
    pReal : VARIANT;   // 16 REALs
END_VAR
VAR_TEMP
    i       : INT;
    wHigh   : WORD;
    wLow    : WORD;
    dWord   : DWORD;
    rValue  : REAL;
END_VAR

BEGIN
    FOR i := 0 TO 15 DO
        // Read the two source words (big-endian) by symbolic name
        wHigh := WORD_TO_BLOCK_DB(NIL).rawBuffer[i * 2];
        wLow  := WORD_TO_BLOCK_DB(NIL).rawBuffer[i * 2 + 1];

        // ABCD > DCBA: swap bytes inside each word, then assemble as DWORD
        dWord := (DWORD(wHigh AND 16#00FF) SHL 8)
               OR (DWORD(wHigh AND 16#FF00) SHR 8)
               OR (DWORD(wLow  AND 16#00FF) SHL 24)
               OR (DWORD(wLow  AND 16#FF00) SHL 8);

        // Interpret DWORD as IEEE 754 REAL
        rValue := REAL_VALUE_FROM_DWORD(dWord);  // or: DWORD_TO_REAL via AT overlay

        // Store into destination REAL buffer
        WORD_TO_BLOCK_DB(NIL).floatBuffer[i] := rValue;
    END_FOR;
END_FUNCTION

An equivalent, type-safe approach uses an AT overlay on a 4-byte field. The principle is identical: take the two incoming WORDs in big-endian order, swap bytes within each word, and reinterpret the resulting DWORD as REAL. If you prefer a 16-bit byte swap instruction, search the TIA Portal libraries for SWAP / BYTE_SWAP_WORD; otherwise inline the shift-and-mask operations as shown above.

Engineering scaling: The KLEFR 6934 register map states the engineering unit, scale factor, and data type for each register. For example, line-to-line voltage may be in volts with one decimal, stored as float = 230.1 representing 230.1 V. Always cross-check the manual's "register address & unit" table before applying scaling factors; do not assume raw floats are direct SI units.

Diagnostics, LED Status, and Error Codes

The CM PtP has three LEDs relevant to commissioning: PWR, DIAG, and RX/TX. Their meaning in RS-485 freeport mode is documented in the CM PtP manual.

LED Color State Meaning
PWR Green Off No 24 V supply to BaseUnit.
PWR Green On Supply OK.
DIAG Green On / slow blink Module configured and ready.
DIAG Red On or fast blink Module fault; check the diagnostic buffer.
RX/TX Yellow / Green Flicker Traffic on the bus. Yellow = TX, Green = RX. Steady-on indicates the bus is stuck dominant (line fault).

Modbus error codes returned in the STATUS output of MB_MASTER:

Status (hex) Cause Remedy
0x0001 Illegal function code (slave returned 0x01) Check MODE against meter's supported function codes (FC03 / FC04 only on most KLEFR meters).
0x0002 Illegal data address (0x02) Verify the register start and length are within the meter's address range; KLEFR 6934 may use 0-based vs 1-based addressing depending on firmware.
0x0003 Illegal data value (0x03) Check byte count, data type, and FC consistency.
0x0080 CRC error Check wiring, baud, parity, termination, and bus shielding.
0x0081 Parity / framing error Parity and stop-bit settings do not match the meter; check BAUD and PARITY of MB_COMM_LOAD.
0x0082 Receive buffer overflow Increase RESP_TO, reduce poll rate, or split long reads into smaller chunks.
0x0083 No response within RESP_TO Slave address wrong, slave not powered, A/B polarity reversed, or termination missing.
0x0084 Invalid parameter Check DATA_ADDR, DATA_LEN, and MODE against the meter documentation.
0x0090 General error from CM PtP Module is in a fault state; evaluate the diagnostic buffer.

Troubleshooting Matrix

Use this matrix as a quick field reference when communication fails or data is garbage.

Symptom Likely cause Diagnostic check Fix
DIAG red, PWR off No 24 V to BaseUnit Measure 24 V on BU terminals Check fuse, PSU, wiring.
DIAG green, RX/TX never lights MB_MASTER never called or REQ not pulsed Monitor REQ in watch table Verify OB1 runs, instance DBs loaded, REQ is a 1-cycle pulse.
RX/TX flickers TX only, no RX A/B polarity reversed, or wrong slave address Swap A and B at one end only Re-check meter Modbus address; reverse polarity if needed.
RX/TX flickers both directions but STATUS=0x0080 (CRC) Baud or parity mismatch Check meter DIP switch Match BAUD / PARITY in MB_COMM_LOAD to meter.
Floats look "shifted" or wildly large Byte order wrong (DCBA vs ABCD) Display raw WORDs in HMI Insert byte-swap per the conversion logic above.
STATUS=0x0002 (illegal data address) Off-by-one between 0-based and 1-based addressing Read register 1; if it succeeds, manual is 0-based Subtract 1 from DATA_ADDR or re-read the manual.
STATUS=0x0083 (timeout) intermittent Bus termination missing or duplicated Check 120R at both ends only Enable termination at ends, disable mid-bus.
Values frozen at 0.0 Float buffer not refreshed; conversion FB not called Watch float buffer in TIA online Call conversion on DONE, not on cycle.
All values zero except float that drops bits 16-bit word alignment off; pointer DATA_PTR wrong size Inspect DB layout in TIA Use 4-byte aligned buffer for 32-bit values; DATA_LEN is in 16-bit words, not bytes.

Commissioning and Verification

After the first download, perform these checks before handing the system over to production.

  1. LED verification: PWR solid green, DIAG solid green, RX/TX flickers yellow then green on each poll cycle.
  2. Online STATUS monitoring: Force the MB_MASTER instance with the online watch table; STATUS must read 0x0000 within one cycle of DONE=TRUE.
  3. Float sanity check: Display raw holding register 5000 in HEX on the HMI; it must equal the value shown in the meter's Modbus test page (most KLEFR meters have a service mode that prints the raw register on a button press). Then compare the converted float against a handheld multimeter reading on the same phase.
  4. Burst test: Run 1000 transactions in a row and count ERRORs. A healthy bus should show < 0.1% errors; anything above 1% points to wiring or termination problems.
  5. Soak test: Leave the poll running for at least 24 hours and verify that no timeouts occur during normal operation. Timeouts under load (e.g. when a VFD is started in the same cabinet) indicate EMC issues; add ferrite cores on the bus cable or re-route it away from VFD power cables.
Safety: Always disconnect the CM PtP BaseUnit power before unplugging or wiring the module. The CM PtP does not provide electrical isolation between the bus and the backplane bus on all BaseUnit variants; verify isolation with a megohmmeter if the meter is on a different protective earth than the cabinet.

FAQ

Does the CM PtP module 6ES7137-6AA00-0BA0 implement Modbus RTU natively, or do I need extra library blocks?

The CM PtP operates as a freeport serial interface. The Modbus RTU master is implemented by the CPU-side library blocks MB_COMM_LOAD (one-time port configuration) and MB_MASTER (one instance per transaction). No additional hardware or firmware option is required on the CM PtP itself.

What is the difference between the -0BA0 and -0BA1 order numbers of the CM PtP?

6ES7137-6AA00-0BA0 is the original released variant. 6ES7137-6AA01-0BA0 is the functionally compatible successor with updated firmware and minor internal component changes. Both support RS-232, RS-422, and RS-485 freeport, and both use the same MB_COMM_LOAD / MB_MASTER blocks; the configuration screens in TIA Portal are identical.

How do I know whether the KLEFR 6934 register address is 0-based or 1-based?

Try reading address 1 with FC03. If the meter returns register 0, the device uses 0-based addressing. If it returns an illegal-data-address exception (0x02), the device is 1-based and you must add 1 to the address shown in the KLEFR documentation. The KLEFR 6934 user manual and the meter's firmware version determine the convention.

Why do my floating-point values come out as garbage numbers like -1.7E+38?

The KLEFR 6934 transmits floats in ABCD (big-endian) byte order, while the S7-1500 stores REAL in DCBA (little-endian). Insert a 16-bit byte swap on each of the two incoming words and reassemble the 32-bit value as a DWORD before casting to REAL. The exact code is shown in the float conversion section above.

Can I poll multiple KLEFR meters from the same CM PtP port?

Yes. RS-485 supports up to 32 unit loads on a single bus (the KLEFR 6934 is one unit load). Configure each meter with a unique Modbus slave address between 1 and 247, and run one MB_MASTER instance per meter. Trigger each instance from a state machine with a 50 to 100 ms inter-frame delay to avoid overlapping requests on the same port.

What is the maximum number of registers I can read in a single FC03 request?

The Modbus specification caps the read-holding-registers request at 125 words (250 bytes). The KLEFR 6934 typically supports up to 32 words per request, but the exact limit is in the device manual. The example above uses 32-word reads (16 floats) to stay well below both limits.

My poll works in the lab but fails in the cabinet. What should I check first?

Check (1) bus termination (120 ohm at both ends, none in the middle), (2) cable shield grounded at one end only, (3) baud and parity match the meter DIP switch, (4) A/B polarity is consistent across the bus, and (5) the cable is routed at least 20 cm away from VFD power cables and contactor coils. Add a ferrite core on the bus cable if the error count rises when large loads switch on.

Back to blog