Configuring TIA Portal Ramp-Down for 10V to 0V Analog Outputs
Ramp generation on a Siemens S7-1500 or S7-1200 analog output is conceptually trivial: decrement a value every scan, scale it to the analog range, and write it to the output word. In practice, the most common symptom reported in demagnetization applications is "the time runs out before the curve reaches zero." The ramp finishes its 4-second window while the output is still at, for example, 0.18 V, because the per-cycle decrement was rounded down or because the integrator stopped one cycle early. This reference walks through the math, the two reliable SCL implementations, and the commissioning checks that guarantee the output lands exactly at 0 V when the ramp time elapses.
1. Problem Statement and Application Context
A demagnetization yoke is typically driven from a 0–10 V analog output that programs the current of an external amplifier or magnetizing supply. To degauss the workpiece, the controller raises the output to a hold level (commonly 10 V), holds it for a magnetization period, then ramps it back to 0 V over a fixed decay window so the magnetic flux follows a controlled envelope rather than collapsing instantaneously.
The two application flags that drive the sequence are:
| Tag | Direction | Meaning |
|---|---|---|
Allg.A_DemagYoke |
Input (BOOL) | Step active: ramp generator is enabled and must produce the demagnetization curve |
Allg.AEndDemag |
Output (BOOL) | Step finished: ramp time has elapsed and the output has reached 0 V |
AEndDemag must NOT be set true until the analog output is mathematically and physically at 0 V. Premature release corrupts the demagnetization curve and leaves residual magnetism in the workpiece.2. Root Cause Analysis — Why the Ramp Stops Above Zero
Three failure modes account for nearly every "time finishes before the curve reaches zero" report. All three are mathematically predictable and all three are fixable in the controller.
2.1 Non-integral step count
The naive implementation computes:
Step = (EndValue - StartValue) / (RampTime / CycleTime)
If the quotient is non-integer and the code uses integer division or REAL_TO_INT with truncation, the last step underflows by the fractional remainder. Example:
| Parameter | Value |
|---|---|
| Start value | 10.0 V |
| End value | 0.0 V |
| Ramp time | 4 000 ms |
| OB1 cycle time | 10 ms |
| Steps required | 400 |
| Step size (correct) | -0.025 V/step |
| Step size if divided at 100 ms | -0.25 V/step → 40 steps, fine |
| Step size if divided at 7 ms | -0.0175 V/step → no integer solution |
Whenever the cycle time does not divide the ramp time exactly, a fractional residual is created. With fixed-point math, that residual is silently discarded.
2.2 Floating-point precision loss
Adding a small negative REAL step 400 times to 10.0 can accumulate to a value that is not exactly 0.0. Values like 0.0000034 are typical because 10.0 is not exactly representable in IEEE-754. The comparator IF value <= 0.0 THEN may evaluate false for one or two extra cycles, extending the ramp beyond its declared window.
2.3 OB1 vs. cyclic interrupt
If the ramp runs inside OB1, the cycle time varies with the rest of the program. A 10 ms OB1 can stretch to 35 ms during heavy communications processing, so by the time 100 OB1 ticks have elapsed, the wall-clock ramp time may already be 3.5 s instead of 1.0 s. The ramp then finishes well before zero is reached, or well after. The robust fix is to drive the ramp from a time-driven OB, e.g., OB30 with a fixed 10 ms interval.
3. Mathematical Foundation of a Clean Ramp
A bounded linear ramp from Vstart to Vstop over a duration T sampled every Δt can be expressed two ways:
Method A — Constant delta (preferred for voltage output):
v(n) = Vstart + n · (Vstop - Vstart) / N where N = T / Δt
This guarantees v(N) = Vstop exactly. The implementation is an integrator that holds the step size as a high-precision LREAL and accumulates n on each tick.
Method B — Rate-based (preferred for current-output drivers with linear time base):
v(t) = Vstart + ∫r(t) dt where r = (Vstop - Vstart) / T V/ms
This is simpler but the final value depends on the precision of the multiplication. Use Method A when you must guarantee the endpoint.
4. TIA Portal Implementation — SCL Function Block
The block below is written for S7-1500 in SCL. It produces a clean 10 V → 0 V ramp and forces the output exactly to 0 on the last cycle. Copy it into a new FB in TIA Portal V17 or later.
FB "RampGen" — Interface
FUNCTION_BLOCK "RampGen"
TITLE = 'Linear ramp generator with exact endpoint'
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iEnable : BOOL; // TRUE = ramp runs
iStartValue : LREAL; // engineering units, e.g. 10.0
iEndValue : LREAL; // engineering units, e.g. 0.0
iRampTimeMs : DINT; // total ramp duration in ms
iCycleMs : DINT; // OB tick in ms (e.g. 10)
END_VAR
VAR_OUTPUT
oCurrentVal : LREAL; // instantaneous value
oFinished : BOOL; // set when ramp has reached end value
oRawOut : INT; // 0..27648 for 0..10 V on AQ module
END_VAR
VAR
sStepSize : LREAL; // per-tick increment
sStepsTotal : DINT; // N = T / dt
sStepCount : DINT; // current n
sRunning : BOOL;
END_VAR
VAR_TEMP
tDone : BOOL;
END_VAR
FB "RampGen" — Code body
BEGIN
// ---- Edge: rising edge of enable ----
IF iEnable AND NOT sRunning THEN
sStepCount := 0;
sStepsTotal := iRampTimeMs / iCycleMs;
// Guard against divide-by-zero and zero-step ramp
IF sStepsTotal < 1 THEN
sStepsTotal := 1;
END_IF;
sStepSize := (iEndValue - iStartValue) / LREAL#TO_LREAL(sStepsTotal);
sRunning := TRUE;
oCurrentVal := iStartValue;
oFinished := FALSE;
END_IF;
// ---- Disable request ----
IF NOT iEnable THEN
sRunning := FALSE;
oFinished := TRUE;
oCurrentVal := iEndValue;
oRawOut := 0;
RETURN;
END_IF;
// ---- Tick processing (call from cyclic OB) ----
IF sRunning THEN
sStepCount := sStepCount + 1;
IF sStepCount >= sStepsTotal THEN
// Final tick: snap exactly to endpoint
oCurrentVal := iEndValue;
sRunning := FALSE;
oFinished := TRUE;
ELSE
oCurrentVal := iStartValue + LREAL#TO_LREAL(sStepCount) * sStepSize;
END_IF;
END_IF;
// ---- Scale to analog output word ----
// For 0..10 V S7-1500 AQ modules the range is 0..27648 (see
// S7-1500 analog module manual, section 4.3 "Output ranges")
oRawOut := REAL_TO_INT(oCurrentVal / 10.0 * 27648.0);
IF oRawOut < 0 THEN oRawOut := 0; END_IF;
IF oRawOut > 27648 THEN oRawOut := 27648; END_IF;
END_FUNCTION_BLOCK
Calling this FB from OB30 with a 10 ms group ensures that StepCount = 400 after exactly 4 000 ms and the output snaps to 0.0 on tick 400, satisfying both the time budget and the endpoint.
5. Scaling from Volts to the Analog Output Word
The S7-1500 analog output modules (e.g., AQ 8xU/I HS) map the bipolar and unipolar ranges as follows:
| Voltage range | Decimal value | Hex |
|---|---|---|
| 0 V | 0 | 0x0000 |
| 5 V | 13 824 | 0x3600 |
| 10 V | 27 648 | 0x6C00 |
| Overrange 11.76 V | 32 511 | 0x7EFF |
Transfer function (unipolar 0–10 V):
OUT_word = ROUND( V_out / 10 · 27 648 )
For a 0–20 mA output to a current-controlled amplifier, the equivalent is:
OUT_word = ROUND( I_out / 20 · 27 648 )
Always write the scaled integer via the process image address configured in the device view (e.g., %QW64 for the first channel of AQ 8xU/I HS). Do not write to the analog output tag from OB1 with the default process image update; doing so couples the output update to the OB1 scan.
6. Cycle Time and Step Size Worksheet
Before commissioning, populate this worksheet so the math is provable:
| Symbol | Meaning | Example |
|---|---|---|
| Vstart | Hold voltage | 10.0 V |
| Vstop | Demagnetized voltage | 0.0 V |
| T | Ramp duration | 4 000 ms |
| Δt | Cyclic OB interval | 10 ms (OB30) |
| N = T / Δt | Total ticks | 400 |
| Δv = (Vstop - Vstart) / N | Step size | -0.025 V/tick |
| LSB_V = 10 / 27 648 | Voltage per LSB | 361.69 µV |
| Quantization error | |Δv| / LSB_V | 69 LSB/tick |
|Δv| < LSB_V, one or more consecutive ticks will produce the same output word. This is not an error, but it means the endpoint will be reached before all ticks have elapsed. The snap-to-end logic in §4 handles this case correctly.7. Edge Cases and Error Handling
| Scenario | Symptom | Mitigation in code |
|---|---|---|
iRampTimeMs < iCycleMs
|
Divide by zero or step size > range | Clamp sStepsTotal to a minimum of 1 |
| OB tick overruns (jitter > 30 %) | Ramp time drifts | Move ramp to OB30/OB35 with watchdog |
| PLC goes STOP mid-ramp | Output holds last value | Configure AQ module "Reaction to CPU STOP" = "Output 0 V / no current" |
| Negative ramp (start < end) | Direction reversed unintentionally | Accept both signs; Δv becomes positive automatically |
| Enable toggles mid-ramp | Step count resets | Edge-trigger iEnable as shown in §4; debounce 100 ms if noisy |
| Overflow on 32-bit REAL after long integration | Slow drift of endpoint | Use LREAL and snap on final tick (already done in §4) |
8. Wiring the Step Flags to the Ramp
The original project uses the step tags Allg.A_DemagYoke and Allg.AEndDemag. Wire them to the FB as follows inside the demagnetization step:
// In the demagnetization step FB (call from OB1 or OB30)
"iDB_DemagStep"(
iEnable := "Allg".A_DemagYoke,
iStartValue := 10.0,
iEndValue := 0.0,
iRampTimeMs := 4000,
iCycleMs := 10,
oCurrentVal => "Allg".DemagCurrentV,
oFinished => "Allg".AEndDemag,
oRawOut => "Allg".DemagRawOut
);
// Drive the analog output word every cycle
"Allg".DemagRawOut_hw := "Allg".DemagRawOut;
%QW64 := "Allg".DemagRawOut_hw; // first channel of AQ module
Because AEndDemag is set only when oFinished asserts (i.e., the FB has snapped to exactly 0 V), the step sequencer transitions to the next state with a guaranteed clean endpoint.
9. Commissioning and Verification
Verify the ramp on the bench before connecting the yoke amplifier:
-
Watch table: create a watch table with
Allg.A_DemagYoke,Allg.DemagCurrentV,Allg.DemagRawOut, andAllg.AEndDemag. SetA_DemagYoke = TRUEand trigger a recording ofDemagCurrentVwith a 10 ms sample period. - Trace: in TIA Portal, add a trace recording of the same tags with a 1 ms resolution. The trace should show a clean straight line from 10.0 to 0.0 over exactly 4 000 ms, with the last sample exactly at 0.0.
-
Multimeter check: measure the voltage at the analog output terminals with a 4½-digit DMM. The terminal voltage should match
DemagCurrentVwithin the module's accuracy class (typical ±0.3 % of full scale for the AQ 8xU/I HS). -
Timing check: verify that
AEndDemagrises between 4 000 ms and 4 020 ms afterA_DemagYoke. Any drift points to OB tick jitter. -
Fault diagnostics: if the analog module reports a wire break or channel fault (diagnostic interrupt, see AQ module manual section 5.2), the ramp will not reach zero. Check
ModuleOKin the diagnostic FB before enabling the ramp.
10. Alternative: Ladder-Logic Incrementer
For projects that must remain in LAD/FBD, the same logic can be implemented as follows. Use a counter driven by the cyclic OB clock:
- Compute
StepsTotal = RampTime / OB_Cycleonce at startup. - Compute
StepSize_REAL = (End - Start) / StepsTotalin REAL. - Each tick: increment a CTU counter, multiply counter value by StepSize_REAL, add to Start, write the result to a temporary REAL tag.
- On the final tick (counter >= StepsTotal), force the output to End and set the finished flag.
The ladder version is harder to read but produces identical results to the SCL FB when the same arithmetic primitives are used.
11. Frequently Asked Questions
Why does my ramp finish at 0.18 V instead of 0 V?
Almost always because the per-cycle step size was rounded to a DINT or REAL with insufficient resolution and the residual was discarded. Compute StepSize as LREAL and force the output to the exact endpoint on the final tick, as shown in §4.
Should I run the ramp in OB1 or in a cyclic interrupt OB?
Use a time-driven cyclic interrupt OB such as OB30 with a 1–10 ms interval. OB1 cycle time drifts under load, which causes the ramp time to drift proportionally and the endpoint to be reached at the wrong wall-clock instant.
How do I scale 0–10 V to the S7-1500 analog output word?
Use OUT_word = ROUND( V / 10 · 27 648 ). The range, including overrange, is documented in the S7-1500 AQ module manual. Clamp negative values to 0 and values above 27 648 to 27 648.
Can the ramp run backwards (e.g., 0 V → 10 V) with the same FB?
Yes. The block accepts iStartValue greater than iEndValue (down-ramp) or less than iEndValue (up-ramp). The sign of Δv follows automatically. This is useful for the magnetization phase that typically precedes the demagnetization ramp.
What happens to the analog output if the CPU goes STOP during the ramp?
Behavior depends on the "Reaction to CPU STOP" parameter of the AQ module. Set it to "Output 0 V" for demagnetization yokes so the magnetic field collapses immediately rather than holding at the last ramped value. The setting is in the device properties of the AQ module in TIA Portal.
Does the external op-amp circuit in the amplifier chain affect the ramp shape?
Yes. If the amplifier uses a non-inverting op-amp with gain and offset (e.g., a 2.5 V reference scaled to 0–10 V as discussed in the TI E2E amplifier forum), the controller must produce the pre-scaling voltage. Verify the transfer function end-to-end: V_out = V_in · G + V_off. Bake G and V_off into the start and end values of the ramp FB.