[raspberry pie] Python development industrial computer emergency stop design

background

We used raspberry pie to replace PLC and host computer in some industrial products, and introduced AI and machine vision into the industrial field with the help of the computing power of raspberry pie.
The previous products had no action mechanism, and only output the results to the indicator light, buzzer or display, without potential safety hazards,
Now the action mechanism is introduced, which needs to drive the equipment to perform certain actions according to the results. The introduction of the action mechanism increases the potential safety hazards of the product, such as hand clamping, machine collision, etc. Therefore, we need to design additional protection programs, the most important of which is the realization of emergency stop function.

requirement

  • The emergency stop signal has the highest priority. In any case, pressing the emergency stop should stop immediately

problem analysis

  • The action mechanism is powered by 24V, and the emergency stop switch is connected in series with the power supply. After the switch is pressed, the action mechanism will be powered off. (all emergency stop switches are equipped with locking mechanism, which will not pop up after being pressed and will remain pressed)
  • Raspberry pie supplies power independently of the operating mechanism. After the emergency stop switch is pressed, raspberry pie receives the signal, starts to terminate the program, and then monitors the emergency stop button signal all the time.
  • Python generally runs in a single thread. In order to respond to the emergency stop in time, the emergency stop function needs to be made into a main process, and the business action logic is used as a sub process. When the supervisor hears the emergency stop signal, the sub process is terminated immediately

Design ideas

  • The reason for choosing a sub process instead of a sub thread is that Python sub threads cannot send a kill signal, and there is no good way to interfere with the behavior of sub threads (unless judged at each step, it will increase the code complexity), while sub processes can directly send a terminate signal to kill.
  • The reason why the emergency stop is triggered by the low level is: we think that the low level is a stable state, and the high level is not a stable state. For example, if the power is cut off for some reason, the emergency stop should also be triggered. In case of any abnormal situation, it is always right to stop.

Wiring diagram

Python program flow chart

code implementation

import RPi.GPIO as GPIO
import time
from multiprocessing import Process
# Define signal pin
button_stop = 20
button_reset = 21
button_start = 22


# Initialize GPIO
def init_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    # Initialization buttons, which are triggered by low level
    GPIO.setup(button_reset, GPIO.IN)
    GPIO.setup(button_start, GPIO.IN)
    GPIO.setup(button_stop, GPIO.IN)


# Business action
def step_1():
    time.sleep(3)
    return True


def step_2():
    time.sleep(3)
    return True


def step_3():
    time.sleep(3)
    return True


# Reset action combination
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("Executing: %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)


# Business action combination
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("Executing: %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__':
    # start-up
    init_gpio()
    while True:
        if GPIO.input(button_start) == 0:
            try:
                p_run = Process(target=run_step, daemon=True)
                p_run.start()
                # Monitor emergency stop signal
                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("Successful execution")
                else:
                    print("Execution failed")
            except:
                print("Execution failed")
        elif GPIO.input(button_reset) == 0:
            p_reset = Process(target=run_reset, daemon=True)
            p_reset.start()
            # Monitor emergency stop signal
            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:
            # Release the program after the emergency stop button is released
            while True:
                if GPIO.input(button_stop) == 0:
                    time.sleep(0.1)
                else:
                    break
        else:
            time.sleep(0.1)

Tags: Python Raspberry Pi

Posted on Wed, 01 Dec 2021 21:56:27 -0500 by Panjabel