Overview
Field engineers frequently need to drive values inside a Siemens S7-1200 data block (DB) on a fixed cadence during commissioning, factory acceptance tests (FAT), or network-integration checks when physical sensors are absent. Manually typing new values into a watch table is fine for a one-off check but quickly becomes impractical when the test must repeat every 500 ms, every 2 s, or whenever a pulse train is required. This reference shows four field-proven patterns for auto-changing DB variables in TIA Portal (V15.1 through V18) without any external hardware: a TON + INC ladder pattern, a compact SCL block, the SIM-flag pattern used for sensor substitution, and the built-in PLCSIM sequence generator. Each method is sized to a S7-1200 CPU (firmware V4.2 through V4.6) but the logic is identical on S7-1500 with the appropriate instruction set.
The technique selected depends on three constraints: (1) is the target DB optimized (default in V14+) or non-optimized, (2) is the controller physical or simulated in PLCSIM, and (3) does the test need a single increment, a ramp, a sequence, or a full sensor-replay waveform. The patterns below are written for each of those cases.
Prerequisites
- TIA Portal V15.1, V16, V17, or V18 with the S7-1200 basic/advanced package installed.
- STEP 7 Safety / SCL optional package enabled for the SCL snippets (Options → Manage TIA Portal add-ins).
- CPU firmware ≥ V4.2 if you plan to use the project-view PLCSIM sequence generator (introduced in PLCSIM V15.1).
- A data block already created in the project tree under Program blocks → Add new block → Data block. See the SIMATIC S7-1200 manual collection — Data block (DB) for the canonical DB concept page.
- Watch/read access to the DB confirmed via an online watch table before any automatic code is added.
DB1.DBD8 is rejected by the compiler. The SCL snippets in this article work in both modes; the ladder examples assume symbolic access.Method Comparison
| Method | Best for | Cycle resolution | Hardware required | Works in PLCSIM |
|---|---|---|---|---|
| TON + INC ladder | Single-tag periodic increment, FAT tests | OB1 scan period | None | Yes |
SCL timer + +=
|
Multiple tags, compact code | OB1 scan period | None | Yes |
| SIM-flag + secondary OB1 | Sensor-replay simulation, no code in main | OB1 scan period | None | Yes |
| PLCSIM project-view sequencer | Pure-software I/O replay | 1 ms (project view) | None (PLCSIM only) | Yes (PLCSIM only) |
Method 1 — TON Timer plus INC Instruction (LAD)
This is the most common pattern. A TON (Timer ON-delay) generates a 1 Hz (or 0.5 Hz) tick; on each rising edge of Timer.Q the INC instruction adds 1 to a tag inside the DB. One-shot behavior is enforced by briefly disabling the timer so a single pulse never re-triggers within the same scan.
Step-by-step
- Open the project in TIA Portal and navigate to Program blocks → Main [OB1].
- Add a new network (Network 1) and insert a TON instruction. Set
IN=%M0.0(or any boolean tag) andPT=T#1sfor a 1 Hz tick. TieINtoTRUEthrough a normally-open contact of a control bitRunTestif you want to enable the test on demand. - Create tag
TonTickof typeTON_TIME(instance DB auto-generated by the call) or use a multi-instance inside a parent FB. - In Network 2, add an INC instruction. Set
IN/OUTto the symbolic name of the target DB tag, for example"MyData".Counter. - Add a normally-open contact of
TonTick.Qin series with the INC coil so the increment happens only on the rising edge. - In Network 3, reset the timer so it can re-time the next interval. The cleanest way is to feed
Timer.Qback into theINinput through an inverter — when Q goes high the input drops and the timer re-arms on the next scan. The ladder equivalent is a single NC contact ofTonTick.Qdriving theINinput of the same TON.
Ladder pattern (textual)
Network 1: 1-Hz tick
| RunTest TonTick
|---| |------(TON)---| // IN = RunTest, PT = T#1s
Network 2: increment on tick rising edge
| TonTick.Q "MyData".Counter
|---| |-----------(INC)-------| // adds 1 every second
Network 3: auto-reset of timer for next cycle
| TonTick.Q TonTick.IN
|---|/|----------| // NC contact on Q drops IN
|---( ) // pulse re-arm
ET accumulator, otherwise the next PT is not evaluated. Driving IN with the inverse of Q is the canonical pattern and survives OB1 restart conditions.Method 2 — SCL Block with += Operator
When several DB tags must change in lockstep, an SCL block keeps the code small and the scan time predictable. The SCL increment operator += is functionally identical to the LAD INC instruction but is more readable when several tags are stacked.
Step-by-step
- Right-click Program blocks → Add new block → Function block. Name it
FB_AutoRamp. - Declare the following interface:
FUNCTION_BLOCK "FB_AutoRamp"
VAR_INPUT
Enable : BOOL; // TRUE = run ramp, FALSE = freeze
Period : TIME := T#1s; // tick interval
END_VAR
VAR
TimerInst : TON_TIME; // local multi-instance
Tick : BOOL;
END_VAR
VAR_IN_OUT
Target : INT; // IN/OUT reference to any INT DB tag
END_VAR
BEGIN
TimerInst(IN := Enable, PT := Period);
Tick := TimerInst.Q;
IF Tick THEN
Target += 1;
TimerInst(IN := FALSE, PT := Period); // re-arm
END_IF;
END_FUNCTION_BLOCK
- Call the FB from OB1 and connect the
TargetIN/OUT to the desired DB tag:
// OB1 Network 1
"InstAutoRamp"(Enable := RunTest,
Period := T#500ms,
Target := "MyData".Counter);
- Compile, download, and observe
"MyData".Counterin a watch table. Each 500 ms it should advance by 1.
Why the IN/OUT pin?
Passing the target tag through an IN/OUT pin keeps the call site in control of which variable is driven. The FB itself is reusable across any INT, WORD, or DINT tag without modification. If the FB input pin is open, the compiler raises a Block parameter assignment incomplete error — this is the same behavior referenced in the project notes about FB instance-DB overwrite only being possible when the calling pin is wired.
Method 3 — SIM Flag with Secondary OB1
For tests where the production code must remain untouched (e.g. verifying an IOT2050 gateway that polls DB tags from a sibling PLC), the SIM pattern is the cleanest option. A global tag SIM gates a secondary OB1 that overwrites DB tags with simulated waveforms, leaving the real OB1 cycle undisturbed.
Step-by-step
- Add a new cyclic OB (right-click Program blocks → Add new block → Organization block → Cyclic interrupt). Use OB30 with a 100 ms cycle time as the simulator cycle.
- Declare a global tag
SIM_ENABLEof type BOOL in a global DB or the standard tag table. - First network of OB30:
IF NOT "SIM_ENABLE" THEN
RETURN; // simulator inactive, leave real values alone
END_IF;
- Subsequent networks drive the simulated tags. Example: a 0–100 sawtooth feeding
"MyData".SawValue:
"MyData".SawValue := "MyData".SawValue + 1;
IF "MyData".SawValue > 100 THEN
"MyData".SawValue := 0;
END_IF;
- Compile and download. Toggling
SIM_ENABLEfrom the watch table starts and stops the simulated waveform without recompiling.
OB30.PRIORITY collisions and the OB80 (time error) buffer to make sure you are not starving the main cycle. The default S7-1200 supports OB1 and OB30–OB38; OB30 runs at the configured time slice regardless of OB1 scan time.Method 4 — PLCSIM Project-View Sequencer
When the entire controller is virtual, PLCSIM V15.1+ exposes a project view with a sequencer that can replay any tag waveform at 1 ms resolution without writing a line of code. This is the fastest path when the goal is to validate the consumer (HMI, gateway, OPC UA client) and not the PLC code.
Step-by-step
- Start PLCSIM (Advanced) and load the project. Switch from the compact view (default) to the Project view via the toggle in the upper-right corner.
- In the project tree, open Sequencer → New sequence.
- Drag the target DB tag (e.g.
"MyData".Counter) into the sequence. Add a step that writes a constant or a ramp and set its duration to 500 ms or 1 s. - Add as many steps as the test requires and press Run sequence. The sequencer drives the tag through PLCSIM's internal image table; no PLC code is involved.
- Use the SIM table next to the sequencer to add one-shot pulses on boolean DB tags if the test requires a trigger bit as well.
Optimized vs Non-Optimized DB Access
| Property | Optimized DB (default V14+) | Non-optimized DB (classic) |
|---|---|---|
| Access path | Symbolic only | Symbolic and absolute |
| Default for new DBs | Yes | No (must clear checkbox) |
| Pointer math in SCL | Not allowed | Allowed with P#
|
| FB multi-instance | Supported | Supported (legacy) |
| Watch table read | Online → symbol path | Online → address or symbol |
If the project is locked to non-optimized blocks (e.g. legacy code imported from STEP 7 V5), the increment in SCL becomes:
DB1.Counter := DB1.Counter + 1; // non-optimized, address-based
For optimized blocks, only the symbolic form is legal:
"MyData".Counter := "MyData".Counter + 1;
"MyData".Counter += 1; // equivalent, single scan
Cycle-Time and Scan-Order Considerations
The S7-1200 OB1 runs as a free cycle. With a typical 1 ms scan on a 1214C and a TON period of 1 s, the timing resolution is well below 1% and the increment is rock solid. The pitfalls appear at sub-100 ms periods:
-
OB1 scan > TON period. If
PT < OB1 scan timethe timer expires between scans and the INC is missed. Either increase the period, lower the program size, or move the simulator into a cyclic OB such as OB30 with a fixed 1 ms or 10 ms time slice. - Two increments in one scan. The NC-reset pattern guarantees one increment per period. If the reset is missing, the TON holds Q high and the INC fires every scan for the duration of the overlap.
-
Integer wrap-around. INT ranges from -32768 to 32767. If the test must exceed this range, declare the target as DINT and replace INC with
Target += 1;in SCL or with the ladder DINT increment. - Retain behavior. A DB declared with the Set Retain attribute keeps the simulated value through a power cycle. This is usually wrong for a simulator. Open the DB properties and clear the retain attribute for the simulator tags.
Verification
- Open a watch table, add
"MyData".Counter, and click Monitor all. The value should advance at the configured period. - Toggle
RunTestoff and confirm the value freezes. Toggle it on and confirm the ramp resumes. - Force a STOP/RUN transition (online → restart) and verify the value resumes from the last written value, not from 0, unless the retain attribute was cleared (in which case it should reset to 0).
- For the SIM-flag pattern, observe
SIM_ENABLEgoing true and the simulated tags overriding the real ones within one OB30 cycle. - For PLCSIM, export the sequence to a CSV using Sequencer → Export and re-import it on the next test to confirm repeatability.
Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
| Value never changes | TonTick.Q never goes high | Check the IN line of the TON; verify RunTest is TRUE |
| Value increments every scan | Timer reset NC missing | Insert the NC contact of Q on the IN line |
| Compiler error “Unknown identifier” on DB tag | DB is optimized and absolute address used | Switch to symbolic name or clear Optimized block access |
| Simulated value ignored by HMI | HMI polls the input peripheral directly, not the DB | Change HMI tag source to the symbolic DB tag |
| OB30 stops running after download | Cyclic OB configured with unsupported time slice | Use a supported multiple of 1 ms (1, 2, 5, 10, 20, 50, 100, 200, 500, 1000) on the S7-1200 |
| Watch table shows red “Invalid value” | FB instance DB overwritten while pin is open | Wire all input pins in the calling block or use IN_OUT for the target |
| PLCSIM sequence runs but production code overwrites the tag | OB1 writes to the same tag every cycle | Disable the production code via a SIM enable, or move the test to a separate DB the production code does not touch |
Edge Cases and Field Notes
- External gateway scenario. When the data block lives on a sibling PLC that the local project only knows by IP, the SIM-flag pattern is the only safe option. The local PLC never touches the remote DB; the remote PLC's own OB30 drives the simulated values and the IOT2050 gateway (or any OPC UA client) reads them transparently.
- Concurrent engineering. Adding a cyclic OB during a live commissioning can shift OB1 priority scheduling. Always download to STOP first, then to RUN, and clear the diagnostic buffer immediately after.
- Security. Knowledge of the protection level (read-only vs full access) is required to overwrite DB tags. The CPU's Properties → Protection → Access level must be set to Full access (no protection) for the test user, or the corresponding password must be entered when going online.
-
Firmware dependency. The TON reset pattern works on every S7-1200 firmware. The SCL
+=operator requires the SCL optional package and a CPU firmware ≥ V4.0. PLCSIM's project view is V15.1+ only.
How do I auto-increment an INT inside an S7-1200 data block every 500 ms?
Add a TON with PT = T#500ms driven by a control bit, place an INC on the symbolic DB tag in the next network with a NO contact of Timer.Q, and add an NC contact of Timer.Q on the timer's IN line to re-arm it. Download to RUN and monitor the value in a watch table; it should advance by 1 every 500 ms.
Can I change a DB variable every scan instead of every 500 ms?
Yes. Drop the TON entirely and wire the INC directly to a constant TRUE contact. The tag will increment on every OB1 scan, giving the fastest possible rate, typically 1–3 ms on an S7-1214C. Watch the integer overflow after 32767 cycles or switch the tag to DINT.
Why does my FB instance DB refuse to accept external writes?
An instance DB cannot be overwritten from outside the FB unless the corresponding input pin of the calling block is wired. To accept external simulation, expose the target tag as a VAR_IN_OUT in the FB and connect it at the call site; otherwise the compiler will raise Block parameter assignment incomplete at download time.
Does the PLCSIM sequencer work without writing any PLC code?
Yes. Open PLCSIM in project view (not miniature view), create a new sequence, drag the target DB tag into the sequence, add steps with the desired values and durations, and press Run. The sequencer drives the tag through the process image at 1 ms resolution and no user program is required.
What is the safest pattern when a gateway like the IOT2050 polls the DB?
Use a SIM flag plus a secondary cyclic OB (OB30). The flag gates the simulator; the simulator writes to the DB only while the flag is true. This way the production code is untouched, the gateway reads the simulated value transparently, and toggling the flag returns the system to live values without recompiling or downloading.