1. Overview
Printing process data from a Siemens SIMATIC S7-1200 CPU to a serial thermal receipt printer is a common requirement in machine building, food processing, laboratory data logging, and field instrumentation. The typical pattern is: a CM 1241 RS422/485 communications module (order number 6ES7 241-1CH32-0XB0) is plugged to the left of the CPU, ESC/POS command frames are built in a data block, and the S7-1200 point-to-point instruction SEND_PTP (FB 9) transmits the buffer to the printer over RS-485 or through an RS-485 to RS-232 converter when the printer only exposes DB9 RS-232.
This reference explains how to configure the hardware, build an ESC/POS command buffer, satisfy the Siemens support entry 42002283 requirement for a non-optimized (non-symbolic) data block, and verify the link end-to-end. The approach is suitable for the SP-RMDIIID-class thermal printers and any other device that implements the Epson ESC/POS command set over a serial UART.
2. Hardware Stack and Part Numbers
The minimum S7-1200 print stack consists of the components in the table below. Order numbers are Siemens catalog numbers and should be sourced from the SIMATIC price list or your local Siemens distributor.
| Component | Order Number (MLFB) | Role |
|---|---|---|
| CPU 1214C DC/DC/DC (or similar) | 6ES7 214-1AG40-0XB0 | PLC processor, executes SEND_PTP |
| CM 1241 RS422/485 | 6ES7 241-1CH32-0XB0 | Serial interface module, RS-485 half/full-duplex |
| Thermal printer (ESC/POS) | SP-RMDIIID or equivalent | Prints ASCII and ESC/POS command buffers |
| RS-485 to RS-232 converter | OM-CONV-SER (or equivalent) | Adapts 2-wire RS-485 to printer DB9 RS-232 |
| S7-1200 firmware | V4.0 or later (V4.5+ recommended) | Required for SEND_PTP with STRING buffer support |
| TIA Portal STEP 7 | V13 SP1 minimum, V16/V17/V18 preferred | Configuration and programming environment |
3. CM 1241 RS422/485 Port Configuration
Open the device configuration of the CM 1241 in TIA Portal. The module's Properties > Port Configuration dialog exposes the parameters listed below. Every parameter must match the printer's UART settings exactly or characters will be dropped, garbled, or silently ignored.
| Parameter | Typical Value for ESC/POS | Notes |
|---|---|---|
| Baud rate | 9600 / 19200 / 38400 / 115200 | 9600 is the printer default for most ESC/POS units; 115200 is supported by SP-RMDIIID at its high-speed mode |
| Parity | None | ESC/POS printers use 8N1 |
| Data bits | 8 | Required for ASCII printing |
| Stop bits | 1 | Rarely 2; check printer manual |
| Flow control | XON/XOFF or none | RS-485 2-wire mode cannot use RTS/CTS; software handshake only |
| Line idle state | Mark (1) | RS-485 fail-safe bias typical |
| Termination | Enabled at end of segment | CM 1241 has internal 390 Ω pull-up / 220 Ω pull-down + 120 Ω between T/R |
| Half/Full duplex | Half-duplex (2-wire) for RS-485 | Full-duplex (4-wire) only for RS-422 printers |
The CM 1241 has an internal 120 Ω termination resistor and fail-safe bias that can be enabled in the port configuration. On a point-to-point link to a single printer, leave the termination enabled on the CM and disable it on the printer side (most thermal printers do not expose a termination switch on the RS-485 pins).
4. The Non-Optimized (Non-Symbolic) Data Block
The Siemens support entry 42002283 - How do you compensate for the string mismatch caused by the RCV_PTP and SEND_PTP blocks? documents a long-standing constraint: SEND_PTP and RCV_PTP require a data block with standard (non-optimized) access. In TIA Portal this is also called a "non-symbolic" block because the tag names are not downloaded to the PLC, only the absolute byte addresses are used.
- In the project tree, add a new DB block. Open its properties and clear the Optimized block access checkbox (or in older releases, clear Symbolic access only).
- Compile the project. The DB will now expose its offsets instead of symbolic names and is the only type of block that the legacy SEND_PTP / RCV_PTP FBs accept for STRING and ARRAY of BYTE parameters.
- Add a tag of type
STRING[254](maximum 254 characters plus 2-byte header) and an additional tag of typeARRAY[0..253] of BYTE. The SEND_PTP LEN parameter is set to the number of bytes to transmit.
5. ESC/POS Command Reference for Print Layouts
ESC/POS is a binary command set defined by Epson. Every command is a single byte or a multi-byte sequence starting with 0x1B (ESC), 0x1F (FS), or 0x1D (GS). For printing log data from a PLC, only a small subset is required.
| Function | Hex Sequence | ASCII / Decoded | Purpose |
|---|---|---|---|
| Line feed | 0x0A | LF | Advance paper one line |
| Carriage return | 0x0D | CR | Return to start of line (Windows line ending: CR+LF) |
| Horizontal tab | 0x09 | HT | Move to next tab stop (typically every 8 columns) |
| Initialize printer | 1B 40 | ESC @ | Reset to power-on defaults; clear buffers |
| Bold ON | 1B 45 01 | ESC E 0x01 | Enable bold printing |
| Bold OFF | 1B 45 00 | ESC E 0x00 | Disable bold |
| Underline ON | 1B 2D 01 | ESC - 0x01 | Enable underline |
| Underline OFF | 1B 2D 00 | ESC - 0x00 | Disable underline |
| Select character size | 1D 21 n | GS ! n | n = height/width nibble, 0x00 normal to 0x77 double w/double h |
| Align left/center/right | 1B 61 n | ESC a n | n=0 left, 1 center, 2 right |
| Cut paper (full) | 1D 56 00 | GS V 0x00 | Full cut (auto-cutter models only) |
| Cut paper (partial) | 1D 56 01 | GS V 0x01 | Partial cut |
| Print and feed n lines | 1B 64 n | ESC d n | Feed n lines after the buffer |
All multi-byte values in ESC/POS are little-endian. For example, to set the character height to 2x and width to 1x, the parameter byte is n = 0x10 (height 2, width 1) so the sequence is 1D 21 10.
6. Building the Send Buffer in the S7-1200
The cleanest way to assemble an ESC/POS frame in a non-optimized DB is to predefine the byte array at compile time, then overwrite the dynamic fields (temperature value, timestamp) at runtime before each transmission. The example below shows the pattern in Structured Text (SCL) in TIA Portal V17.
// DB "PrintBuffer" - non-optimized, standard access
// Offset 0.0 : ARRAY[0..253] of BYTE "Frame"
// Offset 256.0: STRING[254] "AsciiLine"
// Pre-built frame = initialize, center, double-size, ASCII, line feed
// 1B 40 | 1B 61 01 | 1D 21 10 | ... 54 45 4D 50 3D ... 0A
#Frame[0] := 16#1B; // ESC
#Frame[1] := 16#40; // @ -> initialize
#Frame[2] := 16#1B; // ESC
#Frame[3] := 16#61; // a -> align
#Frame[4] := 16#01; // -> center
#Frame[5] := 16#1D; // GS
#Frame[6] := 16#21; // ! -> character size
#Frame[7] := 16#10; // -> 2x height, 1x width
#Frame[8] := 16#54; // T
#Frame[9] := 16#45; // E
#Frame[10] := 16#4D; // M
#Frame[11] := 16#50; // P
#Frame[12] := 16#3D; // =
// "TEMP=" is 5 bytes, then a 6-character numeric value
#Frame[13] := 16#20; // space
#Frame[14] := 16#20; // space
#Frame[15] := 16#20; // space
#Frame[16] := 16#20; // space
#Frame[17] := 16#0A; // LF -> advance paper
#Frame[18] := 16#1B; // ESC
#Frame[19] := 16#40; // @ -> reset size for next line
#Len := 20;
To build the temperature field, use VAL_STRING or convert the REAL temperature to a STRING in a separate DB tag, then copy character by character into the array. The same array can be reused as an input to the SEND_PTP instruction via the BUFFER parameter with the POINTER or VARIANT type (V14+ of TIA Portal).
7. SEND_PTP Instruction Usage
The SEND_PTP instruction is in Instructions > Communication > Point-to-Point > SEND_PTP. In TIA Portal V16+ it is the integrated S7-1200 PtP block, identical in signature to the legacy FB 9. The I/O pinout is shown below.
| Parameter | Direction | Type | Description |
|---|---|---|---|
| REQ | IN | BOOL | Rising edge starts the transmission |
| PORT | IN | PORT | Symbolic name of the CM 1241 configuration |
| BUFFER | IN | VARIANT | Pointer to the data to send (STRING, ARRAY of BYTE, or DB tag) |
| LEN | OUT | INT | Number of bytes actually transmitted |
| DONE | OUT | BOOL | TRUE for one cycle on successful completion |
| ERROR | OUT | BOOL | TRUE for one cycle on error |
| STATUS | OUT | WORD | Status / error code (see Section 10) |
Example call in SCL:
IF "Trigger_30s" THEN
"SEND_PTP_DB".REQ := TRUE; // implicit via edge in CALL
END_IF;
"SEND_PTP_DB"(REQ := "Trigger_30s",
PORT := "CM1241_RS485",
BUFFER := "PrintBuffer".Frame,
LEN => "PrintBuffer".LenOut,
DONE => "PrintBuffer".Done,
ERROR => "PrintBuffer".Error,
STATUS => "PrintBuffer".Status);
8. Wiring: RS-485 to RS-232 Conversion
The CM 1241 RS422/485 ships with a removable 6-pin terminal block. For half-duplex RS-485 (2-wire), the standard pinout is shown in the table. Use shielded twisted pair (e.g., Belden 3106A) with the shield grounded at one end only.
| CM 1241 Terminal | Signal | OM-CONV-SER RS-485 DB9F | Wire Color (typical) |
|---|---|---|---|
| Pin 1 (T/R-) | RS-485 B / - | Pin 2 (RS-485-) | White/blue pair |
| Pin 2 (T/R+) | RS-485 A / + | Pin 7 (RS-485+) | Blue/white pair |
| Pin 3 (GND) | Signal ground | Pin 5 (GND) | Shield drain |
| Pin 4 (NC) | Not used | — | — |
The OM-CONV-SER is a passive RS-485 half-duplex to RS-232 converter powered from the DTR/RTS lines of the host. It does not require an external 24 V supply. Maximum specified distance is 1200 m on the RS-485 side and 5 m on the RS-232 side, which is the inverse of the typical application: the PLC is in the cabinet and the printer is mounted on the machine.
9. Handshake Configuration (XON/XOFF vs RTS/CTS)
The SP-RMDIIID and most ESC/POS thermal printers default to XON/XOFF software flow control (DC1 = 0x11, DC3 = 0x13). RS-485 in 2-wire mode cannot carry hardware handshake lines, so the PLC cannot physically assert RTS/CTS. There are only two valid configurations:
- CM 1241: XON/XOFF enabled, RS-485 2-wire, printer: XON/XOFF enabled. The CM 1241 will transmit XOFF (0x13) if its internal 1024-byte buffer approaches full and resume with XON (0x11). The printer respects these by pausing transmission.
- CM 1241: no flow control, RS-485 2-wire, printer: flow control disabled (set ESC = 27 61 0xFF or DIP switch). Use this for short frames (< 200 bytes) sent at 30-second intervals, which is the typical logging application.
For option 1, ensure the printer's ESC/POS command to disable/enable XON/XOFF is sent on first connection. The command is ESC = n where n = 0x01 enables XON/XOFF and n = 0x02 disables it (per the Epson TM-T20 reference; check the SP-RMDIIID manual for the exact parameter).
10. Step-by-Step Commissioning Procedure
- Wire the link. Connect the CM 1241 RS-485 terminals to the OM-CONV-SER per Section 8. Power up the converter (DTR/RTS) by either asserting these signals from a PC or by leaving the converter's USB host side attached to a service laptop.
-
Verify with a PC loopback. Disconnect the printer, attach a USB-to-RS-232 adapter to the OM-CONV-SER, and run Hercules SETUP utility on the PC at 9600 8N1 XON/XOFF. Send
1B 40 1B 61 01 54 45 53 54 0A(initialize, center, "TEST", LF) and confirm the CM 1241 has the same parameters in the port configuration. If Hercules shows the bytes back (with local echo on), the PLC is transmitting correctly. - Verify with the printer directly. Connect Hercules directly to the printer DB9 at the same settings and send the same frame. If the printer cuts and prints "TEST", the printer is healthy and the issue is the link in step 1 only.
- Reconnect PLC to printer. Re-attach the OM-CONV-SER on the printer side. Power-cycle the printer. In TIA Portal, go online with the S7-1200 and monitor the SEND_PTP STATUS word.
- Build the production frame. Implement the buffer construction in SCL as in Section 6. Trigger SEND_PTP every 30 s from a cyclic OB or from a TON timer.
- Monitor and log. Watch DONE / ERROR / STATUS. STATUS = 16#0000 indicates a clean send. A non-zero value should be decoded per the SEND_PTP error table in the next section.
11. SEND_PTP Status Codes and Troubleshooting Matrix
| STATUS (hex) | Meaning | Likely Cause | Remedy |
|---|---|---|---|
| 16#0000 | Send complete, no error | Normal operation | None |
| 16#7000 | No send active, ready | REQ is low | Trigger REQ with rising edge |
| 16#80C0 | Hardware fault on interface | Wrong port ID, CM not online | Check device configuration and module status LEDs |
| 16#80C1 | Parameter assignment error | PORT not configured or DB optimized | Recompile hardware config; switch DB to standard access |
| 16#80C2 | Configuration error in DB | LEN > buffer size, BUFFER pointing to optimized data | Check BUFFER pointer and LEN |
| 16#80C3 | BUFFER pointer invalid | AnyTag points to a local variable in a non-static block | Use global DB tag |
| 16#80C4 | Data block does not exist or is symbolic-only | DB created with optimized access | Disable Optimized block access, recompile, re-download |
| 16#80B0 | No valid DB; data lost | SEND_PTP called in startup OB or wrong instance DB | Call from OB 1 or a cyclic OB; assign correct instance DB |
| 16#8188 | Receiver did not acknowledge within timeout | Printer off, XON/XOFF mismatch, baud mismatch | Check power, parity, baud; try no flow control |
| 16#80D0 / 16#80D1 | Hardware overrun / parity error | Baud, parity or stop-bit mismatch | Re-check CM and printer parameters |
Some symptoms map to multiple root causes. Use the matrix above together with the CM 1241 diagnostic LEDs: TXD flashes once per byte sent, RXD flashes on every byte received. If TXD is silent when SEND_PTP is triggered, the call never reached the port (check DONE / ERROR / STATUS) - typically STATUS = 16#80C4 due to a symbolic DB.
12. Diagnostic Loop: Verifying a Live Print Job
- Open TIA Portal and go online with the CPU. Force the SEND_PTP REQ bit manually with a watch table.
- Open the watch table and observe the DONE bit transition to TRUE for one scan, then back to FALSE. If DONE never rises, read STATUS.
- Use a TIA Portal Trace (CPU 1214C and above) to record the buffer contents before and after SEND_PTP. This proves the SCL code is building the frame as expected.
- Use the TIA Portal hardware and network printing documentation to print the device configuration for the as-built record.
- If the printer prints but cuts at the wrong position, adjust the line-feed count (ESC d n) and confirm the paper feed lever is closed. SP-RMDIIID units have a manual feed lever that adds extra blank lines when open.
13. Common ESC/POS Field Recipes
| Recipe | Hex Sequence | Effect |
|---|---|---|
| Receipt header (centered, double size, bold) | 1B 40 1B 61 01 1B 45 01 1D 21 11 ... 0A 1B 45 00 1D 21 00 | Initialize, center, bold + 2x size, line of text, restore normal |
| Time stamp with normal text | 1B 61 00 ... 0A | Left align, normal text, line feed |
| Two-column line (24 chars) | ... 09 ... 0A | Left string + HT + right string + LF (relies on tab stops) |
| Footer with partial cut | ... 0A 1D 56 01 | Line, then partial cut |
14. Performance and Timing Considerations
At 9600 baud, a 30-byte frame takes roughly 31 ms to transmit (10 bits per character including start/stop). At 115200 baud the same frame takes about 2.6 ms. For a 30-second log interval the difference is irrelevant. For higher-rate printing (for example, a label printer at one line per second), raise the baud rate and ensure the printer buffer is large enough to absorb the throughput.
The CM 1241 has a 1024-byte transmit FIFO. If the application program triggers SEND_PTP faster than the physical line, the instruction blocks internally until buffer space is available - it does not return an error or lose data. The DONE bit is delayed accordingly.
Why does my S7-1200 send ASCII text to the printer but ignore ESC/POS commands like line feed and cut?
The data block holding the buffer must have Optimized block access disabled (non-symbolic) per Siemens support entry 42002283. Recreate the DB, clear the optimized-access checkbox, recompile, and re-download. The same root cause also explains why bold, alignment, and cut commands have no effect while printable characters do.
Can I use RTS/CTS hardware flow control on the CM 1241 RS422/485 module with a thermal printer?
No, not in RS-485 2-wire (half-duplex) mode, because RS-485 has only two signal wires (T/R+ and T/R-) and no RTS/CTS pins. Either use the full-duplex RS-422 mode (4-wire) with a printer that supports hardware handshake, or use software flow control (XON/XOFF), or disable flow control on both sides for short frames. The SP-RMDIIID supports XON/XOFF and a no-handshake mode via its internal configuration.
Which baud rate should I select for an SP-RMDIIID thermal printer from an S7-1200?
9600 8N1 is the safe default that all ESC/POS printers support. The SP-RMDIIID also supports 19200, 38400, 57600, and 115200 baud. Always match the parameter exactly on the CM 1241 port configuration and on the printer's DIP switches or software configuration. Mismatched baud rates are the most common cause of garbled output (mojibake).
How do I build an ESC/POS command buffer that mixes ASCII text and control bytes in a non-optimized DB?
Declare an ARRAY[0..253] of BYTE in a standard (non-optimized) DB and assign each byte as a hex literal (16#1B, 16#0A, etc.). Use SCL or LAD to populate the array at runtime, then pass it as the BUFFER parameter of SEND_PTP with the byte count in LEN. For dynamic numeric data, convert the REAL/INT to a STRING with VAL_STRING, copy the characters into the array, and append the line feed and cut bytes.
How do I cut the receipt at the end of a print job from TIA Portal?
Append the partial-cut sequence 1D 56 01 (GS V 0x01) to the end of the buffer. For a full cut, use 1D 56 00. The printer must have an auto-cutter option installed. Always feed at least one line (0x0A) before the cut command so the cut occurs on the paper perforation, not on the printed line itself.