Appearance
Cookbook: Conveyor Start Interlock in Ladder Logic
Last updated
License feature: Ladder LogicLine 2's infeed conveyor may only start when the E-stop circuit is healthy, the guard is closed, air pressure is at least 85 psi, the downstream machine isn't blocked and the PLC is communicating. Operators request start and stop from a dashboard. This recipe computes the permissive in Scada.Ink ladder logic and passes a run permit and a heartbeat to the PLC.
Warning: This is an operational permissive, not a safety function. E-stops and guards must be wired through safety-rated hardware in the machine. Scada.Ink logic runs on a general-purpose appliance, shares a thread with the web server, and a stopped task leaves its outputs as they were.
What shapes the design
Ladder can't write to a PLC tag the appliance is already reading. For such a tag, a ladder output only changes the value Scada.Ink shows until the next poll replaces it; the PLC isn't written. See Tags and Addresses. So the logic writes Local Tags, and a workflow copies them to the PLC once a second — the documented workaround.
Start/stop uses latch and unlatch rungs. A classic seal-in rung (Start in parallel with a Run contact) can also be drawn with a parallel branch (see The Ladder Editor); this recipe keeps the latch form because each rung then reads on its own in Monitor mode. See Common Ladder Patterns.
The signals
Line 2 PLC — Modbus TCP at 10.20.2.40, register map (zero-based holding registers):
Tag path (register name) | Address | Direction | Meaning |
|---|---|---|---|
L2/EStopOK | 0 | read | 1 = E-stop circuit healthy |
L2/GuardClosed | 1 | read | 1 = infeed guard closed |
L2/AirPressure_x10 | 2 | read | psi × 10 (850 = 85.0 psi) |
L2/DownstreamBlocked | 3 | read | 1 = downstream machine full or faulted |
L2/ConveyorPermit | 10 | write | 1 = Scada.Ink permits running |
L2/Heartbeat | 11 | write | Counts up once a second while the logic runs |
Local Tags (create on the Local Tags page, all int, default 0, Persist unticked):
| Tag Path | Written by | Purpose |
|---|---|---|
Line2/StartReq | Dashboard button | Operator start request; ladder clears it |
Line2/StopReq | Dashboard button | Operator stop request; ladder clears it |
Line2/ConveyorPermit | Ladder | The permit, copied to the PLC |
Line2/Heartbeat | Ladder | The heartbeat, copied to the PLC |
Line2/Booted | Ladder | 0 after every restart; lets the logic drop the permit at start-up |
Step 1: Add the PLC
- Devices → Add Device → Modbus TCP: Device Name
Line 2 PLC, IP Address10.20.2.40, Port502, Polling Rate (ms)250, tick Allow Tag Writes → Create Device. - Set the register map through the API (Advanced Driver Settings):
json
{
"driverConfig": {
"registers": [
{ "name": "L2/EStopOK", "address": 0, "type": "hr", "data_type": "int" },
{ "name": "L2/GuardClosed", "address": 1, "type": "hr", "data_type": "int" },
{ "name": "L2/AirPressure_x10", "address": 2, "type": "hr", "data_type": "int" },
{ "name": "L2/DownstreamBlocked", "address": 3, "type": "hr", "data_type": "int" },
{ "name": "L2/ConveyorPermit", "address": 10, "type": "hr", "data_type": "int" },
{ "name": "L2/Heartbeat", "address": 11, "type": "hr", "data_type": "int" }
]
}
}- Disconnect / Connect, then Browse Tags → tick all six → Subscribe Selected. The two output registers are subscribed only so the workflow's tag picker can offer them and you can see what the PLC holds; the ladder must never use them.
Step 2: Create the task
- Ladder Logic → New Task: Task Name
Line 2 Interlocks, Scan Mode Periodic, Period (ms)100→ Create. - In Routines, Add Program →
Conveyor. It gets a Main routine. - Gear (Task Settings) → tick Enabled → Save, so the task starts again after a restart.
Step 3: Enter the rungs
For each rung: Add Rung, click the rung, click instructions in the palette (each is added at the right-hand end), then click each element and set its operands. B_… and N_… are Program Tag addresses (type them in the box). Paths with a slash are Device Tag operands picked with Browse: Line2/… on Local Tags, L2/… and _STATUS/Connected on Line 2 PLC.
| Rung | Elements, left to right | Purpose |
|---|---|---|
| 1 | XIO Line2/Booted → OTU B_Run → OTU Line2/ConveyorPermit → OTL Line2/Booted | First scan after a restart: drop the run bit and the permit |
| 2 | XIC _STATUS/Connected → XIC L2/EStopOK → XIC L2/GuardClosed → GEQ Source A L2/AirPressure_x10, Source B Literal 850 → XIO L2/DownstreamBlocked → OTE B_Permissive | The permissive: all conditions in series |
| 3 | XIC Line2/StartReq → XIC B_Permissive → OTL B_Run | Start only if permitted |
| 4 | XIC Line2/StartReq → OTU Line2/StartReq | Clear the start request |
| 5 | XIC Line2/StopReq → OTU B_Run | Stop |
| 6 | XIC Line2/StopReq → OTU Line2/StopReq | Clear the stop request |
| 7 | XIO B_Permissive → OTU B_Run | Any interlock lost drops the run bit |
| 8 | OSR B_Run → OTL Line2/ConveyorPermit | Publish the permit on the rising edge only |
| 9 | OSF B_Run → OTU Line2/ConveyorPermit | …and on the falling edge |
| 10 | XIO B_Pulse → TON Preset (ms) 1000 → OTE B_Pulse | One-second pulse |
| 11 | XIC B_Pulse → ADD Source A N_Heartbeat, Source B Literal 1, Destination N_Heartbeat → MOV Source N_Heartbeat, Destination Line2/Heartbeat | Heartbeat once a second |
| 12 | GEQ N_Heartbeat ≥ Literal 30000 → CLR N_Heartbeat | Keep it inside a 16-bit register |
Click Save, then Run.
Why it's built this way:
- Rung order is the priority. Stop (rung 5) and the interlock (rung 7) come after start (rung 3), so if start and stop arrive in the same scan, stop wins.
- Requests are cleared by the logic. Device-tag and Local Tags values are read at the start of the scan and written at the end, so rung 3 still sees the request that rung 4 clears.
- Program tags change immediately, so the OSR/OSF in rungs 8–9 see
B_Runchange in the same scan. Publishing only on edges keeps Local Tags writes rare; an OTE on a local tag would write it ten times a second. - Restart behavior.
B_Runis restored from saved state after a restart, so on its own the permit could come straight back.Line2/Bootedis not persistent, so it is 0 after every restart and rung 1 drops the run bit: the conveyor needs a fresh start request. _STATUS/Connecteddrops the permissive if the PLC stops communicating. Otherwise the logic would keep using the last values it received, because ladder ignores tag quality.
Step 4: Copy the permit and heartbeat to the PLC
- Workflows → New Workflow →
Line 2 permit to PLC→ Create. - Add and wire, in order:
| Node | Settings |
|---|---|
| Schedule | Type Interval, Interval (ms) 1000 |
| Set Tag | Tag Path Line 2 PLC → L2/ConveyorPermit; Value Source From another tag; Source Device Local Tags; Source Tag Line2/ConveyorPermit |
| Set Tag | Tag Path Line 2 PLC → L2/Heartbeat; Value Source From another tag; Source Device Local Tags; Source Tag Line2/Heartbeat |
- Save, then set it to Enabled.
Don't use a Tag Change trigger on the local tags here. A schedule rewrites the PLC every second whatever happened, so a PLC that restarts gets the current permit within a second.
Note: Set Tag does not report a write the device refuses — the run still shows as completed. That's why the PLC checks the heartbeat rather than trusting that the permit was delivered.
Step 5: PLC side
In the PLC program:
- Run the conveyor only while
ConveyorPermit(register 10) = 1 and the heartbeat (register 11) has changed within the last 3 seconds. - If the heartbeat stops changing, drop the run output. This covers a stopped ladder task, a stopped workflow, a crashed appliance and a network break — Stop in Scada.Ink leaves
Line2/ConveyorPermitat its last value, so the heartbeat is what makes the PLC safe to rely on. - Keep the hardwired E-stop and guard circuits in the safety relay regardless.
Step 6: Operator buttons and status
On the Line 2 dashboard:
| Widget | Settings |
|---|---|
| Button "Start conveyor" | Action Write Tag, Write Tag Line2/StartReq, Write Value 1, Color green |
| Button "Stop conveyor" | Action Write Tag, Write Tag Line2/StopReq, Write Value 1, Color red |
| Status "Permit" | value → Line2/ConveyorPermit; rules = equals 1 → PERMITTED green, = equals 0 → NOT PERMITTED gray |
| Value "Heartbeat" | value → Line2/Heartbeat |
| Status "Guard" | value → L2/GuardClosed; equals 1 → Closed green, equals 0 → OPEN red |
| Value "Air" | value → L2/AirPressure_x10; Multiply by 0.1, Unit psi, Decimals 1 |
Operators can press Write Tag buttons (operator role is enough). They could also press a button that starts or stops the ladder task itself; to prevent that, switch the task to Restricted and grant run only to the people who should.
Step 7: Test before connecting the conveyor
There's no force function. With the PLC's run output disabled:
- Open the editor in Monitor mode. Rung 2 is green up to the first false condition.
- Open the guard: rung 2's XIC
L2/GuardClosedgoes gray,B_Permissivedrops, rung 7 unlatchesB_Run, and within a second the PLC's register 10 reads 0. - Close the guard and press Start conveyor:
Line2/StartReqgoes 1 then back to 0, the permit goes to 1. - Press Stop conveyor and check the permit drops.
- Stop the task with Stop: the permit stays 1 in Scada.Ink, the heartbeat stops, and the PLC must drop the run output within 3 seconds.
- Restart the Scada.Ink service: after it comes back, the permit is 0 until someone presses Start.
To test a condition you can't create physically, temporarily bind that contact to a Local Tags test tag and toggle it from a dashboard, then bind it back and Save.
Timing
| Path | Worst case |
|---|---|
| Guard opens → PLC register updated | Modbus poll (250 ms) + ladder scan (100 ms) + workflow interval (1 s) ≈ 1.4 s |
| Scada.Ink stops → PLC drops run | Heartbeat timeout in the PLC (3 s) |
Anything that must react faster than that belongs in the PLC.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Coil looks on in Monitor but the PLC register doesn't change | The ladder wrote a PLC tag directly | Write Line2/… on Local Tags; let the workflow copy it |
| Permit never goes to 1 | A permissive input false, or _STATUS/Connected false | Follow rung 2 in Monitor to the first gray element |
| Start request stays at 1 | Task not running, or rung 4 bound to a different tag | Check the task status and the operand |
| PLC register 10 doesn't follow the local tag | Workflow disabled, Allow Tag Writes off (Write access not enabled for device … in History), or wrong source tag | Check the workflow's History and the device settings |
| Task stopped after a restart | Enabled not ticked in Task Settings | Tick it and Save |
| Heartbeat stuck | Task stopped or faulted | Check the status bar for a fault |
| Dashboard Start button: "Local tag not found" | Line2/StartReq not created | Create it on the Local Tags page |