PLC与Raspberry Pi信号交互触发Python脚本循环运行方案咨询
PLC触发树莓派执行脚本实现方案
硬件连接要点
- 优先确认PLC输出类型:如果是继电器干接点输出,接线最简单最安全,直接将输出两端分别接树莓派选定的GPIO引脚、GND引脚即可,不需要额外电平转换。
- 如果是晶体管型24V输出,必须加装24V转3.3V光耦隔离模块,绝对不能直接把24V信号接到树莓派GPIO上,否则会直接烧毁引脚甚至整板;光耦还能隔绝工厂现场的电磁干扰,大幅降低死机、误触发概率。
- 接线时必须保证PLC侧和树莓派侧共地,否则电平参考不一致,会出现信号检测不准的问题;GPIO引脚优先选没有默认复用I2C、SPI功能的通用引脚,比如BCM编码的17号引脚,避免和其他硬件功能冲突。
软件实现核心逻辑
不要用轮询扫引脚的方式,资源占用高响应还慢,直接用GPIO边沿中断做触发,同时加两层防护避免异常:
- 第一层是硬件/软件防抖,过滤PLC触点抖动、电磁干扰产生的尖峰误触发信号。
- 第二层是运行状态锁,脚本执行过程中直接忽略新的触发请求,避免重复启动脚本占满系统资源,等当前工作周期完全结束、脚本退出后再释放锁,回到等待状态。
- 依赖安装直接执行命令:
sudo apt update && sudo apt install python3-rpi.gpio,不需要额外装第三方库;把运行监听服务的用户加入gpio组就能访问GPIO,不用长期用root权限跑服务,命令是sudo usermod -aG gpio 你的当前用户名。
参考实现代码
将下面的代码保存为plc_listener.py,记得修改里面的引脚号、目标脚本路径为你自己的实际配置:
import RPi.GPIO as GPIO import subprocess import time import threading # 配置参数 TRIGGER_PIN = 17 # 对应BCM编码的GPIO引脚号 BOUNCE_DURATION = 200 # 防抖时长,单位毫秒 WORK_SCRIPT_PATH = "/home/pi/your_preset_work.py" # 要触发的Python脚本绝对路径 # 运行锁,防止重复执行 task_running = False def execute_work_script(): global task_running try: # 调用子进程执行目标脚本,阻塞等待执行完成 exec_result = subprocess.run( ["python3", WORK_SCRIPT_PATH], capture_output=True, text=True ) print(f"[{time.ctime()}] 工作脚本执行结束,返回码:{exec_result.returncode}") if exec_result.returncode != 0: print(f"脚本异常信息:{exec_result.stderr}") finally: # 无论脚本正常结束还是抛错,都释放运行锁,避免服务卡死 task_running = False def trigger_handle(channel): global task_running # 短延时后二次确认电平,过滤短脉冲干扰 time.sleep(0.05) if GPIO.input(channel) == GPIO.HIGH and not task_running: task_running = True print(f"[{time.ctime()}] 检测到PLC触发信号,启动工作流程") # 开独立子线程跑任务,不阻塞GPIO中断监听 task_thread = threading.Thread(target=execute_work_script, daemon=True) task_thread.start() if __name__ == "__main__": try: GPIO.setmode(GPIO.BCM) # 配置引脚为输入模式,默认下拉,触发时输入高电平 GPIO.setup(TRIGGER_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # 注册上升沿中断触发 GPIO.add_event_detect( TRIGGER_PIN, GPIO.RISING, callback=trigger_handle, bouncetime=BOUNCE_DURATION ) print("监听服务启动,等待PLC触发信号...") # 主线程保活 while True: time.sleep(1) except KeyboardInterrupt: print("服务被手动终止") finally: GPIO.cleanup()
开机自启配置
用systemd托管监听服务是最稳的方式,开机自动启动,服务异常退出还能自动拉起,不要用老旧的rc.local方案:
- 新建服务配置文件,执行命令:
sudo nano /etc/systemd/system/plc_listen.service - 写入以下配置,把用户名、脚本路径替换成你的实际值:
[Unit] Description=PLC Signal Listener Service After=multi-user.target [Service] User=pi WorkingDirectory=/home/pi ExecStart=/usr/bin/python3 /home/pi/plc_listener.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
- 执行以下命令加载配置、设置开机自启并启动服务:
sudo systemctl daemon-reload sudo systemctl enable plc_listen.service sudo systemctl start plc_listen.service
- 实时查看服务运行日志用命令:
journalctl -u plc_listen.service -f,出问题直接看日志排查。
常见避坑点
- 光耦隔离必须加,工厂现场电磁环境复杂,没隔离的话树莓派很容易死机、误触发,甚至被浪涌打坏。
- 你自己写的业务工作脚本不要写死无限循环,必须保证一个工作周期结束后能正常退出,否则运行锁会一直被占用,后续触发信号不会有响应。
- 如果需要给PLC反馈工作状态,可以多接一个GPIO引脚连到PLC输入点,脚本启动时输出高电平、执行完成后输出低电平,PLC就能实时知道树莓派当前是忙还是空闲,避免重复发信号。
- 不要把防抖时间设太短,一般PLC继电器触点抖动在几十毫秒级,设200ms足够过滤,不会影响正常响应速度。
内容的提问来源于stack exchange,提问作者dsp
相关产品推荐
相关产品推荐

