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.
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:
- Disconnect the ET200SP station power and the 24 V supply to the BaseUnit.
- 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.
- 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.
- 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.
- 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).
- Power up the station and observe the LEDs on the CM PtP: a green
PWRand a steady or slow-blinkingDIAGindicate the module is ready for cyclic operation.
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.
- Open the project and select the ET200SP station in the project tree.
- 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.
- 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.
- Set the Interface field to RS485 (half-duplex) and enable the internal termination if this module is the end of the bus.
- 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.
- 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:
- Call
MB_COMM_LOADin OB100 (startup OB) with a rising edge onREQ. Wait untilDONE=TRUEandERROR=FALSEbefore continuing. The block disables itself internally once the port is configured; further calls do nothing untilREQtoggles again. - Call
MB_MASTERin OB1. It must be called cyclically, but theREQinput should be pulsed with a rising edge to start each new transaction. IfBUSY=TRUE, do not trigger a new request on the same instance. - Evaluate
DONEandERRORon each cycle. OnERROR=TRUE, read theSTATUSword for the Modbus exception code (0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x90) or the CM PtP-specific error. - 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.
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
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.
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.
- LED verification: PWR solid green, DIAG solid green, RX/TX flickers yellow then green on each poll cycle.
-
Online STATUS monitoring: Force the
MB_MASTERinstance with the online watch table;STATUSmust read 0x0000 within one cycle ofDONE=TRUE. - 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.
- 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.
- 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.
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.