Problem Overview
An S7-1200 PLC is configured as a Profibus DP master to a Bosch Rexroth HACD-2 servo drive. The drive expects each parameter word to arrive on the Profibus wire as a 16-bit hexadecimal pattern; the controller does not decode ASCII, it decodes bits. The original symptom was a clean mismatch between the HMI setpoint and the drive's reported engineering value: entering 327670 decimal into the source tag produced a nonsensical value on the drive, while entering 0x0004FFF6 directly produced the correct engineering value of 1000. The formula used by the application was:
(desired_value - offset) * scale = raw_value
(1000 - 0) * 327.67 = 327670 = 0x0004FFF6
The fundamental rule that resolves the issue is that the bit pattern transmitted on Profibus DP is what the drive interprets. Whether the PLC engineer writes the value as 327670 decimal or as 0x0004FFF6 hex is irrelevant from the wire's perspective; both produce identical bytes. The bug was located upstream of the wire, in the MOVE block where a WORD source was feeding an INT destination. This article documents the root cause, the Siemens CONV and HTA/ATH instructions used to fix it, the data-type sizing rules that prevent recurrence, and the commissioning workflow that confirms the fix on a live Profibus DP segment.
Root Cause: MOVE Block Data Type Width and Signedness Mismatch
The Siemens TIA Portal compiler accepts a MOVE block where the input is a WORD (16-bit unsigned) and the output is an INT (16-bit signed). The compiler does not flag the mismatch because both operands occupy 16 bits; both pass the IEC 61131-3 width check. At runtime, bit 15 of the WORD value is interpreted as the sign bit of the INT. A value such as 0xFFF6 (65526 decimal) becomes -10 when cast as INT, which is exactly the "obscure number" reported in the original problem. The pattern repeats for any value where bit 15 is set: 0x8000..0xFFFF appears as -32768..-1.
The fix is to keep bit width and signedness consistent across the entire MOVE chain. Three legal combinations are shown below.
| Source Tag | Source Type | Width | Target Tag | Target Type | Width | Status |
|---|---|---|---|---|---|---|
| Scale_Result | INT | 16-bit | Output_Word | WORD | 16-bit | Compile passes, runtime sign-flip on bit 15 |
| Scale_Result | DINT | 32-bit | Output_DWord | DWORD | 32-bit | Compile passes, runtime correct |
| Scale_Result | REAL | 32-bit | Output_DWord | DWORD | 32-bit | Compile passes after explicit CONV, runtime correct |
| Scale_Result | WORD | 16-bit | Output_DWord | DWORD | 32-bit | Compile passes, runtime zero-extended |
S7-1200 Data Types Relevant to Profibus DP Hex Payloads
Selecting the right data type is the foundation of correct hex payload transmission. The S7-1200 supports the IEC 61131-3 elementary types listed below; only a subset are commonly used in Profibus DP payload mapping.
| Type | Width (Bits) | Range | Signed | Typical Use Case |
|---|---|---|---|---|
| BOOL | 1 | 0..1 | No | Discrete I/O bit, Profibus DP status word bit |
| BYTE | 8 | 0..255 | No | Byte-level Profibus slot, single ASCII character |
| WORD | 16 | 0..65535 | No | Unsigned 16-bit Profibus parameter word |
| INT | 16 | -32768..32767 | Yes | Signed 16-bit scaled parameter |
| DINT | 32 | -2147483648..2147483647 | Yes | Large scaled value, 32-bit Profibus parameter |
| DWORD | 32 | 0..4294967295 | No | Unsigned 32-bit hex payload, bit pattern container |
| REAL | 32 | ~±3.4E38 (7 decimal digits) | Yes | Intermediate scaling math, HMI input |
| LREAL | 64 | ~±1.7E308 (15 decimal digits) | Yes | High-precision scaling on S7-1500; not available on S7-1200 |
| CHAR | 8 | ASCII 0..255 | N/A | Single ASCII character inside STRING |
| STRING[n] | n*8 + overhead | ASCII string of length n | N/A | Hex string for HMI display via HTA |
The example value 327670 decimal equals 0x0004FFF6, a 20-bit unsigned pattern. It cannot fit in INT or WORD (both 16-bit, max 65535) and requires DINT or DWORD. If the Profibus DP parameter slot is 16 bits wide per the GSD file, the upper 4 bits of 0x0004FFF6 are either discarded, packed into the adjacent slot, or the scale factor must be reduced so the maximum scaled value fits in 16 bits. If the slot is 32 bits wide, the full DWORD transmits intact. Always verify the slot width in the GSD file before sizing the variable.
The CONV (Convert Value) Instruction
The CONV instruction in the S7-1200 basic instructions set converts any elementary data type to any other elementary data type. In LAD/FBD the source operand IN appears at the top of the block and the destination OUT at the bottom; a dropdown selector picks the target type explicitly. In SCL the equivalent form is out := _TO_(in);.
| Source (IN) | Destination (OUT) | Result Behaviour | Notes |
|---|---|---|---|
| INT | DINT | -32768..32767 sign-extended to 32 bits | Default path for scaled math that may exceed 16 bits |
| DINT | WORD | Lower 16 bits only; upper 16 bits discarded | Risk of silent truncation if value > 65535 |
| DINT | DWORD | Bit pattern preserved, sign bit becomes data bit | Correct hex payload for unsigned Profibus slot |
| REAL | DINT | Truncates fractional part toward zero | Use TRUNC for explicit semantics; ROUND for nearest |
| REAL | INT | Truncates; may overflow if out of range | Route through DINT instead to detect overflow |
| BYTE | INT | 0..255 zero-extended to 16 bits | Useful for parsing single hex character nibbles |
| WORD | INT | Bit pattern preserved when bit 15 = 0; negative when bit 15 = 1 | The exact conversion that triggered the original bug |
| DWORD | REAL | Bit-cast reinterpretation of IEEE 754 | Use only for actual float bit patterns |
| BOOL | BYTE | 0 -> 16#00, 1 -> 16#01 | For byte-packed boolean arrays on Profibus |
Reference: CONV (Convert value) instruction — SIMATIC S7-1200 manual collection.
The HTA and ATH Instructions for Hex String I/O
When the Profibus DP slave accepts or returns hex characters through a STRING port (common on Rexroth IndraDrive parameter channels and on third-party SCADA bridges), the HTA and ATH extended instructions convert between ASCII hex strings and numeric values.
- HTA (Hexadecimal to ASCII): Reads a numeric input (BYTE, WORD, DWORD) and writes a STRING where each nibble is represented by a hex character ('0'..'9', 'A'..'F'). For example, input DWORD 16#0004FFF6 with N = 5 emits the string "4FFF6".
- ATH (ASCII to Hexadecimal): Reads an input STRING of hex characters and writes the numeric value to a WORD or DWORD. For example, input STRING '4FFF6' with N = 5 writes DWORD 16#0004FFF6.
The N input pin defines how many hex digits (1..8) are processed. For a 16-bit Profibus parameter (4 hex digits), set N = 4. For the 20-bit value 0x04FFF6, set N = 5 and route through a DWORD. For a full 32-bit hex payload, set N = 8.
Reference: ATH and HTA — SIMATIC S7-1200 manual collection.
Applying the Rexroth HACD-2 Scaling Formula
The communication formula supplied by Rexroth for the HACD-2 parameter channel is:
(desired_value - offset) * scale = raw_value
Worked example with desired_value = 1000, offset = 0, scale = 327.67:
(1000 - 0) * 327.67 = 327670
327670 decimal = 0x0004FFF6
The raw value 327670 is the bit pattern that the drive interprets as engineering value 1000. Writing 327670 directly into a 16-bit INT tag causes overflow (327670 > 32767); the high bits are clipped and the drive sees garbage. Writing 0x0004FFF6 into a 32-bit DWORD tag is the correct approach because the bit pattern matches what the drive expects on the wire. Both are equivalent in terms of the bytes transmitted; only the storage type differs.
The reverse conversion, performed inside the drive, divides the raw value by scale and adds the offset to recover the engineering value: 327670 / 327.67 = 1000. If the scale factor and offset are not symmetric between the PLC and the drive, the value at the drive will not match the value at the HMI. Confirm both ends of the formula against the parameter manual before commissioning.
Step-by-Step: Hex Conversion in TIA Portal for an S7-1200 to Profibus DP Slave
Prerequisites
- TIA Portal V15.1 or later (V18 or V19 recommended for full S7-1200 firmware 4.5+ support).
- S7-1200 CPU firmware V4.2 or higher (V4.4 or higher recommended for full HTA/ATH reliability on long STRING operands).
- Bosch Rexroth HACD-2 GSD file installed in the TIA Portal device catalog under "Other field devices → Profibus DP → Drives".
- CM 1243-5 Profibus DP master module (6GK7243-5DX30-0XE0) or a CPU 1214C / 1215C / 1217C with the integrated DP master port.
- IEC check enabled on every OB / FB / FC.
- Rexroth IndraWorks commissioning tool with parameter-channel access to the HACD-2.
Step 1 — Declare the Working Tags
In the PLC tag table or in the static section of the FB, declare the following tags. Using a dedicated FB (for example FB1200 "HACD2_Scale") isolates the conversion logic from the rest of the program and makes IEC check errors easier to diagnose.
VAR
rSetpoint : REAL := 0.0; // HMI input, e.g. 1000.0
rOffset : REAL := 0.0; // Engineering offset
rScale : REAL := 327.67; // Raw-units per engineering-unit
rScaled : REAL := 0.0; // (rSetpoint - rOffset) * rScale
diScaled : DINT := 0; // Truncated integer, e.g. 327670
dwHexPayload : DWORD := 16#0; // Bit pattern to Profibus slot
wLowWord : WORD := 16#0; // Low 16 bits of dwHexPayload
wHighWord : WORD := 16#0; // High 16 bits if 32-bit slot
sHexDisplay : STRING[6]; // '4FFF6' for HMI diagnostics
bOverflow : BOOL := FALSE; // Set when diScaled > 65535
END_VAR
Step 2 — Compute in REAL to Preserve Resolution
In the FB body, written in SCL, perform the scaling and the conversion. Use REAL arithmetic for the multiplication to avoid integer rounding during the scale step; only convert to integer at the end.
// Section 1 - Scaling
"rScaled" := ("rSetpoint" - "rOffset") * "rScale";
// Section 2 - Truncate to DINT (round toward zero, IEC 61131-3 standard)
"diScaled" := REAL_TO_DINT("rScaled");
// Section 3 - Overflow guard for 16-bit slots
IF ("diScaled" > 65535) OR ("diScaled" < 0) THEN
"bOverflow" := TRUE;
ELSE
"bOverflow" := FALSE;
END_IF;
// Section 4 - Convert to unsigned bit pattern
"dwHexPayload" := DINT_TO_DWORD("diScaled");
// Section 5 - Slice into 16-bit words (Profibus DP slots)
"wLowWord" := DWORD_TO_WORD("dwHexPayload");
"wHighWord" := DWORD_TO_WORD(SHR(IN := "dwHexPayload", N := 16));
The REAL intermediate ensures floating-point precision is preserved through the scaling (REAL on the S7-1200 has approximately 7 decimal digits of precision, sufficient for the 327.67 example). Converting directly from REAL to INT or WORD can lose precision due to rounding direction; routing through DINT first matches the IEC 61131-3 standard conversion semantics. The SHR (Shift Right) call extracts the upper 16 bits when the slave expects a 32-bit parameter spread across two 16-bit slots.
Step 3 — Map the Payload to the Profibus DP Process Image
In the device configuration, open the HACD-2 slot for the parameter channel. Right-click the output word slot and assign "wLowWord". If the parameter is defined as 16 bits in the GSD, the upper 4 bits of "dwHexPayload" are discarded; if the slave expects 32 bits, assign a DWORD slot with "dwHexPayload" instead, or assign "wLowWord" to the first slot and "wHighWord" to the second slot. Compile and download the hardware configuration.
Step 4 — Add an HTA Block for HMI Diagnostics
Drop an HTA instance on the same FB and wire it to the hex display string. This step is optional but extremely useful during commissioning.
// HTA block call
"HTA_DB"(
EN := TRUE,
IN := "dwHexPayload",
N := 5, // 5 hex digits for 0x4FFF6
OUT => "sHexDisplay"
);
The HMI can now display the actual bit pattern being transmitted. If the drive shows 1000 but the HMI shows '4FFF6', the wiring is correct. If the HMI shows '7FFE' while the drive shows -1, the sign-flip bug has reappeared somewhere.
Step 5 — Verify with the Drive Parameter Monitor
Place the drive in its parameter monitor mode (typically P-0-0085 on the HACD-2, accessed via IndraWorks). The drive should report the engineering value of 1000.0, not the raw 327670. The Profibus DP diagnostic buffer should show no "Slave not ready" or "Invalid parameter" entries.
Verification Checklist
| Item | Expected Result | Pass Criteria |
|---|---|---|
| TIA Portal compile | No warnings | Zero errors and zero warnings with IEC check on |
| Online watch — "diScaled" | 327670 for setpoint 1000 | Decimal value matches the formula |
| Online watch — "dwHexPayload" | 16#0004FFF6 | Hex literal matches the expected bit pattern |
| Online watch — "wLowWord" | 16#4FFF6 | Low 16 bits only |
| Online watch — "wHighWord" | 16#0000 | Upper 16 bits zero for a 20-bit value |
| Drive parameter monitor | Engineering value 1000 | Matches the HMI input |
| HMI hex display | '4FFF6' | 5-character string with uppercase hex |
| Profibus DP diagnostic buffer | No fault entries | Clean buffer, slave in "Data Exchange" state |
| Profibus DP trace tool | Bytes F6 FF 04 00 on the wire (LE) | Matches the configured byte order |
| Overflow flag | FALSE for setpoint 1000 | Only TRUE if scaled value exceeds 16-bit range |
Profibus DP Byte Order and Endianness
If the HACD-2 GSD defines a 32-bit parameter slot starting at byte offset 4, the S7-1200 transmits the DWORD "dwHexPayload" = 16#0004FFF6 in little-endian order (low byte first). The bytes on the wire are:
| Byte Offset | Byte Value (Hex) | Binary |
|---|---|---|
| 4 (low byte) | F6 | 11110110 |
| 5 | FF | 11111111 |
| 6 | 04 | 00000100 |
| 7 (high byte) | 00 | 00000000 |
If the drive expects big-endian (high byte first), use the SWAP_DWORD block or assemble manually with POKE_BLK. The Rexroth IndraDrive default is little-endian for Profibus DP process data, but parameter channels and serial-over-Profibus bridges may differ. Always consult the drive parameter manual for the exact mapping. A quick field check: write 16#12345678 to the slot, then read back the raw bytes from a Profibus DP trace. If the bytes appear as 78 56 34 12, the bus is little-endian; if they appear as 12 34 56 78, the bus is big-endian and a SWAP is required.
Common Pitfalls and Field Notes
- Implicit signedness flip. TIA Portal does not warn when moving a WORD to an INT. Always inspect the "Type" column in the tag table and the block interface. The fix is either to widen the variable to DINT/DWORD or to use CONV with the explicit same-signedness target.
- CONV rounding direction. CONV from REAL to INT truncates toward zero. For round-to-nearest, use ROUND before CONV. For round-toward-positive-infinity, use CEIL. For round-toward-negative-infinity, use FLOOR.
- ATH and HTA require declared STRING length. A STRING[4] cannot hold "4FFF6"; declare STRING[6] or larger. The +1 byte is for the implicit length byte managed by the STRING type.
- Profibus DP cycle time. If the parameter is in a high-priority slot, every PLC scan recomputes and transmits. For non-critical setpoints, place the write in a slower cyclic OB such as OB35 at 100 ms, or in OB1 guarded by a clock-bit pulse.
- HACD-2 scaling formula uses (desired − offset) * scale. If offset is non-zero, subtract it before multiplying. Using unsigned arithmetic on the scaled value can introduce a sign error when the scaled result crosses 32767.
- S7-1200 firmware version. Some older firmware versions (V4.0 and below) do not support all extended string instructions or have reduced STRING handling performance. Verify firmware ≥ V4.2 on the device identification page before relying on HTA/ATH for production code.
- GSD slot consistency. If you change the parameter slot length in the GSD (e.g. 16 → 32 bits), the entire slot map shifts. Recompile the hardware configuration and re-check adjacent parameters for offset errors.
- IEC check interacts with multi-instance DBs. If a multi-instance FB declares parameters with mixed signedness (for example, an INT input feeding a WORD output via a multi-instance call), IEC check flags it. Resolve by changing the parameter type or by inserting an explicit CONV.
- Watchdog reset on Profibus DP failure. If the slave drops out of "Data Exchange", the input process image freezes at the last value. Add an OB82 / OB86 error handler to detect the dropout and write a safe default (typically 0) to the drive slot.
- HTA output case. The HTA block emits uppercase hex characters by default. If your HMI expects lowercase, post-process the STRING or use the lower-case variant attribute if available in your firmware version.
Troubleshooting Matrix
| Symptom | Likely Cause | Corrective Action |
|---|---|---|
| Drive shows mirrored sign value (e.g. -10 instead of 65526) | WORD → INT MOVE without CONV | Change both sides to the same signedness or route via DWORD |
| Drive shows 0 or 32767 for every setpoint | INT overflow during scaling | Route through DINT or scale the input down |
| HMI shows correct decimal but drive shows wrong engineering value | Profibus DP byte-order assumption wrong | Swap bytes with the SWAP_DWORD block or with POKE_BLK |
| HTA output shows fewer digits than expected | N pin set too low | Set N to match the bit width (4 for 16-bit, 8 for 32-bit) |
| Compile warning "Conversion from REAL to INT loses precision" | Direct REAL → INT without TRUNC | Insert TRUNC or ROUND before CONV |
| Drive accepts hex literal but rejects scaled result | Drive expects fixed-point Q-format | Multiply by 32767 (Q15) instead of the generic scale |
| Profibus DP slave drops to "Not Ready" after write | Invalid parameter length or address | Verify slot length against the GSD file |
| HMI displays lowercase hex '4fff6' instead of '4FFF6' | ATH/HTA output not uppercased | Verify the HTA block is set to emit uppercase hex |
| ATH returns 0 even though input STRING is correct | N pin set higher than the STRING length | Set N ≤ LEN(input STRING) |
| Drive shows engineering value but PLC shows wrong raw value | Scale factor mismatch between PLC and drive | Verify scale and offset on both ends against the parameter manual |
| Compile error "Type mismatch in MOVE block" after enabling IEC check | Implicit WORD ↔ INT conversion | Insert explicit CONV block or change types to match |
| Drive value oscillates between two values | Two OBs writing the same Profibus slot | Identify the duplicate write and remove it |
| HMI hex display is empty | STRING length too small for the HTA output | Increase STRING length to N + 1 or larger |
Commissioning Tools and Wire-Level Verification
For proof beyond online watch tables, capture the actual bytes on the Profibus DP wire and compare them against the expected hex pattern. The following tools are commonly used:
- Siemens PROFINET / Profibus analyzer: Integrated into TIA Portal under "Online → Diagnostics → Profibus DP Trace". Captures a configurable number of cycles and decodes each slot.
- Softing PROFIusb: External USB Profibus DP analyzer with a Windows trace tool. Captures raw bytes per slot per cycle. Useful for verifying byte order.
- Siemens SIMATIC Automation Tool: Reads the S7-1200 process image from the PLC side and compares against expected values without needing an online connection to TIA Portal.
- Rexroth IndraWorks: The drive-side commissioning tool. Read parameter P-0-0085 to confirm the engineering value, and read the parameter channel echo to confirm the raw value the drive received.
A typical commissioning flow: (1) set the HMI setpoint to 0 and verify the wire bytes are zero; (2) set the HMI setpoint to mid-scale (for example 500) and verify the wire bytes match 16#00027F...; (3) set the HMI setpoint to full-scale and verify the wire bytes match the maximum raw value; (4) read the engineering value from the drive parameter monitor and confirm it matches the HMI setpoint at all three points.
Safety and Pre-Commissioning Checklist
- Always run a Profibus DP diagnostic buffer check (Online → Diagnostics → Profibus DP) before energizing the drive.
- For initial commissioning, set the drive to "parameter write disabled" and verify read-only echoes first. This prevents the drive from acting on a corrupt value during debug.
- Use a Profibus DP trace tool to capture the wire bytes and compare against the expected hex pattern.
- Keep IEC check enabled in all blocks; this prevents the WORD/INT mismatch described in the original problem.
- Validate the HMI scaling against the drive's parameter monitor at zero, mid-scale, and full-scale setpoints to catch non-linearities.
- Wire an OB82 / OB86 error handler so the PLC defaults the output slot to a safe value when the slave drops out of "Data Exchange".
- Document the scale factor, offset, and bit-width for every parameter in a parameter sheet. The HACD-2 manual typically provides the formula; record the matching PLC-side formula in the same sheet.
- Lock the firmware version of the S7-1200 in the project to prevent an automatic firmware update from changing the CONV or HTA behaviour.
FAQ
Why does my Profibus DP slave show the wrong value when I write a decimal number directly?
The slave interprets the bit pattern of the value, not its decimal representation. A 16-bit signed INT value such as 0xFFF6 is 65526 decimal as a WORD but -10 as a signed INT. Either route through a DWORD to keep the bit pattern intact, or convert with CONV to the same signedness as the slave expects. Always check the slave's GSD file for the expected data width and signedness.
What is the difference between the CONV instruction and the HTA / ATH instructions?
CONV converts between numeric data types (for example, INT → DINT or REAL → DWORD). HTA and ATH convert between numeric values and ASCII hex character strings (for example, DWORD 16#4FFF6 ↔ STRING '4FFF6'). Use CONV for bit-pattern-level Profibus DP writes; use HTA / ATH for HMI displays or for serial bridges that accept hex strings.
How do I convert 327670 decimal to hexadecimal in TIA Portal?
Store the value as a DINT, then convert to DWORD using DINT_TO_DWORD, then watch the tag online in hex display mode — it will show 16#0004FFF6. Use the CONV instruction block if you need to write the result to another tag, or the HTA instruction with N = 5 if you need a STRING output for the HMI.
What does enabling IEC check actually do in TIA Portal?
IEC check enforces strict type compatibility on block parameter assignments. With IEC check on, the compiler rejects implicit conversions between signed and unsigned types of the same width (for example, INT ↔ WORD), between types of different widths (for example, BYTE → INT without explicit CONV), and between bit-string and numeric types. This is the single most effective setting for preventing the WORD-to-INT sign-flip bug.
Which S7-1200 firmware version supports HTA and ATH reliably?
HTA and ATH are available from firmware V4.0 of the S7-1200 CPU, but full reliability on long STRING operands is best on firmware V4.2 or higher. Check the device identification in TIA Portal (Online → Accessible devices) and update the firmware if necessary before relying on these extended string instructions for production code.
Can I use the same approach on an S7-1500 or ET 200SP CPU?
Yes. The CONV, HTA, and ATH instructions are present in the S7-1500 basic and extended instruction sets with identical semantics. On the S7-1500 you also have access to LREAL (64-bit floating point) and the additional conversion blocks in the "Conversion operations" folder of the TIA Portal instruction tree. The IEC check behaviour is the same.