Configuring S7-1200 CM 1241 RS485 for ESC/POS Thermal Printing

David Krause15 min read
S7-1200SiemensTutorial / 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

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
Compatibility note: The CM 1241 RS232 module (6ES7 241-1AH32-0XB0) can be used when the printer exposes a true RS-232 DB9. The RS422/485 variant is selected when the field wiring is long (>15 m), runs through a noisy plant, or terminates on a 2-wire industrial bus.

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.

  1. 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).
  2. 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.
  3. Add a tag of type STRING[254] (maximum 254 characters plus 2-byte header) and an additional tag of type ARRAY[0..253] of BYTE. The SEND_PTP LEN parameter is set to the number of bytes to transmit.
Common pitfall: If the DB is created with optimized access, SEND_PTP returns STATUS = 16#80C4 (parameter assignment error) or 16#80B0 (no valid data block). The fix is to disable the optimized-access flag, recompile, and download the new block. This is the root cause of many "text prints but no command executes" symptoms.

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.

RS-232 cable to printer: The DB9 pinout on the converter is DCE. Use a straight-through DB9 M-F cable (not a null modem) between the OM-CONV-SER and the printer's RS-232 DB9. Crossed (null-modem) cables are not required because both ends behave as DTE/DCE in opposite roles.

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:

  1. 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.
  2. 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).

Symptom: If the printer prints the ASCII line but never responds to the line feed or cut command, XON/XOFF is mismatched. The printer is holding the rest of the buffer in its serial FIFO waiting for an XOFF to clear. Disable XON/XOFF on both sides and retest.

10. Step-by-Step Commissioning Procedure

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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

  1. Open TIA Portal and go online with the CPU. Force the SEND_PTP REQ bit manually with a watch table.
  2. 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.
  3. 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.
  4. Use the TIA Portal hardware and network printing documentation to print the device configuration for the as-built record.
  5. 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.

Back to blog