• 【树莓派】Python开发工控机急停设计


    背景

    我们在一些工业产品中使用树莓派替代了PLC和上位机,并借助树莓派的算力将AI和机器视觉引入工业领域。
    以前的产品都不存在动作机构,仅仅将结果输出到指示灯、蜂鸣器或者显示器上,没有安全隐患,
    现在引入了动作机构,需要根据结果驱动设备执行一定的动作,动作机构的引入,增加了产品的安全隐患,比如可能会夹手,撞机等。为此我们需要设计额外的保护程序,其中最重要的是急停功能的实现。

    要求

    • 急停信号优先级最高,任何情况下按下急停都应该马上停止

    问题分析

    • 动作机构由24V供电,急停开关串联在电源上,可以做到开关按下后,动作机构断电。(急停开关都带有锁定机构,按下后不会弹起,会保持按下状态)
    • 树莓派独立于动作机构供电,急停开关按下后,树莓派收到信号,开始终止程序,之后一直监听急停按钮信号。
    • Python一般情况下是单线程运行,为了及时响应急停,需要将急停功能做成主进程,业务动作逻辑作为子进程,当监听到急停信号后,马上终止子进程

    设计思路

    • 择子进程而不是子线程的原因为:Python中子线程无法发送kill信号,没有很好的办法干预子线程的行为(除非每一步都判断一下,会造成代码复杂度升高),而子进程可以直接发送terminate信号杀死。
    • 急停使用低电平触发原因为:我们认为低电平是一个稳定的状态,高电平不是一个稳定的状态,比如由于某种原因导致断电,那么也应该触发急停,发生任何非正常的情况,停下来总是没错的。

    接线示意图

    Python程序流程图

    代码实现

    import RPi.GPIO as GPIO
    import time
    from multiprocessing import Process
    # 定义信号引脚
    button_stop = 20
    button_reset = 21
    button_start = 22
    
    
    # 初始化GPIO
    def init_gpio():
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        # 初始化按钮,按钮均为低电平触发
        GPIO.setup(button_reset, GPIO.IN)
        GPIO.setup(button_start, GPIO.IN)
        GPIO.setup(button_stop, GPIO.IN)
    
    
    # 业务动作
    def step_1():
        time.sleep(3)
        return True
    
    
    def step_2():
        time.sleep(3)
        return True
    
    
    def step_3():
        time.sleep(3)
        return True
    
    
    # 复位动作组合
    def run_reset():
        move_reset_list = [
            step_3,
            step_2,
            step_1
        ]
        result = True
        try:
            for func in move_reset_list:
                func_name = func.__name__
                print("正在执行: %s" % func_name)
                func_result = func()
                if not func_result:
                    result = False
                    break
        except:
            result = False
        finally:
            if not result:
                exit(1)
            else:
                exit(0)
    
    
    # 业务动作组合
    def run_step():
        result = True
        try:
            auto_cover_list = [
                step_1,
                step_2,
                step_3
            ]
            for func in auto_cover_list:
                func_name = func.__name__
                print("正在执行: %s" % func_name)
                func_result = func()
                if not func_result:
                    result = False
                    break
        except:
            result = False
        finally:
            if not result:
                exit(1)
            else:
                exit(0)
    
    
    if __name__ == '__main__':
        # 开始工作
        init_gpio()
        while True:
            if GPIO.input(button_start) == 0:
                try:
                    p_run = Process(target=run_step, daemon=True)
                    p_run.start()
                    # 监听急停信号
                    while p_run.is_alive():
                        if GPIO.input(button_stop) == 0:
                            p_run.terminate()
                            break
                        else:
                            time.sleep(0.1)
                    if p_run.exitcode == 0 or p_run.exitcode is None:
                        print("执行成功")
                    else:
                        print("执行失败")
                except:
                    print("执行失败")
            elif GPIO.input(button_reset) == 0:
                p_reset = Process(target=run_reset, daemon=True)
                p_reset.start()
                # 监听急停信号
                while p_reset.is_alive():
                    if GPIO.input(button_stop) == 0:
                        p_reset.terminate()
                        break
                    else:
                        time.sleep(0.1)
            elif GPIO.input(button_stop) == 0:
                # 急停按钮释放后,再释放程序
                while True:
                    if GPIO.input(button_stop) == 0:
                        time.sleep(0.1)
                    else:
                        break
            else:
                time.sleep(0.1)
    
    

    原创作者:郑立赛


    邮箱:zhenglisai@qq.com


    欢迎关注我们的公众号获取最新文章:运维自动化开发


    公众号
    公众号
  • 相关阅读:
    codeforces 1295 题解(完结)
    Leetcode 第 173 场周赛 题解(完结)
    P2564-[USACO12MAR]花盆Flowerpot
    Task 1-2
    LeetCode--169--多数元素(python)
    049字符异位词分组(python)
    矩阵路径(python)
    全排列
    滑动窗口最大值leetcode & nowcoder(python)
    取topK
  • 原文地址:https://www.cnblogs.com/zhenglisai/p/15608434.html
Copyright © 2020-2023  润新知