簡體   English   中英

使用 KeyboardInterrupt 退出循環,然后在 python 中開始另一個循環

[英]Exit loop with KeyboardInterrupt then begin another loop in python

我目前有一段代碼旨在通過 TCP 設備服務器與兩個電機通信,該設備服務器向它們發送 ASCII 命令以跟蹤正弦路徑。 我希望讓運動無限期地繼續,然后在觸發KeyboardInterrupt時立即停止,然后在程序結束之前讓電機回到它們定義的起始位置。

此代碼當前可以復制正弦運動,但當前不會在觸發KeyboardInterrupt時立即停止,電機也不會返回其原始位置。 正弦循環的設計使得當KeyboardInterrupt發生時,一個名為move的全局變量從 True 變為 False,這會中斷循環。 簡化代碼如下:

import socket
import time
import numpy as np
import math

pi = math.pi

try:
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
    print("Failed to connect")
    exit()
print("Sockets Created")

s1.connect(("192.168.177.200", 4001)) # Y motor
s2.connect(("192.168.177.200", 4002)) # X motor

# Disengage the motor to allow manual movement by wheel
s1.send("DI\n".encode("ASCII")) 
message = s1.recv(1024).decode()
s2.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()



homeposition = input("Are the motors centred? Press 'y' to confirm: ")
if homeposition == 'y':
    s1.send("EN\n".encode("ASCII"))
    s2.send("EN\n".encode("ASCII")) # energise the motors so they cannot be moved
    print("Motors Engaged")
    s1.send("HO\n".encode("ASCII")) # set current position as home position
    s2.send("HO\n".encode("ASCII")) # set current position as home position
else:
    print("Set home position and restart program")
    exit()


#----ADD DATA FOR SAMPLING SINUSODIAL FUNCTIONS----

radius = input("Desired radius of movement (mm):")
radius = float(radius)
print("radius of circular path (mm): ", radius)

# need slightly different ratios for each motor due to different thread sizes
gearpositionlim_x = 20000 #one rotation equals 2.5mm (+ bearing ration on manipulator of 2:1)
gearpositionlim_y = 10000 #one rotation equals 2mm



# sample sine and cosine
step = 2*pi / 1000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim_x*np.cos(time_range)
y_motorrange = gearpositionlim_y*np.sin(time_range)
x_motorrange = ['la'+str(int(i)) for i in x_motorrange]
y_motorrange = ['la'+str(int(i)) for i in y_motorrange]
#print(x_motorrange)

x_motorrange_wcom = []
y_motorrange_wcom = []
{x_motorrange_wcom.extend([e, 'm', 'np']) for e in x_motorrange} # add movement prompts and wait for movement to complete
{y_motorrange_wcom.extend([e, 'm', 'np']) for e in y_motorrange} # add movement prompts and wait for movement to complete

# Set Acceleration and Deceleration of Motors
s1.send("AC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("AC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Acceleration set to 10 ") 

s1.send("DEC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DEC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Deceleration set to 10")

def setup():  #move to initial position before starting movement
    s2.send(str(str(x_motorrange_wcom[0])+"\n").encode("ASCII"))
    s2.send("m\n".encode("ASCII"))
    s2.send("np\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))
    
def end():
    print("Movement ended, return to home position")
    s1.send("la0\n".encode("ASCII"))
    s1.send("m\n".encode("ASCII"))
    s1.send("np\n".encode("ASCII"))
    s1.send("delay200\n".encode("ASCII"))
    s1.send("DI\n".encode("ASCII"))
    s1.send("delay200\n".encode("ASCII"))
    time.sleep(2)
    s2.send("la0\n".encode("ASCII"))
    s2.send("m\n".encode("ASCII"))
    s2.send("np\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))
    s2.send("DI\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))


def motormove():
    global move
    try:
        for i in np.arange(0,len(x_motorrange)):
            if (move == True):
                s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
                s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
            else:
                break
    except KeyboardInterrupt:
        move = False
        print(move)
        end()
            

#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
        print("Code Running: Press ctrl + c to end")
        while (move == True):
            motormove()

我相信我的問題在於我的 function motormove() ,但我不確定我應該做什么才能實現我想要的操作。 有誰知道如何做到這一點?

提前致謝

使用庫信號應該足以滿足您的用例。 請參見下面的代碼。

import socket
import signal
import time
import numpy as np
import math

pi = math.pi
try:
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
    print("Failed to connect")
    exit()
print("Sockets Created")

s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position

gearpositionlim = int(10000)
# sample sine and cosine
step = 2*pi / 2000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim*np.sin(time_range)
y_motorrange = gearpositionlim*np.cos(time_range)

def handler(signum, frame):
    res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
    if res == 'y':
        exit(1) 
    else:
        #Do STH


def setup():
    s2.send(y_motorrange[0])+"\n").encode("ASCII"))
    s2.send("m\n".encode("ASCII"))
    s2.send("np\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))

def end():
    print("Movement ended, return to home position")
    s1.send("la0\n".encode("ASCII"))
    s1.send("m\n".encode("ASCII"))
    s1.send("np\n".encode("ASCII"))
    s1.send("delay200\n".encode("ASCII"))
    s1.send("DI\n".encode("ASCII"))
    s1.send("delay200\n".encode("ASCII"))
    time.sleep(2)
    s2.send("la0\n".encode("ASCII"))
    s2.send("m\n".encode("ASCII"))
    s2.send("np\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))
    s2.send("DI\n".encode("ASCII"))
    s2.send("delay200\n".encode("ASCII"))


def motormove():
    global move
    try:
        for i in np.arange(0,len(x_motorrange)):
            if (move == True):
                s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
                s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
            else:
                break
    except KeyboardInterrupt:
        signal.signal(signal.SIGINT, handler)

            

#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
        print("Code Running: Press ctrl + c to end")
        while (move == True):
            motormove()

這應該工作得很好,注意信號 function 在KeyboardInterrupt上被調用,這重定向到信號 function ,你可以退出或做其他事情。

我會重新安排您的代碼以刪除重復項(請注意,以下內容未經測試,但您應該明白):

from socket import socket, AF_INET, SOCK_STREAM
from time import sleep
import numpy as np
import math

class Motor:
    def __init__(self, gearposition_limit=10000, step_count=2000):
        self.socket = socket(AF_INET, SOCK_STREAM)
        self.step = 2 * math.pi / step_count
        self.time_range = np.arange(0, 2 * math.pi + self.step, self.step)
        self.x_range = gearposition_limit * np.sin(self.time_range)
        self.y_range = gearposition_limit * np.cos(self.time_range)
        self.reset()

    def send(self, *args):
        try:
            for c in args:
                self.socket.send(f'{c}\n'.encode("ASCII"))
        except KeyboardInterrupt:
            self.end()

    def reset(self):
        self.send(self.x_range[0], "m", "np", "delay200", "HO")

    def end(self):
        self.send("la0", "m", "np", "delay200", "DI", "delay200")

m1 = Motor()
m2 = Motor()

input("Ready. Press enter to proceed")
print("Running. Press CTRL+C to end")

m1.send(*m1.x_range)
sleep(2)
m2.send(*m2.x_range)

如果您想在兩個電機上獨立平行移動,則需要研究多線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM