Reversing Drive Direction with a Digital Input in SIMATIC S7-300/400 LAD
1. Problem Definition
An existing SIMATIC S7-300/400 program uses a Set/Reset (SR) flip-flop to latch the direction command for a Variable Frequency Drive (VFD) or a contactor-controlled motor. The output of the flip-flop — typically a flag bit such as M200.2 — drives the forward command. A spare digital input (DI) becomes available, and the engineering question is: what is the safest, lowest-overhead way to invert the value currently held in M200.2 when that DI goes high, without rewriting the existing direction-control logic?
Three methods are practical on a classic S7-300/400 with STEP 7 V5.x and the LAD/FBD/STL editors. They are listed in order of preference for the typical case where the direction is a single Boolean.
- NO/NC contact pair around the output coil — implements a hardware-style XOR between the existing direction bit and the new DI. Zero extra memory, one rung.
- Conditional multiplication by −1 — numeric inversion, used when the direction is carried as a signed integer (e.g., 0 / +1 / −1) rather than a single Boolean.
- Twin SR flip-flops with a DI-driven selector — preserves the original flip-flop untouched. A second SR holds the "reversed" state and a branch selects between the two. Heavier, but useful when the original SR is read by HMI tags or other code paths that must not be touched.
2. Prerequisites
- STEP 7 V5.4, V5.5, V5.6, or STEP 7 Lite v5.5 installed with the SIMATIC Manager.
- Target CPU: S7-300 (CPU 31x / CPU 31xC) or S7-400 (CPU 41x). Both support the standard bit-logic SR flip-flop from the instruction library.
- Open block — OB1, FC, or FB — in which the direction command is currently written.
- Spare digital input module channel. Verify on the I/O assignment table that the bit is truly free and is not assigned to a system function on your CPU.
- Spare flag bit if Method 1 or Method 2 produces an intermediate result that must be referenced downstream.
Reference manuals: the SIMATIC S7-300 CPU 31x/31xC Reference Manual and the STEP 7 V5.5 Programming and Operating Manual are both available on the Siemens Industry Online Support portal. The S7-300 module data reference (which lists the system-flag area and the size of the M area per CPU) is also published there under the S7-300 product tree.
3. How the SR Flip-Flop Holds the Direction State
The SR (Set dominant) flip-flop is in the bit-logic operations folder of the standard library. It sets Q = 1 on a rising edge at S and resets to Q = 0 on a rising edge at R. With "Set dominant" semantics, a simultaneous 1 at both inputs leaves Q = 1. The output Q is a Boolean, so in the source application it is wired to M200.2 and the value of that bit — 0 or 1 — represents the latched direction command.
| S | R | Q (next) |
|---|---|---|
| 0 | 0 | unchanged (latch) |
| 1 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 1 | 1 (S dominant) |
The RS (Reset dominant) variant inverts the dominance — when both S and R are 1, Q = 0. For drive stop-on-fail philosophies, RS is usually the safer choice because a broken wire at R will still reset Q. Pick the variant that matches the safety policy; do not change it casually.
To produce a direction reversal, the engineer does not change the SR. The SR continues to hold the operator's intent. The DI is applied in front of the final output so the value driving the drive terminal becomes (SR_state XOR I_reverse). The operator still presses the same forward button; the DI performs the inversion as an external command (for example, a hand switch in the field or a permissive from a positioning system).
4. Method 1 — NO/NC Contact Pair Around the Output Coil
This is the cleanest method when the direction is a single Boolean. The pattern is two parallel branches from the trunk of the rung:
SR_OUTPUT I_REVERSE
---| |---------|/|------------------------( Q_REVERSE )---
| |
SR_OUTPUT I_REVERSE
---|/|---------| |--------------------------|
Top branch: SR_OUTPUT is TRUE and I_REVERSE is FALSE → set Q_REVERSE.
Bottom branch: SR_OUTPUT is FALSE and I_REVERSE is TRUE → set Q_REVERSE.
This is the boolean identity Q_REVERSE = SR_OUTPUT XOR I_REVERSE. Truth table:
| SR_OUTPUT | I_REVERSE | Q_REVERSE |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
If you prefer not to place the XOR in front of the physical output (because the same SR drives other logic and that logic should not see the inversion), capture the XOR result in a new flag, e.g. M200.3, and use that downstream. The rung above then assigns M200.3 rather than Q 124.0.
5. Method 2 — Conditional Multiplication by −1
When the direction command is carried as a small signed integer (e.g., a 16-bit INT in a data block that drives a VFD speed setpoint sign, or a −1 / 0 / +1 command word), numeric inversion is more idiomatic. The pattern in LAD/FBD is a multiply block whose second operand is selected by the DI.
I_REVERSE
|
[==0 ? -1 : 1] <-- selector returns -1 when DI is ON, +1 otherwise
|
[ MUL_R / MUL_I ]
|
= DBx.DBWy (the signed direction word)
Implementation in FBD on S7-300/400 using only the standard library:
- Read the existing direction word (call it
DBx.DBWn, INT type). - Build a constant word equal to +1 or −1 using an
==0comparator driven byI_REVERSE: if DI = 0, output +1; if DI = 1, output −1. - Multiply the original direction word by the constant. The product is the new direction value.
- Assign the product back to the original tag, or to a new tag if the operator's intent must be preserved bit-for-bit for HMI display.
STL equivalent on any S7-300/400 CPU (uses the MUL_I instruction):
L #direction_word // INT, holds 0, 1, or +1
L 1
L #I_reverse
==I
JMID NEG
TAK // DI = 0: multiply by +1
JU CONT
NEG: L -1 // DI = 1: multiply by -1
*I
CONT: T #direction_word_out
The result: when the operator has commanded forward (direction_word = +1) and the DI is OFF, the drive runs forward. When the DI is ON, the same forward command is numerically inverted to −1 and the drive runs in the opposite rotation.
6. Method 3 — Twin SR Flip-Flops with DI Selector
This method is the safest if you must keep the original SR intact (e.g., because HMI tags read it directly, or because it is part of a closed-source library block you cannot modify). Two parallel SRs are written:
-
SR_FWD: S = forward button, R = stop button →
M_forward -
SR_REV: S = reverse button, R = stop button →
M_reverse
A third rung implements an interlock and the DI-based override:
M_forward I_REVERSE M_reverse I_REVERSE
---| |----------|/|---------| |----------| |---------( Q_run_reverse )---
| | | |
M_reverse I_REVERSE M_forward I_REVERSE
---| |----------| |---------|/|------------|/|----|
The truth table yields Q_run_reverse = (M_forward XOR I_REVERSE) AND NOT (M_reverse XOR I_REVERSE). Mechanical and electrical interlocks remain on the contactor side; the rung only resolves the logic. This is heavier than Method 1 and is recommended only when the system uses separate hardware forward and reverse contactors with a hard interlock, or when a separate forward/reverse enable is mandated by the safety circuit (per IEC 60204-1 stop categories and the performance level required by EN ISO 13849-1 for the safety-related parts of the drive command path).
7. Step-by-Step — Inserting the Parallel Branch in STEP 7 LAD
- Open the block (OB1, FC, FB) in the LAD/FBD editor. The default view is LAD. If the network is in STL or FBD, right-click the network header and choose Display as → LAD.
- Click into the trunk of the rung at the point where the branch should start (typically just after the left power rail or just after a contact).
- Use the LAD toolbar button that opens a branch downward — in STEP 7 V5.5 this is the "Open branch" tool, an icon with a vertical line and a fork. Place the cursor on the trunk and click the button to insert a branch origin.
- Click the matching "Branch up arrow" tool to terminate the branch — this closes the parallel section back into the trunk. You may start a new branch at the same point where the previous one ended.
- Inside the new branch, place the normally-closed contact
-|/|—. Reference the DI bit, e.g.I 124.0. - In the original (top) branch, place a normally-open contact
-| |—referencing the same DI bit. If you also need the SR bit to gate the inversion, insertM200.2in series in front of each branch. - Place a coil
—( )—at the end of the trunk. The coil is the last element in the rung; intermediate elements must be contacts, comparators, or FB/FC calls. Only one coil sits at the trunk end. - Compile the block (Edit → Compile or Ctrl+B) and download to the CPU.
8. Mixing LAD and FBD Elements in One Network
STEP 7 allows mixed-language networks within the same block (LAD next to STL next to FBD in the same OB), but a single network carries a single view: once opened in LAD, you can only insert LAD elements; the same is true for FBD. To mix:
- Keep the whole network in LAD — every element (contact, comparator, block call) has a LAD representation.
- Convert the network to FBD (right-click → Display as → FBD) and rebuild it in FBD. Function calls like
MUL_Iare clearer in FBD. - If the project was originally STL, STL networks accept any instruction. Place the arithmetic in a separate STL network next to the LAD network in the same block.
Mixing across networks in the same block is normal and is what most real-world S7-300/400 programs do — a bit-logic network in LAD, an arithmetic network in STL, a function-call network in FBD. It is not confusing to a maintainer provided each network carries a title and a comment.
9. Choosing and Declaring TEMP Variables
If Method 2 needs an intermediate result, declare it in the FC/FB interface:
- Open the block's interface editor (the left pane, "Interface").
- Under the TEMP section, add a new row. Name it (e.g.,
swap_factor) and set the data type toINTfor a 16-bit signed integer. - Booleans are also valid TEMP types: declare
inv_bitasBOOLif you are holding a single inverted contact state. - Use the variable in the network — STEP 7 automatically prepends
#in the symbol.
Important constraint on TEMP variables. In S7-300/400, TEMP storage is allocated on the local stack at the moment the block is entered and is undefined on entry. A TEMP BOOL is not initialized to 0; it must be written by the block before it is read. Unlike M (flag) memory, a TEMP cannot carry a remanent value across scans. The block-local STAT section of an FB instance DB is the only place an FB holds initialized state across calls.
10. Tracking Used and Spare M-Bits and I/O
The two tools in SIMATIC Manager for resource bookkeeping are Cross-references and the Symbol Table; the tool for physical I/O is HW Config.
- Cross-references — right-click the bit, byte, or symbol in the program editor and choose Cross-references, or use Options → Cross-references in the menu. The window shows every block, network, and operand where the address appears, plus the access mode (R / W / RW). Filter by access mode "W" to find writes only.
- Symbol Table — Options → Symbol Table shows the engineering symbol for every named operand. An address with no entry is symbolic-free; cross-check against the cross-reference list to confirm it is unused in code.
- HW Config — HW Config opens the rack view. The I/O address overview is reached via Station → Open and then reading the I/O list, or via PLC → Module Information. Free DI/DO channels are those not assigned to a process image partition and not listed in the address overview.
| Need | Tool | Menu path |
|---|---|---|
| All uses of a flag bit | Cross-references | Right-click → Cross-references, or Options → Cross-references |
| All uses of a process I/O bit | Cross-references | Same as above, with the I/O bit selected |
| Free M bytes | Cross-reference list (sorted by address) | Options → Cross-references → View → Sorted by address |
| Free DI/DO channels | HW Config | HW Config → Station → Open, then read the I/O list |
| All symbols assigned to a byte | Symbol table | Options → Symbol Table |
| System flag area for this CPU | CPU manual | Product tree on Siemens Industry Online Support |
To produce a list of all unused M-bits in a project, sort the cross-reference list by absolute address, scan for gaps in the address range, and cross-check against the symbol table. A gap with no symbol and no cross-reference entry is unused. This is the most reliable way to find a free M200.x neighbour for your intermediate bit. Note that system-flag accesses (internal to the CPU firmware) are not in the cross-reference list; check the CPU manual for the system-flag area and exclude it by hand.
11. Verification After the Change
- Compile the changed block (LAD/STL/FBD editor: Edit → Compile or Ctrl+B). Resolve all warnings before downloading.
- Download to the CPU in STOP or RUN-P. RUN-P allows online edit if the CPU is in RUN-P and the block supports it. On S7-300/400, prefer STOP download when changing logic that controls a contactor or a VFD enable; RUN-P is acceptable for diagnostic logic only.
- Open a Watch Table (VAT) and force the new DI to 0. Verify the drive direction command is unchanged from the pre-modification state.
- Force the DI to 1. Verify the drive direction command inverts at the output contact or at the VFD control word.
- Force both DI states repeatedly with the drive enable OFF. The bit must toggle cleanly with no glitches at the contactor side and no spurious setpoint transitions at the VFD.
- Open the cross-reference list for the new flag bit, the SR output, the DI, and the affected output. Confirm there are no unintended writes elsewhere in the program.
- Run the standard drive test sequence: stop, forward enable, run, stop, reverse enable (via DI), run, stop. Watch the drive parameters r0021 (speed actual) and r0022 (speed setpoint) — or the equivalent on your drive — and confirm the sign inversion is clean and that no fault trips.
12. Parameter / Tag Reference
| Operand | Type | Direction | Description |
|---|---|---|---|
M200.2 |
BOOL | internal | SR flip-flop output — latched direction command from the operator |
M200.3 |
BOOL | internal | Optional: XOR result (SR_OUT XOR I_REVERSE) |
I 124.0 |
BOOL | input | Spare DI used as the inversion command |
Q 124.0 |
BOOL | output | Final direction output to the drive or contactor |
DBx.DBWn |
INT | internal | Optional: signed direction word if Method 2 is used |
FC/FB TEMP swap_factor
|
INT | local | Holds −1 or +1 multiplier; valid only inside the block |
13. Common Pitfalls
- Forgetting the "S dominant" semantics of the SR. If both S and R are 1 simultaneously, Q = 1, not 0. The RS (Reset dominant) variant is the mirror image. Pick the right one for the application — for a stop-on-fail philosophy, RS is usually the safer choice because a broken wire at R still produces Q = 0.
- STEP 7 Lite v5.5 rung layout limits. You cannot terminate two parallel branches into two coils; the network has one trunk, and only one coil sits at its end. If you need two output conditions, use a second network.
- Plug reversal of an induction motor. Reversing a contactor on a coasting motor is mechanically and electrically destructive. Always drop the run command first, wait for a controlled stop, and only then change the direction.
- Reading a TEMP before writing it. TEMP memory in S7-300/400 is undefined on block entry. Always write before read.
- Using a flag bit that is also used by the system. The S7-300 reserves a small range of flags for system use on some CPU versions. The cross-reference list will not show system accesses; check the CPU's technical data sheet on the Siemens Industry Online Support portal for the system-flag area on your specific CPU.
- Reusing a flag bit that another FC/FB already writes. Two writes to the same bit in the same scan is not inherently broken (the last write wins), but it is a maintenance trap. Cross-reference your candidate bit before claiming it.
14. Field Commissioning Notes
-
Document the inversion in the rung comment. Maintainers will see
M200.2andI 124.0and must understand that the combination is the reversed command. A one-line rung comment ("Reverse command = SR_OUT XOR I_REVERSE") is the cheapest insurance against a future bug fix that breaks the inversion silently. -
Mark the DI in HW Config and in the symbol table. An unsymbolic address like
I 124.0is the kind of bit that gets reassigned to something else in a future I/O expansion. Give it a name (I_reverse) the moment you wire it. - Test the inversion under controlled stop. With the drive in "Ready to switch on" (CiA 402 state 2), toggle the DI and confirm the speed setpoint polarity flips. With the drive in "Operation Enabled" (state 4) and the motor running, the drive may either ramp through zero (configurable) or trip on polarity change (default for many VFDs). Read the drive's Control Word handling section in the drive manual before commissioning a runtime inversion.
- Add a watchdog on the inversion DI. If the DI is a hand switch or a sensor, decide what happens if the switch fails or the wire breaks. A failure-open philosophy is usually safer: a broken wire reads as 0, the inversion is OFF, and the drive runs the operator's commanded direction. A failure-closed wire reads as 1 and the drive runs the inverted direction — which may be the wrong way for the process. Choose the philosophy and document it.
15. Related Siemens Tools Worth Knowing
- Monitor / Modify (VAT / Watch Table) — force a Boolean or write an integer to any operand. Use it for the verification steps in Section 11.
- Reference Data → Program Structure — a tree view of all blocks, OBs, FBs, FCs, DBs in the project. Useful when you must check whether the new flag bit is also written by a second block you forgot about.
- PLC → Download User Program to Memory Card — for S7-300, the program lives on the MMC. After a download, the CPU reloads from the card; keep the card labeled and archived.
- Diagnostics → Module Information — read the diagnostic buffer of the CPU. If the new code triggers a Stop, the buffer tells you which OB or FC faulted and at which operand.
All of the above are part of the standard STEP 7 V5.x install and are documented in the STEP 7 V5.5 Programming and Operating Manual on the Siemens Industry Online Support portal.
16. FAQ
How do I invert a single bit in STEP 7 V5.5 LAD without an SR flip-flop?
Use a NO/NC contact pair around a coil driven by the same source signal — that is the LAD idiom for a Boolean inversion. A contact pair driven by the inversion DI implements an XOR with the inversion bit and produces the reversed command at the coil.
Where do I find the "Open branch" tool in STEP 7 V5.5?
It is in the LAD toolbar. Select the rung, click into the trunk where the branch must originate, click the "Open branch" tool, place the elements, and click the matching "Close branch" tool to terminate the parallel section. A new branch can start where the previous one ended.
Can I declare a local Boolean in the FC interface as a TEMP?
Yes. In the Interface editor, TEMP section, add a row with name my_bit and type BOOL. Use it as #my_bit in the network. Remember: TEMP in S7-300/400 is undefined at block entry; assign it before reading it.
How do I tell which M-bits are already used in the project?
Open Options → Cross-references in SIMATIC Manager, switch the view to "Sorted by address", and scan the absolute address column for the bit. Any M-bit with no entry in the cross-reference list and no symbol-table entry is unused. The system-flag area of your CPU is a separate exclusion — check the CPU manual on the Siemens Industry Online Support portal.
Is a NO/NC contact pair the same as an XOR function block?
For Boolean inputs the truth table is identical. The contact pair is preferred on S7-300/400 because it is one rung, two contacts, no extra memory, and the intent is visible in the diagram. A software XOR instruction in STL/FBD is used when the input is a bit string longer than one bit, or when the inversion is part of a larger word-level operation.
Can I do this in STL instead of LAD?
Yes. The STL equivalent is A SR_OUTPUT; AN I_REVERSE; O; AN SR_OUTPUT; A I_REVERSE; = Q_REVERSE; — the standard XOR-on-Bits ladder pattern in five lines of code. Many S7-300/400 programmers prefer STL for inversion logic because the truth table reads linearly.