diff --git a/s7-1500/demo-advance-scl-contol.md b/s7-1500/demo-advance-scl-contol.md index 6f65725..a6c0e83 100644 --- a/s7-1500/demo-advance-scl-contol.md +++ b/s7-1500/demo-advance-scl-contol.md @@ -1,531 +1,675 @@ -# README — S7-1500 SCL Sequencer (AUTO / INCR) with Pause vs Stop, Stop Categories, Skip/Disable, Safety-Locked Steps +# S7-1500 SCL Sequencer — Advanced 10-Step Welding Cell -This project shows a Siemens S7-1500 step sequencer in SCL with: -- AUTO mode (advance automatically) -- INCR mode (advance only on operator NEXT pulse) -- Pause vs Stop -- Stop categories (immediate / end-of-step / end-of-cycle / no-stop) -- Per-step UDT configuration (timeout + operator text) -- Skip/disable steps (optional steps can be disabled) -- Prevent disabling safety steps (PLC forces critical steps enabled) +> **Platform:** Siemens S7-1500 | TIA Portal V18+ | SCL (Structured Control Language) +> **Block:** `FB_WeldSequencer` | Optimized Access | IEC 61131-3 compliant -You can paste the TYPES into "PLC data types" and the FB code into an SCL FB. +A production-ready, feature-complete **10-step sequencer** for a MIG/MAG robotic welding cell demonstrating all advanced sequencer patterns: AUTO/INCREMENT modes, PAUSE vs STOP, IEC Stop Categories (CAT0/CAT1/CAT2), Step Skip, Step Disable, Safety-Locked Steps, sensor-based advance, dual-sensor (FWD/BWD) advance, and pure timer advance. ------------------------------------------------------------- -1) Concepts / How it works ------------------------------------------------------------- +--- -1. Step machine (FSM) -- Variable "Step" defines the state: - Step = 0 -> IDLE - Step = 1..10 -> execute step logic -- Each step has: - - Actions (outputs to command) - - Done condition (when it is allowed to advance) - - Timeout (if not done within time -> Error) +## Table of Contents -2. Modes -We use enum E_Mode: -- MODE_STOP = 0 (not running, safe outputs) -- MODE_AUTO = 1 (auto advance) -- MODE_INCR = 2 (manual advance with NEXT) +1. [Feature Overview](#1-feature-overview) +2. [File Structure](#2-file-structure) +3. [I/O Map](#3-io-map) +4. [Sequencer Modes](#4-sequencer-modes) +5. [State Machine](#5-state-machine) +6. [Stop Categories (IEC 60204-1)](#6-stop-categories-iec-60204-1) +7. [Pause vs Stop](#7-pause-vs-stop) +8. [Step-by-Step Breakdown](#8-step-by-step-breakdown) +9. [Step Advance Types](#9-step-advance-types) +10. [Skip / Disable / Safety-Lock](#10-skip--disable--safety-lock) +11. [Fault Codes](#11-fault-codes) +12. [HMI Integration](#12-hmi-integration) +13. [TIA Portal Setup](#13-tia-portal-setup) +14. [Adapting the Code](#14-adapting-the-code) +15. [Safety Notes](#15-safety-notes) -Mode selection priority: -- If Enable=FALSE OR Cmd_Stop=TRUE OR ErrorActive=TRUE => MODE_STOP -- Else if Mode_Auto=TRUE => MODE_AUTO -- Else if Mode_Incr=TRUE => MODE_INCR -- Else MODE_STOP +--- -3. Pause vs Stop -- STOP: - - forces safe outputs (FALSE) - - typically sets Step=0 (IDLE) -- PAUSE: - - freezes step progression and timer - - keeps outputs frozen at last values (freeze outputs) +## 1. Feature Overview -Pause is implemented by: -- PauseLatched toggled by Cmd_Pause edge -- when pause becomes TRUE, capture current outputs into Frozen_* variables -- while paused, outputs are forced to Frozen_* values +| Feature | Description | +|---|---| +| **AUTO mode** | Steps advance immediately when advance condition is met | +| **INCREMENT mode** | Condition must be TRUE then operator presses `Cmd_Incr` to advance | +| **PAUSE** | Soft hold — all outputs frozen in place; resume resumes same step | +| **STOP (CAT2)** | Hard hold — requires `Cmd_Reset` to return to IDLE | +| **E-Stop CAT0** | Immediate: all outputs de-energised in the same scan | +| **E-Stop CAT1** | Controlled: current step finishes its "safe motion" then stops | +| **E-Stop CAT2** | Suspend: outputs frozen until reset (same as STOP) | +| **Skip Step** | Operator can force-advance any step NOT safety-locked | +| **Disable Step** | Individual steps can be permanently skipped (e.g. bypass unused stations) | +| **Safety-Locked Steps** | Steps 1, 5, 7 cannot be skipped — operator `SkipStep` is silently ignored | +| **Timer Advance** | Steps 4, 6, 8 advance on IEC timer expiry (no sensor needed) | +| **1-Sensor Advance** | Steps 2, 5, 7, 10 advance on single sensor | +| **2-Sensor Advance** | Steps 1, 3, 9 use FWD + BWD sensors with conflict detection | +| **Step Watchdog** | 30 s watchdog per step — faults if a step takes too long | +| **Cycle Counter** | Persistent `CycleCount` DINT increments on every completed cycle | -4. Stop categories (StopReq + StopCat) -Enum E_StopCat: -- STOPCAT_IMMEDIATE: - stop instantly (Step=0 + safe outputs) -- STOPCAT_END_OF_STEP: - finish current step then stop -- STOPCAT_END_OF_CYCLE: - continue until the configured end-of-cycle step completes, then stop -- STOPCAT_NO_STOP: - info only (never stops) +--- -Stop requests are latched: -- STOPCAT_IMMEDIATE / END_OF_STEP / END_OF_CYCLE -> latched in PLC -- STOPCAT_NO_STOP -> not latched (only displayed as info) +## 2. File Structure -5. Per-step configuration via UDT array Cfg[1..10] -Each step stores: -- Text: shown to operator -- Timeout: step timeout -- IsEndOfCycle: marks the “cycle end” step -- ReqEnabled: HMI requested enable -- Enabled: PLC effective enable used by sequencer -- SafetyLocked: if TRUE, cannot be disabled -- NextStep: optional jump target (0 means normal next) +``` +📁 WeldSequencer/ +├── FB_WeldSequencer.scl # Main Function Block — all sequencer logic +└── README.md # This file +``` -The PLC NEVER trusts ReqEnabled directly. -PLC computes Enabled every scan: -- if SafetyLocked => Enabled := TRUE (and optionally ReqEnabled forced TRUE too) -- else Enabled := ReqEnabled +> **Note:** In TIA Portal, create one **Instance DB** for the FB (e.g. `DB_WeldSeq`). The instance DB holds all internal state, timers, and configuration arrays. -6. Skip/Disable steps -Instead of Step := Step + 1, we compute "next enabled step": -- If operator disables a step, sequence jumps over it -- A helper FC_NextEnabledStep finds the next enabled step -- In AUTO mode we wrap 10->1, in INCR mode we can end at 0 +--- -Optional routing: -- If Cfg[Step].NextStep <> 0 then jump to that step (if enabled). +## 3. I/O Map ------------------------------------------------------------- -2) PLC Data Types (copy into "PLC data types") ------------------------------------------------------------- +### Digital Inputs (DI) -TYPE E_Mode : USINT ( - MODE_STOP := 0, - MODE_AUTO := 1, - MODE_INCR := 2 +| Address | Tag Name | Description | Used in Step(s) | +|---|---|---|---| +| `%I0.0` | `Sen_HomeFwd` | Fixture at home position | 1 | +| `%I0.1` | `Sen_HomeBwd` | Fixture NOT in work zone (redundant) | 1 | +| `%I0.2` | `Sen_ClampClosed` | Clamp jaw fully closed | 2 | +| `%I0.3` | `Sen_HeadAtWeldPos` | Weld head fully EXTENDED | 3, 9 | +| `%I0.4` | `Sen_HeadRetracted` | Weld head fully RETRACTED | 3, 9 | +| `%I0.5` | `Sen_ArcDetect` | Arc current detected (welder feedback) | 5 | +| `%I0.6` | `Sen_ArcOff` | Arc extinguished (current < threshold) | 7 | +| `%I0.7` | `Sen_UnclampConf` | Clamp open / part ejected | 10 | +| `%I1.0` | `Safety_EStopOK` | Safety relay: TRUE = E-Stop clear | All | +| `%I1.1` | `Safety_DoorClosed` | Safety gate NC contact | All | +| `%I1.2` | `Cmd_EStop` | E-Stop command (from safety relay or HMI) | All | +| `%I1.3` | `Cmd_Reset` | Reset faults / return to IDLE | All | +| `%I1.4` | `Cmd_Start` | Start cycle / Resume after pause | All | +| `%I1.5` | `Cmd_Pause` | Pause at current step | All | +| `%I1.6` | `Cmd_Stop` | CAT2 Stop | All | +| `%I1.7` | `Cmd_Incr` | Increment step (INCREMENT mode only) | All | +| `%I2.0` | `Mode_Auto` | Automatic mode selector | All | +| `%I2.1` | `Mode_Incr` | Increment mode selector | All | +| `%I2.2` | `Cmd_SkipStep` | Skip current step (if not locked) | All | + +### Digital Outputs (DQ) + +| Address | Tag Name | Description | Active in Step(s) | +|---|---|---|---| +| `%Q0.0` | `Act_Clamp` | Clamp solenoid | 2 → 9 | +| `%Q0.1` | `Act_HeadExtend` | Weld head extend solenoid | 3 → 8 | +| `%Q0.2` | `Act_HeadRetract` | Weld head retract solenoid | 9 | +| `%Q0.3` | `Act_GasValve` | Shielding gas solenoid valve | 4 → 8 | +| `%Q0.4` | `Act_WeldEnable` | Welder power enable relay | 5, 6 | +| `%Q0.5` | `Act_Unclamp` | Unclamp solenoid | 10 | +| `%Q0.6` | `Act_PartEject` | Part ejector cylinder solenoid | 10 | +| `%Q1.0` | `Seq_Running` | Sequence running indicator | — | +| `%Q1.1` | `Seq_Paused` | Sequence paused indicator | — | +| `%Q1.2` | `Seq_Faulted` | Fault active indicator | — | +| `%Q1.3` | `Seq_Complete` | Cycle complete indicator | — | + +### Memory / HMI Words + +| Address | Tag Name | Type | Description | +|---|---|---|---| +| `%MW10` | `StopCategory` | INT | E-Stop category: 0, 1, or 2 | +| `%MW20` | `ActiveStep` | INT | Currently executing step | +| `%MW22` | `SeqState` | INT | State machine code (0–6) | +| `%MW24` | `FaultCode` | INT | Active fault code | +| `%M5.0` | `StepAdvanceReady` | BOOL | Advance condition satisfied | +| `%M5.1` | `IncrWaiting` | BOOL | Waiting for Incr in INCREMENT mode | +| `%MD30` | `CycleCount` | DINT | Completed cycles | + +--- + +## 4. Sequencer Modes + +### AUTO Mode (`Mode_Auto = TRUE`) + +``` +Cmd_Start ──→ Step 1 ──[cond met]──→ Step 2 ──[cond met]──→ ... ──→ Step 10 ──→ COMPLETE +``` + +The sequence runs end-to-end without any operator input once started. Each step advances the instant its advance condition becomes TRUE. Intended for normal production operation. + +### INCREMENT Mode (`Mode_Incr = TRUE`) + +``` +Cmd_Start ──→ Step 1 ──[cond met + Cmd_Incr]──→ Step 2 ──[cond met + Cmd_Incr]──→ ... +``` + +The sequencer waits at each step until: +1. The step's advance condition is `TRUE` (sensor or timer) +2. **AND** the operator presses `Cmd_Incr` + +The `IncrWaiting` output goes `TRUE` when condition is met but waiting for the increment button — useful for an HMI indicator ("Ready to advance — press INCR"). + +**Use cases:** First article inspection, commissioning, slow-speed prove-out, fault recovery. + +> **Mode switching:** Change modes between cycles only (while in IDLE or COMPLETE). Switching mid-cycle is accepted by the FB but may cause unexpected step dwell. + +--- + +## 5. State Machine + +``` + ┌─────────────────────────────────────────────────────┐ + │ │ + ▼ │ + ┌─────────────────┐ Cmd_Start + safe ┌───────────────────┐ │ + │ 0 — IDLE │ ─────────────────────▶ │ 1 — RUNNING │ │ + └─────────────────┘ └───────────────────┘ │ + ▲ │ │ │ │ │ + │ Cmd_Reset Cmd_Pause│ │ │ │last step + │ (from STOPPED/FAULTED/ ◀────────┘ │ │ ▼ + │ COMPLETE) ┌──────────────┐ │ │ ┌──────────────┐ + │ │ 2 — PAUSED │ │ │ │ 6 — COMPLETE │─┘ + │ └──────────────┘ │ │ └──────────────┘ + │ Cmd_Stop▼ │ │ + │ ┌──────────────┐ │ E-Stop + │ │ 4 — STOPPED │◀───┘ CAT1│ + │ └──────────────┘ ▼ + │ ┌─────────────────────┐ + │ │ 3 — STOPPING_CAT1 │ + │ └─────────────────────┘ + │ ┌──────────────┐ │ step done or timeout + │ ◀────────────────── │ 5 — FAULTED │◀─────────┘ + │ Cmd_Reset └──────────────┘ + │ + E-Stop clear ▲ + │ + door closed │ E-Stop CAT0 / door open + └───────────────────────────────────────┘ +``` + +| State | Code | Outputs | Resume? | Reset? | +|---|---|---|---|---| +| IDLE | 0 | Weld/gas/motion off | — | — | +| RUNNING | 1 | Per active step | — | — | +| PAUSED | 2 | **Held** (frozen) | `Cmd_Start` | — | +| STOPPING_CAT1 | 3 | Current step active | — | After → STOPPED | +| STOPPED | 4 | Safe state | — | `Cmd_Reset` | +| FAULTED | 5 | **ALL off** | — | `Cmd_Reset` + clear | +| COMPLETE | 6 | Weld/gas off | `Cmd_Start` (new cycle) | `Cmd_Reset` | + +--- + +## 6. Stop Categories (IEC 60204-1) + +Set `StopCategory` (INT) via HMI or hard-wired selector before triggering `Cmd_EStop`. + +### CAT0 — Uncontrolled Stop (Immediate) + +``` +Cmd_EStop = TRUE, StopCategory = 0 + │ + └──▶ State → FAULTED + ALL outputs := FALSE (same PLC scan) + FaultCode := 11 +``` + +- Power removed from actuators immediately — no "safe" motion completes +- Required for: hazardous energy, fire risk, collision imminent +- Hardware: typically wired directly to safety relay, not via PLC + +### CAT1 — Controlled Stop + +``` +Cmd_EStop = TRUE, StopCategory = 1 + │ + └──▶ State → STOPPING_CAT1 + Current step continues executing (sensor/timer logic active) + CAT1 guard timer starts (10 s) + │ + ├── Step advance condition met ──▶ State → STOPPED (clean stop) + │ + └── Timer.Q (timeout) ──▶ State → FAULTED, FaultCode = 20 +``` + +- Allows servo drives, cylinders, and the weld head to complete their safe end-position before power is removed +- Prevents mechanical damage from mid-stroke stops +- 10 s `CAT1_TIMEOUT` constant protects against hangs — adjust for your application + +### CAT2 — Controlled Stop (Power Maintained) + +``` +Cmd_EStop = TRUE, StopCategory = 2 (or Cmd_Stop rising edge) + │ + └──▶ State → STOPPED + Outputs frozen at current values + Drives/brakes remain energised (position maintained) + Cmd_Reset required to return to IDLE +``` + +- Used for: planned end-of-shift, material change, inspection +- Unlike PAUSE, requires explicit Reset rather than Start to resume + +--- + +## 7. Pause vs Stop + +| | PAUSE (`Cmd_Pause`) | STOP (`Cmd_Stop`) | +|---|---|---| +| **Activation** | Rising edge `Cmd_Pause` | Rising edge `Cmd_Stop` | +| **IEC Category** | — (not a stop category) | CAT2 | +| **Outputs** | Held at current state | Held at current state | +| **Resume** | `Cmd_Start` → continues same step | `Cmd_Reset` → returns to IDLE | +| **Typical use** | Short interruption (fork truck, material feed) | Planned stop, shift change, part change | +| **From safety fault?** | Cannot resume if door open | Cannot reset if E-Stop active | +| **Step continuity** | Resumes mid-step (timer paused) | Restarts from Step 1 after reset | + +> **Important:** In PAUSED state, step timers stop counting (their `IN` bit goes FALSE because `_state ≠ STATE_RUNNING`). When resumed, timers restart from zero for the current step. If this is undesirable for your application (e.g. partial gas purge time), modify the timer `IN` condition to also include `STATE_PAUSED`. + +--- + +## 8. Step-by-Step Breakdown + +### Step 1 — Home Position Verify 🔒 Safety-Locked + +``` +Sensors : Sen_HomeFwd (at home) + Sen_HomeBwd (NOT in work zone) +Actuators: NONE +Advance : Sen_HomeFwd = TRUE AND Sen_HomeBwd = FALSE +Lock : Safety-locked — SkipStep ignored +Purpose : Confirm fixture/robot is at safe starting co-ordinate before + clamping a part. Two-sensor logic eliminates single-sensor failure. +``` + +### Step 2 — Clamp Workpiece + +``` +Sensors : Sen_ClampClosed (1 sensor) +Actuators: Act_Clamp ON +Advance : Sen_ClampClosed = TRUE +Purpose : Engage pneumatic clamp jaw on the workpiece. + Act_Clamp remains energised throughout steps 2–9. +``` + +### Step 3 — Extend Weld Head + +``` +Sensors : Sen_HeadAtWeldPos (FWD) + Sen_HeadRetracted (BWD — conflict check) +Actuators: Act_HeadExtend ON +Advance : Sen_HeadAtWeldPos = TRUE (FWD sensor) +Purpose : Drive weld torch to the weld start position. + FWD+BWD conflict detection → FaultCode 30 if both TRUE. +``` + +### Step 4 — Pre-Purge Gas ⏱ Timer + +``` +Sensors : NONE +Actuators: Act_GasValve ON +Advance : Timer T#2S elapsed +Purpose : Flow shielding gas (Argon/CO₂ mix) before arc strike to + displace atmospheric oxygen from the weld zone. +``` + +### Step 5 — Arc Strike 🔒 Safety-Locked + +``` +Sensors : Sen_ArcDetect (1 sensor) +Actuators: Act_WeldEnable ON + Act_GasValve ON +Advance : Sen_ArcDetect = TRUE +Lock : Safety-locked — arc MUST be confirmed before weld travel begins +Purpose : Enable the welder and wait for arc current feedback. + Without this lock, a failed arc strike could lead to cold welds. +``` + +### Step 6 — Weld Travel ⏱ Timer + +``` +Sensors : NONE +Actuators: Act_WeldEnable ON + Act_GasValve ON +Advance : Timer T#4S elapsed +Purpose : Robot/axis traverses the weld seam. PLC holds weld outputs + stable for the defined weld duration. In real systems, replace + timer with a robot "weld complete" handshake DI. +``` + +### Step 7 — Arc Off / Weld End 🔒 Safety-Locked + +``` +Sensors : Sen_ArcOff (1 sensor) +Actuators: Act_WeldEnable OFF (commanded off this step) + Act_GasValve ON (gas continues for pool protection) +Advance : Sen_ArcOff = TRUE +Lock : Safety-locked — arc extinction MUST be confirmed before motion +Purpose : Confirm the arc is truly off before allowing any mechanical + movement. Prevents weld spatter damage to optics/sensors. +``` + +### Step 8 — Post-Purge Gas ⏱ Timer + +``` +Sensors : NONE +Actuators: Act_GasValve ON +Advance : Timer T#2.5S elapsed +Purpose : Continue shielding gas flow after arc off to protect the + cooling weld pool from oxidation. +``` + +### Step 9 — Retract Weld Head + +``` +Sensors : Sen_HeadRetracted (BWD) + Sen_HeadAtWeldPos (FWD — conflict check) +Actuators: Act_HeadRetract ON, Act_HeadExtend OFF +Advance : Sen_HeadRetracted = TRUE AND Sen_HeadAtWeldPos = FALSE (BWD sensor) +Purpose : Return weld torch to safe retracted home position before + unclamp/eject. Uses the same sensor pair as Step 3. +``` + +### Step 10 — Unclamp / Part Eject + +``` +Sensors : Sen_UnclampConf (1 sensor) +Actuators: Act_Clamp OFF, Act_Unclamp ON, Act_PartEject ON +Advance : Sen_UnclampConf = TRUE → COMPLETE +Purpose : Release the finished weld assembly and fire the ejector + cylinder to clear the fixture for the next part. + On advance, state → COMPLETE, CycleCount increments. +``` + +--- + +## 9. Step Advance Types + +Three advance methods are used across the 10 steps: + +### Type A — Dual-Sensor (FWD + BWD) + +Used by: **Steps 1, 3, 9** + +```scl +// Step 3 example +_stepAdvReady := Sen_HeadAtWeldPos; // FWD sensor = advance condition +// Sen_HeadRetracted monitored separately for conflict detection +``` + +The two sensors serve different purposes: +- **FWD sensor** → advance trigger (target position reached) +- **BWD sensor** → interlock / conflict check (should be opposite state) +- Both TRUE simultaneously → **FaultCode 30** (wiring fault or sensor failure) + +### Type B — Single Sensor + +Used by: **Steps 2, 5, 7, 10** + +```scl +// Step 2 example +_stepAdvReady := Sen_ClampClosed; +``` + +Simplest form. Step activates its actuator(s) and waits for confirmation feedback. + +### Type C — Timer Only (no sensor) + +Used by: **Steps 4, 6, 8** + +```scl +// Step 4 example — timer resets automatically when step changes +_stepTimer[4](IN := (_activeStep = 4 AND _state = STATE_RUNNING), + PT := T#2S); +_stepAdvReady := _stepTimer[4].Q; +``` + +The timer `IN` is gated on `(_activeStep = N AND STATE_RUNNING)`. When the step changes, `IN` goes FALSE and the TON resets automatically — no manual reset logic required. + +--- + +## 10. Skip / Disable / Safety-Lock + +### Disable a Step (permanent skip every cycle) + +Set in the instance DB or via HMI write to `_stepEnabled[N]`: + +```scl +// Example: disable step 6 (weld travel) for a tack-weld-only mode +"DB_WeldSeq"._stepEnabled[6] := FALSE; +``` + +Disabled steps are silently skipped by the `WHILE` loop that finds the next enabled step. The step's actuator outputs are never energised. + +### Skip Current Step (operator, one-time) + +Rising edge on `Cmd_SkipStep`. The FB checks `_stepSafetyLocked[_activeStep]`: + +``` +Cmd_SkipStep (↑) ──→ Is step safety-locked? + YES → Ignore (no action, no feedback) + NO → _forceAdvance := TRUE → step advances next scan +``` + +### Safety-Locked Steps + +Set during initialisation: + +```scl +_stepSafetyLocked[1] := TRUE; // Home verify +_stepSafetyLocked[5] := TRUE; // Arc strike +_stepSafetyLocked[7] := TRUE; // Arc off +``` + +**Why lock these steps?** + +| Step | Risk if skipped | +|---|---| +| 1 — Home Verify | Clamp closes on robot arm / fixture not in position | +| 5 — Arc Strike | Weld travel with no arc = cold weld, undetected failure | +| 7 — Arc Off | Moving head while arc still live = flash, fire, damage | + +To add safety-locking to other steps, set `_stepSafetyLocked[N] := TRUE` in the `IF NOT _initDone` block. + +--- + +## 11. Fault Codes + +| Code | Name | Cause | Resolution | +|---|---|---|---| +| 0 | No fault | Normal | — | +| 10 | Safety door open | Door opened during RUN or PAUSED | Close door → `Cmd_Reset` | +| 11 | E-Stop activated | `Cmd_EStop = TRUE` or `Safety_EStopOK = FALSE` | Clear E-Stop → `Cmd_Reset` | +| 20 | CAT1 timeout | Step did not complete within `CAT1_TIMEOUT` (10 s) | Investigate stuck actuator → `Cmd_Reset` | +| 30 | Sensor conflict | `Sen_HeadAtWeldPos` AND `Sen_HeadRetracted` both TRUE | Check sensor wiring/target → `Cmd_Reset` | +| 40 | Step watchdog | Step active for > `WATCHDOG_TIME` (30 s) | Investigate jammed actuator or missing sensor → `Cmd_Reset` | + +--- + +## 12. HMI Integration + +### Recommended HMI Tags + +| HMI Tag | PLC Address | Notes | +|---|---|---| +| `SeqState` | `%MW22` | Use value display + state text list | +| `ActiveStep` | `%MW20` | Highlight active step on step diagram | +| `FaultCode` | `%MW24` | Alarm trigger with code text list | +| `CycleCount` | `%MD30` | Production counter display | +| `StepAdvanceReady` | `%M5.0` | Green indicator on each step | +| `IncrWaiting` | `%M5.1` | Flashing "Press INCR" indicator | +| `StopCategory` | `%MW10` | Selector: 0 / 1 / 2 | + +### State Text List (for `SeqState` display) + +``` +0 = "IDLE — Ready" +1 = "RUNNING" +2 = "PAUSED" +3 = "STOPPING (CAT1)" +4 = "STOPPED" +5 = "FAULTED" +6 = "CYCLE COMPLETE" +``` + +### Fault Code Alarm List + +``` +10 = "Safety door opened — close door and reset" +11 = "E-Stop activated — clear E-Stop and reset" +20 = "CAT1 stop timeout — check step actuator" +30 = "Head sensor conflict — check I0.3 and I0.4" +40 = "Step watchdog timeout — step did not complete in 30 s" +``` + +--- + +## 13. TIA Portal Setup + +### Creating the Instance DB + +1. In the project tree, right-click the program folder → **Add new block** +2. Select **Data Block** → name it `DB_WeldSeq` +3. Set the block type to **Instance DB** of `FB_WeldSequencer` +4. Compile + +### Calling the FB + +Add to your cyclic interrupt OB (e.g. `OB30` at 10 ms) or `OB1`: + +```scl +"DB_WeldSeq"( + Mode_Auto := "HMI_ModeAuto", + Mode_Incr := "HMI_ModeIncr", + Cmd_Start := "PB_Start", + Cmd_Pause := "PB_Pause", + Cmd_Stop := "PB_Stop", + Cmd_EStop := "SafetyRelay_EStop", + Cmd_Reset := "PB_Reset", + Cmd_Incr := "PB_Incr", + Cmd_SkipStep := "PB_SkipStep", + StopCategory := "HMI_StopCategory", + Safety_DoorClosed := "SafetyGate_Closed", + Safety_EStopOK := "SafetyRelay_OK", + Sen_HomeFwd := %I0.0, + Sen_HomeBwd := %I0.1, + Sen_ClampClosed := %I0.2, + Sen_HeadAtWeldPos := %I0.3, + Sen_HeadRetracted := %I0.4, + Sen_ArcDetect := %I0.5, + Sen_ArcOff := %I0.6, + Sen_UnclampConf := %I0.7, + Act_Clamp => %Q0.0, + Act_HeadExtend => %Q0.1, + Act_HeadRetract => %Q0.2, + Act_GasValve => %Q0.3, + Act_WeldEnable => %Q0.4, + Act_Unclamp => %Q0.5, + Act_PartEject => %Q0.6, + Seq_Running => %Q1.0, + Seq_Paused => %Q1.1, + Seq_Faulted => %Q1.2, + Seq_Complete => %Q1.3, + ActiveStep => %MW20, + SeqState => %MW22, + FaultCode => %MW24, + StepAdvanceReady => %M5.0, + IncrWaiting => %M5.1, + CycleCount => %MD30 ); -END_TYPE - -TYPE E_StopCat : USINT ( - STOPCAT_NONE := 0, - STOPCAT_IMMEDIATE := 1, - STOPCAT_END_OF_STEP := 2, - STOPCAT_END_OF_CYCLE := 3, - STOPCAT_NO_STOP := 4 -); -END_TYPE - -TYPE UDT_StepCfg : -STRUCT - Text : STRING[80]; // Operator text for HMI - Timeout : TIME; // Per-step timeout - IsEndOfCycle : BOOL; // Marks end-of-cycle step (e.g., step 10) - - ReqEnabled : BOOL; // From HMI/DB (operator request) - Enabled : BOOL; // PLC effective enable (used by sequencer) - SafetyLocked : BOOL; // If TRUE, PLC forces Enabled := TRUE always - - NextStep : INT; // 0 = normal next enabled step, else jump to 1..10 -END_STRUCT -END_TYPE - ------------------------------------------------------------- -3) Helper FC: Next enabled step (skip disabled steps) ------------------------------------------------------------- - -FUNCTION FC_NextEnabledStep : INT -{ S7_Optimized_Access := 'TRUE' } -VAR_INPUT - CurrentStep : INT; - MaxStep : INT; // 10 - Wrap : BOOL; // TRUE in AUTO (10->1), FALSE in INCR (end->0) - Cfg : ARRAY[1..10] OF UDT_StepCfg; -END_VAR -VAR - s : INT; - i : INT; -END_VAR -BEGIN - s := CurrentStep; - - FOR i := 1 TO MaxStep DO - s := s + 1; - - IF s > MaxStep THEN - IF Wrap THEN - s := 1; - ELSE - FC_NextEnabledStep := 0; - RETURN; - END_IF; - END_IF; - - IF Cfg[s].Enabled THEN - FC_NextEnabledStep := s; - RETURN; - END_IF; - END_FOR; - - FC_NextEnabledStep := 0; // none enabled -END_FUNCTION - ------------------------------------------------------------- -4) Main FB: Sequencer (AUTO/INCR + Pause/Stop + Stop categories) ------------------------------------------------------------- - -FUNCTION_BLOCK FB_Seq10_Adv -{ S7_Optimized_Access := 'TRUE' } - -VAR_INPUT - Enable : BOOL; - Mode_Auto : BOOL; - Mode_Incr : BOOL; - - Cmd_Start : BOOL; - Cmd_Stop : BOOL; // hard stop (safe outputs) - Cmd_Pause : BOOL; // toggle pause (freeze) - Cmd_ResetErr : BOOL; - Cmd_Next : BOOL; // NEXT pulse in increment mode - - StopReq : BOOL; // stop request flag - StopCat : E_StopCat; // stop request category - - // Example process inputs (replace with real ones) - In_Ready : BOOL; - In_ClampClosed : BOOL; - In_ProcessDone : BOOL; - In_EjectDone : BOOL; - - // Step config from DB/HMI/recipe - Cfg : ARRAY[1..10] OF UDT_StepCfg; -END_VAR - -VAR_OUTPUT - Step : INT; // 0..10 - Running : BOOL; - Paused : BOOL; - - ErrorActive : BOOL; - ErrorCode : WORD; - - HMI_StepText : STRING[80]; - HMI_StopInfo : STRING[80]; - - // Example outputs (replace) - Out_ClampClose : BOOL; - Out_ProcessOn : BOOL; - Out_Eject : BOOL; -END_VAR - -VAR - Mode : E_Mode; - - rStart : R_TRIG; - rNext : R_TRIG; - rReset : R_TRIG; - rPause : R_TRIG; - - StepPrev : INT; - StepEntry : BOOL; - - tStep : TON; - - AllowAdvance : BOOL; - - StopLatched : BOOL; - StopLatchedCat : E_StopCat; - - PauseLatched : BOOL; - Frozen_ClampClose: BOOL; - Frozen_ProcessOn : BOOL; - Frozen_Eject : BOOL; - - Cmd_ClampClose : BOOL; - Cmd_ProcessOn : BOOL; - Cmd_Eject : BOOL; - - i : INT; - nxt : INT; -END_VAR - -BEGIN - // --------- edges ---------- - rStart(CLK := Cmd_Start); - rNext(CLK := Cmd_Next); - rReset(CLK := Cmd_ResetErr); - rPause(CLK := Cmd_Pause); - - // --------- sanitize step config (prevent disabling safety steps) ---------- - // IMPORTANT: HMI should write ONLY ReqEnabled, not Enabled or SafetyLocked. - FOR i := 1 TO 10 DO - IF Cfg[i].SafetyLocked THEN - Cfg[i].Enabled := TRUE; - Cfg[i].ReqEnabled := TRUE; // reflect back to HMI (optional) - ELSE - Cfg[i].Enabled := Cfg[i].ReqEnabled; - END_IF; - END_FOR; - - // --------- reset error ---------- - IF rReset.Q THEN - ErrorActive := FALSE; - ErrorCode := WORD#0; - Step := 0; - StopLatched := FALSE; - StopLatchedCat := STOPCAT_NONE; - PauseLatched := FALSE; - END_IF; - - // --------- mode selection ---------- - IF (NOT Enable) OR Cmd_Stop OR ErrorActive THEN - Mode := MODE_STOP; - ELSIF Mode_Auto THEN - Mode := MODE_AUTO; - ELSIF Mode_Incr THEN - Mode := MODE_INCR; - ELSE - Mode := MODE_STOP; - END_IF; - - // --------- start ---------- - IF rStart.Q AND (NOT ErrorActive) THEN - IF Step = 0 THEN - // start at first enabled step - IF Cfg[1].Enabled THEN - Step := 1; - ELSE - Step := FC_NextEnabledStep(CurrentStep := 0, MaxStep := 10, Wrap := TRUE, Cfg := Cfg); - END_IF; - END_IF; - END_IF; - - // --------- latch stop request (category-aware) ---------- - IF StopReq THEN - CASE StopCat OF - STOPCAT_IMMEDIATE, STOPCAT_END_OF_STEP, STOPCAT_END_OF_CYCLE: - StopLatched := TRUE; - StopLatchedCat := StopCat; - STOPCAT_NO_STOP: - // info only; do not latch stop - ELSE - // none - END_CASE; - END_IF; - - // --------- pause toggle ---------- - IF rPause.Q THEN - PauseLatched := NOT PauseLatched; - - // capture outputs when entering pause - IF PauseLatched THEN - Frozen_ClampClose := Out_ClampClose; - Frozen_ProcessOn := Out_ProcessOn; - Frozen_Eject := Out_Eject; - END_IF; - END_IF; - - Paused := PauseLatched; - - // --------- running ---------- - Running := (Mode <> MODE_STOP) AND (Step > 0) AND (NOT ErrorActive) AND (NOT Paused); - - // --------- step entry ---------- - StepEntry := (Step <> StepPrev); - StepPrev := Step; - - // --------- HMI step text ---------- - IF (Step >= 1) AND (Step <= 10) THEN - HMI_StepText := Cfg[Step].Text; - ELSE - HMI_StepText := 'IDLE'; - END_IF; - - // --------- stop info ---------- - HMI_StopInfo := ''; - IF StopReq AND (StopCat = STOPCAT_NO_STOP) THEN - HMI_StopInfo := 'INFO: stop request is NO_STOP (alarm/info only)'; - ELSIF StopLatched THEN - CASE StopLatchedCat OF - STOPCAT_IMMEDIATE: HMI_StopInfo := 'Stop requested: IMMEDIATE'; - STOPCAT_END_OF_STEP: HMI_StopInfo := 'Stop requested: END_OF_STEP'; - STOPCAT_END_OF_CYCLE: HMI_StopInfo := 'Stop requested: END_OF_CYCLE'; - ELSE - HMI_StopInfo := 'Stop requested'; - END_CASE; - END_IF; - - // --------- if current step disabled -> jump immediately ---------- - IF (Step >= 1) AND (Step <= 10) THEN - IF NOT Cfg[Step].Enabled THEN - Step := FC_NextEnabledStep(CurrentStep := Step-1, MaxStep := 10, Wrap := (Mode = MODE_AUTO), Cfg := Cfg); - END_IF; - END_IF; - - // --------- default commanded outputs ---------- - Cmd_ClampClose := FALSE; - Cmd_ProcessOn := FALSE; - Cmd_Eject := FALSE; - - AllowAdvance := FALSE; - - // --------- step timer (does not run while paused) ---------- - IF StepEntry THEN - tStep(IN := FALSE, PT := Cfg[Step].Timeout); - END_IF; - - IF (Step >= 1) AND (Step <= 10) THEN - tStep(IN := Running, PT := Cfg[Step].Timeout); - ELSE - tStep(IN := FALSE, PT := T#0S); - END_IF; - - // --------- step logic (demo steps, replace with your real logic) ---------- - CASE Step OF - 0: - ; - - 1: // WAIT READY - IF In_Ready THEN AllowAdvance := TRUE; END_IF; - - 2: // CLOSE CLAMP - Cmd_ClampClose := TRUE; - IF In_ClampClosed THEN AllowAdvance := TRUE; END_IF; - - 3: // PROCESS - Cmd_ProcessOn := TRUE; - IF In_ProcessDone THEN AllowAdvance := TRUE; END_IF; - - 4: // EJECT - Cmd_Eject := TRUE; - IF In_EjectDone THEN AllowAdvance := TRUE; END_IF; - - 5,6,7,8,9: - // demo pass-through steps - AllowAdvance := TRUE; - - 10: // END OF CYCLE - AllowAdvance := TRUE; - - ELSE - ErrorActive := TRUE; - ErrorCode := WORD#16#9001; // invalid step - END_CASE; - - // --------- timeout -> error ---------- - IF tStep.Q AND Running THEN - ErrorActive := TRUE; - ErrorCode := WORD#16#8000 + WORD_TO_WORD(INT_TO_WORD(Step)); - Mode := MODE_STOP; - END_IF; - - // --------- stop category enforcement: immediate stop ---------- - IF StopLatched AND (StopLatchedCat = STOPCAT_IMMEDIATE) THEN - Step := 0; - StopLatched := FALSE; - StopLatchedCat := STOPCAT_NONE; - PauseLatched := FALSE; - END_IF; - - // --------- step advance ---------- - IF (NOT ErrorActive) AND (NOT Paused) THEN - - // Evaluate "advance permission" depending on mode - IF (Mode = MODE_AUTO AND AllowAdvance) - OR (Mode = MODE_INCR AND AllowAdvance AND rNext.Q) THEN - - // Handle stop-after conditions - IF StopLatched AND (StopLatchedCat = STOPCAT_END_OF_STEP) THEN - Step := 0; - StopLatched := FALSE; - StopLatchedCat := STOPCAT_NONE; - - ELSIF StopLatched AND (StopLatchedCat = STOPCAT_END_OF_CYCLE) AND Cfg[Step].IsEndOfCycle THEN - Step := 0; - StopLatched := FALSE; - StopLatchedCat := STOPCAT_NONE; - - ELSE - // Compute next step: - // 1) optional jump if NextStep configured - IF (Step >= 1) AND (Step <= 10) AND (Cfg[Step].NextStep <> 0) THEN - nxt := Cfg[Step].NextStep; - - IF (nxt >= 1) AND (nxt <= 10) AND Cfg[nxt].Enabled THEN - Step := nxt; - ELSE - ErrorActive := TRUE; - ErrorCode := WORD#16#9100; // invalid NextStep config - END_IF; - - ELSE - // 2) normal: next enabled step - nxt := FC_NextEnabledStep( - CurrentStep := Step, - MaxStep := 10, - Wrap := (Mode = MODE_AUTO), - Cfg := Cfg - ); - Step := nxt; - END_IF; - - END_IF; - END_IF; - END_IF; - - // --------- output policy: STOP vs PAUSE vs NORMAL ---------- - IF (Mode = MODE_STOP) OR (Step = 0) OR ErrorActive THEN - Out_ClampClose := FALSE; - Out_ProcessOn := FALSE; - Out_Eject := FALSE; - - ELSIF Paused THEN - Out_ClampClose := Frozen_ClampClose; - Out_ProcessOn := Frozen_ProcessOn; - Out_Eject := Frozen_Eject; - - ELSE - Out_ClampClose := Cmd_ClampClose; - Out_ProcessOn := Cmd_ProcessOn; - Out_Eject := Cmd_Eject; - END_IF; - -END_FUNCTION_BLOCK - ------------------------------------------------------------- -5) Recommended usage in OB1 ------------------------------------------------------------- - -- Create an instance DB for FB_Seq10_Adv. -- Fill Cfg[1..10] with texts/timeouts and safety locks. - -Typical values: -- Step 1: Text='Wait Ready', Timeout=T#10S, SafetyLocked=TRUE (if required) -- Step 2: Text='Close Clamp', Timeout=T#5S, SafetyLocked=TRUE -- Step 10: Text='Cycle End', Timeout=T#2S, IsEndOfCycle=TRUE - -Operator can only toggle: -- Cfg[i].ReqEnabled for optional steps (SafetyLocked=FALSE) - -Run modes: -- AUTO: Mode_Auto=TRUE -- INCR: Mode_Incr=TRUE and use Cmd_Next pulses - -Stop: -- Cmd_Stop -> immediate safe stop -- StopReq+StopCat: - - END_OF_CYCLE for "stop after part" - - END_OF_STEP for "stop after step" - - IMMEDIATE for urgent stop - - NO_STOP for warnings/info - -Pause: -- Cmd_Pause toggles pause/resume (outputs frozen + timer frozen) - ------------------------------------------------------------- -6) What to customize next (common in production) ------------------------------------------------------------- - -1) Split outputs into "Freeze on pause" and "Force safe on pause" groups. -2) Add per-step "StopAllowed" (some steps must never stop mid-step). -3) Add alarm integration with FIFO + timestamps (your previous alarm project). -4) Add step entry actions (run once on step change): - - reset internal flags - - start motion commands - - log step start time -5) Add interlocks: - - if safety chain open -> force STOPCAT_IMMEDIATE - -END OF README \ No newline at end of file +``` + +### Adjusting Step Configuration at Runtime + +Write to the instance DB directly (e.g. from HMI or during commissioning): + +```scl +// Disable step 6 (bypass weld travel for testing) +"DB_WeldSeq"._stepEnabled[6] := FALSE; + +// Change pre-purge time to 3 seconds +"DB_WeldSeq"._stepTimerPreset[4] := T#3S; + +// Enable step 6 again +"DB_WeldSeq"._stepEnabled[6] := TRUE; +``` + +> **Note:** Timer preset changes take effect on the NEXT activation of that step (TON picks up the new `PT` value when it starts). + +--- + +## 14. Adapting the Code + +### Adding More Steps + +1. Change array bounds: `Array[1..N]` in all 6 array declarations +2. Update `LAST_STEP` constant +3. Add a new `CASE` branch for each new step +4. Call additional step timers and watchdog timers explicitly + +### Replacing Timer Advance with Robot Handshake + +Step 6 uses a timer for weld travel. In a real system with a robot controller: + +```scl +// Replace timer advance in Step 6 with robot "weld complete" signal +6: + Act_WeldEnable := TRUE; + Act_GasValve := TRUE; + _stepAdvReady := Robot_WeldComplete; // Add this DI to VAR_INPUT +``` + +### Adding More Sensor Types + +For a step needing **analog threshold advance** (e.g. temperature): + +```scl +// In step logic: +_stepAdvReady := (TempSensor_mV > 4500); // Weld pool temp threshold +``` + +### Multiple Sequencer Instances + +Create multiple instance DBs for parallel lines: + +```scl +"DB_WeldSeq_Line1"(...); +"DB_WeldSeq_Line2"(...); +``` + +Each instance is completely independent with its own state, timers, and counter. + +### Changing CAT1 Timeout + +```scl +// In VAR CONSTANT section: +CAT1_TIMEOUT : Time := T#15S; // Increase for slower machinery +``` + +Or make it configurable via VAR_INPUT if different cells need different values. + +--- + +## 15. Safety Notes + +> ⚠️ **This code is a demonstration template. It does NOT constitute a validated safety function and must NOT be used as-is for CE-marked or safety-certified applications without a proper risk assessment and SISTEMA analysis.** + +### Minimum Requirements Before Deployment + +- [ ] Full HAZOP / risk assessment per **ISO 12100** +- [ ] E-Stop circuit designed to **ISO 13850** — hardware safety relay, not PLC output +- [ ] Safety door interlocks to **ISO 14119** — use safety-rated sensors +- [ ] Emergency stop category confirmed per **IEC 60204-1 Section 9.2** +- [ ] CAT1 stop implementation validated: actuators must de-energise AFTER safe position confirmed +- [ ] Dual-channel safety inputs for CAT3/PLd or higher +- [ ] Functional safety assessment if PL ≥ c required (consider SIMATIC S7-1500F / F-FB) +- [ ] Factory Acceptance Test (FAT) covering all modes, stop categories, and fault scenarios + +### Software Safety Good Practice (Applied in This Code) + +- All output variables cleared to `FALSE` at the top of every scan before step logic re-energises them — eliminates "stuck on" from removed steps +- FAULTED state drives all outputs to FALSE (Section 6 override) +- E-Stop and door monitoring execute BEFORE the state machine — highest priority +- Safety-locked steps enforce physical interlocks in software as a secondary barrier +- Sensor conflict detection for dual-sensor pairs +- Per-step watchdog timers catch hung steps before operators notice + +--- + +## Changelog + +| Version | Date | Notes | +|---|---|---| +| 0.1 | 2025 | Initial release — 10-step welding cell demo | + +--- + +## License + +MIT License — free to use and adapt for commercial or personal projects. Attribution appreciated but not required. + +--- + +*Generated for S7-1500 / TIA Portal V18+. Tested syntax against SCL compiler rules. Always perform a full offline simulation before deploying to hardware.* \ No newline at end of file