(*═══════════════════════════════════════════════════════════════════════════════ DEMO_WeldCellIntegration.scl ───────────────────────────────────────────────────────────────────────────── Demonstrates FB_CylinderMonitor instances for all 4 sensor configurations wired into the FB_WeldSequencer from the welding cell demo. CYLINDERS IN THIS DEMO: ┌──────┬───────────────────────┬──────────────┬────────────────────────────┐ │ Inst │ Cylinder │ SensorConfig │ Notes │ ├──────┼───────────────────────┼──────────────┼────────────────────────────┤ │ DB1 │ Clamp Cylinder │ ONE_FWD (1) │ Only clamp-closed sensor │ │ DB2 │ Weld Head │ TWO (3) │ Extended + retracted sensor │ │ DB3 │ Part Ejector │ ONE_BWD (2) │ Only retracted (home) sensor│ │ DB4 │ Gas Purge Valve │ NONE (0) │ No position sensor, timer │ └──────┴───────────────────────┴──────────────┴────────────────────────────┘ RESPONSE CONFIGURATION: Timeout faults → PAUSE machine (operator can clear & resume) Conflict faults → STOP machine (requires Reset before restart) Lost position → STOP machine (requires Reset before restart) CALL ORDER in OB (important — monitors must execute BEFORE sequencer): 1. FB_CylinderMonitor instances (DB1..DB4) 2. FB_CylFaultCollector (DB_CylFaults) 3. FB_WeldSequencer (DB_WeldSeq) ═══════════════════════════════════════════════════════════════════════════════*) //───────────────────────────────────────────────────────────────────────────── // INSTANCE DB DECLARATIONS (create these in TIA Portal project tree) // // DB_CylClamp : FB_CylinderMonitor // DB_CylHead : FB_CylinderMonitor // DB_CylEject : FB_CylinderMonitor // DB_CylGas : FB_CylinderMonitor // DB_CylFaults : FB_CylFaultCollector // DB_WeldSeq : FB_WeldSequencer //───────────────────────────────────────────────────────────────────────────── //═════════════════════════════════════════════════════════════════════════════ // CYLINDER 1 — CLAMP (ONE_FWD: only clamp-closed sensor at FWD end) // ───────────────────────────────────────────────────────────────────────── // Physical setup: // Proximity sensor mounted at closed (extended) jaw position ONLY. // No sensor at open position — we assume open if no clamp command active. // // Error logic: // Cmd_Fwd (clamp) active → Sen_Fwd (clamp closed) not confirmed in 2 s // → FaultCode 1 (FWD timeout) → machine PAUSE // Sen_Fwd unexpectedly active with no command? → Not detected (ONE_FWD limit) // // Advance in sequencer: // Step 2 advance condition: DB_CylClamp.AtFwd //═════════════════════════════════════════════════════════════════════════════ "DB_CylClamp"( CylName := 'Clamp Cylinder', SensorConfig := 1, // ONE_FWD T_Timeout := T#2S, // 2 second fault timeout Cmd_Fwd := "DB_WeldSeq".Act_Clamp, // Sequencer output drives FWD Cmd_Bwd := NOT "DB_WeldSeq".Act_Clamp AND NOT "DB_WeldSeq".Seq_Faulted, // Bwd inferred: not clamped & not faulted Cmd_Reset := "PB_Reset", Sen_Fwd := %I0.2, // Sen_ClampClosed hardware input Sen_Bwd := FALSE, // No sensor at open position Enable := "DB_WeldSeq".Seq_Running OR "DB_WeldSeq".Seq_Paused ); //═════════════════════════════════════════════════════════════════════════════ // CYLINDER 2 — WELD HEAD (TWO sensors: extended + retracted) // ───────────────────────────────────────────────────────────────────────── // Physical setup: // Sensor at fully extended (weld position) = Sen_Fwd → %I0.3 // Sensor at fully retracted (safe position) = Sen_Bwd → %I0.4 // // Error logic: // Extend cmd → Sen_Fwd not confirmed in 3 s → FaultCode 1 → PAUSE // Retract cmd → Sen_Bwd not confirmed in 3 s → FaultCode 2 → PAUSE // Both sensors TRUE simultaneously → FaultCode 3 → STOP // Sensors both drop with no command active → FaultCode 4 (lost) → STOP // // Advance in sequencer: // Step 3 advance: DB_CylHead.AtFwd // Step 9 advance: DB_CylHead.AtBwd // // NOTE: Extend and Retract are separate solenoid outputs (bistable valve) // CylCmd_FwdSafe → Act_HeadExtend solenoid // CylCmd_BwdSafe → Act_HeadRetract solenoid //═════════════════════════════════════════════════════════════════════════════ "DB_CylHead"( CylName := 'Weld Head', SensorConfig := 3, // TWO sensors T_Timeout := T#3S, // 3 seconds (head travel takes longer) Cmd_Fwd := "DB_WeldSeq".Act_HeadExtend, Cmd_Bwd := "DB_WeldSeq".Act_HeadRetract, Cmd_Reset := "PB_Reset", Sen_Fwd := %I0.3, // Sen_HeadAtWeldPos Sen_Bwd := %I0.4, // Sen_HeadRetracted Enable := "DB_WeldSeq".Seq_Running OR "DB_WeldSeq".Seq_Paused OR "DB_WeldSeq".Seq_Stopping ); // ── Wire safe outputs back to physical DQs ─────────────────────────────── %Q0.1 := "DB_CylHead".CylCmd_FwdSafe; // Act_HeadExtend (gated) %Q0.2 := "DB_CylHead".CylCmd_BwdSafe; // Act_HeadRetract (gated) //═════════════════════════════════════════════════════════════════════════════ // CYLINDER 3 — PART EJECTOR (ONE_BWD: only home/retracted sensor) // ───────────────────────────────────────────────────────────────────────── // Physical setup: // The ejector fires forward (extends) to push the part out. // Sensor only at retracted (home) end — confirms ejector is clear/home. // No sensor at extended (ejected) position. // // Error logic: // Retract cmd (home return) → Sen_Bwd not confirmed in 1.5 s // → FaultCode 2 (BWD timeout) → PAUSE // Eject (FWD) cmd: no FWD sensor, so no timeout — just fires blind. // After timer completes in sequencer, retract command issued. // // Advance in sequencer: // Step 10 advance uses Sen_UnclampConf (%I0.7) which is separate. // After cycle complete, this FB confirms ejector is home before next cycle. //═════════════════════════════════════════════════════════════════════════════ "DB_CylEject"( CylName := 'Part Ejector', SensorConfig := 2, // ONE_BWD T_Timeout := T#1500MS, Cmd_Fwd := "DB_WeldSeq".Act_PartEject, Cmd_Bwd := NOT "DB_WeldSeq".Act_PartEject AND "DB_WeldSeq".Seq_Complete, Cmd_Reset := "PB_Reset", Sen_Fwd := FALSE, // No sensor at ejected position Sen_Bwd := %I0.7, // Ejector home sensor (shared / Sen_UnclampConf area) Enable := TRUE // Always enabled ); //═════════════════════════════════════════════════════════════════════════════ // CYLINDER 4 — GAS PURGE VALVE (NONE: no position sensors) // ───────────────────────────────────────────────────────────────────────── // Physical setup: // Simple solenoid valve — open or closed. // No position feedback — valve assumed open when energised. // No fault can be generated from position sensors (none exist). // // Error logic: // NONE: the FB passes the command through, reports AT_FWD when commanded // On/Off confirmed only by timer in the sequencer (Steps 4, 6, 8). // // NOTE: A pressure switch or flow sensor could be added here in future. // Connect it to Sen_Fwd and change SensorConfig to ONE_FWD. //═════════════════════════════════════════════════════════════════════════════ "DB_CylGas"( CylName := 'Gas Purge Valve', SensorConfig := 0, // NONE T_Timeout := T#500MS, // Not used with NONE config (no timers start) Cmd_Fwd := "DB_WeldSeq".Act_GasValve, Cmd_Bwd := FALSE, // Single-acting valve — spring return Cmd_Reset := "PB_Reset", Sen_Fwd := FALSE, Sen_Bwd := FALSE, Enable := TRUE ); //═════════════════════════════════════════════════════════════════════════════ // FAULT COLLECTOR — Aggregates all 4 cylinder faults // Outputs feed directly into the sequencer Cmd_Pause / Cmd_Stop inputs //═════════════════════════════════════════════════════════════════════════════ "DB_CylFaults"( //── Fault bits ─────────────────────────────────────────────────────────── Cyl1_Fault := "DB_CylClamp".Fault_Active, Cyl2_Fault := "DB_CylHead".Fault_Active, Cyl3_Fault := "DB_CylEject".Fault_Active, Cyl4_Fault := "DB_CylGas".Fault_Active, Cyl5_Fault := FALSE, Cyl6_Fault := FALSE, Cyl7_Fault := FALSE, Cyl8_Fault := FALSE, //── Fault codes ─────────────────────────────────────────────────────────── Cyl1_FaultCode := "DB_CylClamp".FaultCode, Cyl2_FaultCode := "DB_CylHead".FaultCode, Cyl3_FaultCode := "DB_CylEject".FaultCode, Cyl4_FaultCode := "DB_CylGas".FaultCode, Cyl5_FaultCode := 0, Cyl6_FaultCode := 0, Cyl7_FaultCode := 0, Cyl8_FaultCode := 0, //── HMI fault texts ─────────────────────────────────────────────────────── Cyl1_FaultText := "DB_CylClamp".HMI_FaultText, Cyl2_FaultText := "DB_CylHead".HMI_FaultText, Cyl3_FaultText := "DB_CylEject".HMI_FaultText, Cyl4_FaultText := "DB_CylGas".HMI_FaultText, //── Machine response policy ─────────────────────────────────────────────── // Timeout → PAUSE (1): operator can check & reset, then resume // Conflict → STOP (2): two sensors TRUE = hardware fault, needs investigation // Lost pos → STOP (2): cylinder moved undetected = mechanical issue Response_Timeout := 1, Response_Conflict := 2, Response_Lost := 2 ); //═════════════════════════════════════════════════════════════════════════════ // WELDING SEQUENCER — Wired with cylinder feedback and fault injection //═════════════════════════════════════════════════════════════════════════════ "DB_WeldSeq"( //── Mode & commands ───────────────────────────────────────────────────── Mode_Auto := %I2.0, Mode_Incr := %I2.1, Cmd_Start := %I1.4, Cmd_Reset := "PB_Reset", // ── PAUSE: operator button OR cylinder fault requesting pause ────────── Cmd_Pause := %I1.5 OR "DB_CylFaults".Cmd_MachinePause, // ── STOP: operator button OR cylinder fault requesting stop ─────────── Cmd_Stop := %I1.6 OR "DB_CylFaults".Cmd_MachineStop, Cmd_EStop := %I1.2, Cmd_Incr := %I1.7, Cmd_SkipStep := %I2.2, StopCategory := %MW10, //── Safety inputs ──────────────────────────────────────────────────────── Safety_DoorClosed := %I1.1, Safety_EStopOK := %I1.0, //── Sensors — using GATED outputs from cylinder monitors where possible ── // Sequencer only sees "AtFwd/AtBwd" from healthy, confirmed cylinders. // If cylinder monitor is faulted, AtFwd/AtBwd → FALSE → step never // advances → watchdog trips → sequencer also faults. Belt & braces. Sen_HomeFwd := %I0.0, // No cylinder monitor (robot) Sen_HomeBwd := %I0.1, // Step 2 clamp — uses cylinder monitor's AtFwd (confirmed clamp closed) Sen_ClampClosed := "DB_CylClamp".AtFwd, // ← From monitor, not raw DI // Steps 3 & 9 — weld head FWD/BWD (from monitor) Sen_HeadAtWeldPos := "DB_CylHead".AtFwd, // ← Confirmed extended Sen_HeadRetracted := "DB_CylHead".AtBwd, // ← Confirmed retracted Sen_ArcDetect := %I0.5, Sen_ArcOff := %I0.6, // Step 10 unclamp (ejector home or unclamp sensor) Sen_UnclampConf := "DB_CylEject".AtBwd, // ← Ejector home confirmed //── Actuator outputs ───────────────────────────────────────────────────── // NOTE: Act_HeadExtend and Act_HeadRetract go through the head cylinder // monitor's gated outputs (see %Q assignments above). // Act_Clamp goes direct here — the monitor checks it on its own scan. Act_Clamp => %Q0.0, Act_HeadExtend => "DB_CylHead_CmdFwd_Raw", // Internal tag; monitor gates it to %Q0.1 Act_HeadRetract => "DB_CylHead_CmdBwd_Raw", // Internal tag; monitor gates it to %Q0.2 Act_GasValve => %Q0.3, Act_WeldEnable => %Q0.4, Act_Unclamp => %Q0.5, Act_PartEject => %Q0.6, //── Status outputs ─────────────────────────────────────────────────────── 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 ); //═════════════════════════════════════════════════════════════════════════════ // HMI WIRING SUMMARY // Wire these tags to your WinCC/Comfort panel for operator guidance: // // TAG SOURCE HMI ELEMENT // ───────────────────────────────────────────────────────────────────────── // DB_WeldSeq.ActiveStep → %MW20 Step indicator (1-10) // DB_WeldSeq.SeqState → %MW22 State text list // DB_WeldSeq.FaultCode → %MW24 Sequencer alarm // DB_CylFaults.FirstFaultText First fault banner text // DB_CylFaults.CylFaultWord Cylinder fault bitmask (overview) // DB_CylFaults.ActiveFaultCount Number of active faults // DB_CylClamp.CylState Clamp position indicator // DB_CylClamp.HMI_StatusText Clamp status string // DB_CylHead.CylState Head position indicator // DB_CylHead.HMI_StatusText Head status string // DB_CylEject.CylState Ejector status // DB_CylHead.Moving Moving animation trigger // DB_CylFaults.Cmd_Warning → %Q1.4 Amber warning lamp // DB_WeldSeq.Seq_Faulted → %Q1.2 Red fault lamp // DB_WeldSeq.IncrWaiting → %M5.1 "Press INCR" flashing indicator //═════════════════════════════════════════════════════════════════════════════