← Safety Interlocks and E-Stop on a Raspberry PLC
Fuse test benchRaspberry PLC 19RGPIOSafety
Safety Interlocks and E-Stop on a Raspberry PLC — full example
Implement fail-safe interlocks in Python on a Raspberry PLC: emergency stop, blown-fuse chain and end-of-test inputs that cut power and latch a red beacon.
Complete, runnable program for the Raspberry PLC 19R (safety-interlocks-emergency-stop.py): wiring header, requirements and integration notes included.
Download the full project pack — freeThis example + the related ones + bill of materials
Read-only preview.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
COMPLETE EXAMPLE — Safety interlocks: emergency stop and microfuses
Equipment: Raspberry PLC 19R (Industrial Shields)
Based on: fuse test bench project
Wiring (PLC digital inputs):
I0.0 Protection microfuse chain (closed = OK)
I0.2 Emergency stop button (NC: open = emergency)
I0.3 End-of-test signal from the programmable supply
R0.8 Red beacon (relay)
R0.1 Green beacon (relay)
Requirements:
pip3 install python3-librpiplc # Industrial Shields rpiplc library
pip3 install pyserial
Integration with the catalog:
- check_interlocks() is called inside the 500 ms loop of the
test sequences (fuse-test-sequences.py).
- The supply cut-off reuses the SCPI driver
(sorensen-scpi-power-supply-control.py).
"""
import time
from rpiplc_lib import rpiplc
# --- Bench I/O map -----------------------------------------------------------
I_MICROFUSES = "I0.0" # microfuse chain protecting the electronics
I_EMERGENCY_STOP = "I0.2" # NC mushroom button on the bench front panel
I_SUPPLY_TEST_END = "I0.3" # the Sorensen XG signals end of test
R_GREEN_BEACON = "R0.1"
R_RED_BEACON = "R0.8"
def init_plc():
rpiplc.init("RPIPLC_19R")
for pin in (I_MICROFUSES, I_EMERGENCY_STOP, I_SUPPLY_TEST_END):
rpiplc.pin_mode(pin, rpiplc.INPUT)
for pin in (R_GREEN_BEACON, R_RED_BEACON):
rpiplc.pin_mode(pin, rpiplc.OUTPUT)
rpiplc.digital_write(pin, rpiplc.LOW)
def check_interlocks():
"""Return None if everything is fine, or the reason to stop.
Fail-safe philosophy: any signal outside its resting state stops
the test. An open NC emergency stop, a blown microfuse or the
supply's end-of-test signal all have the same effect: stop.
"""
if rpiplc.digital_read(I_MICROFUSES) == 0:
return "MICROFUSE BLOWN (I0.0)"
if rpiplc.digital_read(I_EMERGENCY_STOP) == 0:
return "EMERGENCY STOP PRESSED (I0.2)"
if rpiplc.digital_read(I_SUPPLY_TEST_END) == 1:
return "END OF TEST SIGNALED BY THE SUPPLY (I0.3)"
return None
def safe_stop(supply, reason):
"""Stop sequence: cut power first, signal afterwards."""
print("\n*** SAFETY STOP: %s ***" % reason)
if supply is not None:
supply.output(False) # 1) cut the supply output
rpiplc.digital_write(R_GREEN_BEACON, rpiplc.LOW)
rpiplc.digital_write(R_RED_BEACON, rpiplc.HIGH) # 2) red beacon steady
def wait_for_reset():
"""Rearming is not allowed until ALL signals are back at rest."""
print("Waiting for reset (release emergency stop / replace microfuse)...")
while check_interlocks() is not None:
time.sleep(0.2)
rpiplc.digital_write(R_RED_BEACON, rpiplc.LOW)
print("Interlocks at rest. Bench ready.")
def main():
init_plc()
supply = None # here you would use SorensenXG() from the catalog SCPI module
print("Interlock supervision active (100 ms loop). Ctrl+C to exit.")
rpiplc.digital_write(R_GREEN_BEACON, rpiplc.HIGH) # bench running
try:
while True:
reason = check_interlocks()
if reason is not None:
safe_stop(supply, reason)
wait_for_reset()
rpiplc.digital_write(R_GREEN_BEACON, rpiplc.HIGH)
time.sleep(0.1)
except KeyboardInterrupt:
safe_stop(supply, "manual program exit")
if __name__ == "__main__":
main()
Download the full project pack — freeThis example + the related ones + bill of materials