Python:如何中断,然后返回while循环,不需要goto



我正在用python运行一个简单的PID控制程序。基本上是一个无限while循环,它从传感器读取,然后计算适当的控制信号,以及输出诊断信息到终端。

然而,有时在观察诊断信息时,我想通过打破循环,接受用户输入,然后返回到相同的循环来改变PID系数-它本质上是循环使用的一些常量。我想这样做任意次数

使用'goto',这将是简单和容易,正是我想要的。有人能给我一些python伪代码来做这个吗?我实在想不出该怎么做。我可以用CTRL+C异常处理程序中断循环,但这样我就无法回到主循环。

一定有一些非常简单的方法可以做到这一点,但我想不出来。想法吗?代码片段:

while True:
        t0 = get_temp_deg_c(thermocouple1)
        print "Hose Temperature = " + str(t0) + " deg C"
        t1 = get_temp_deg_c(thermocouple2)
        print "Valve Temperature = " + str(t1) + " deg C"
        # write temps to file
        fi.write(str(t0))
        fi.write(" " + str(t1) + "n")
        error = setpoint - t0
        print "Setpoint = " + str(setpoint) + " deg C"
        print "Error = " + str(error) + " deg C"
        percent_error = error/setpoint*100
        print "Percent error = " + str(percent_error) + " %"
        duty_out = p.GenOut(percent_error)
        print "PID controller duty output: " + str(duty_out) + " %"
        # clamp the output
        if(duty_out) > 100:
            duty_out = 100
        if(duty_out < 0):
            duty_out = 0
        PWM.set_duty_cycle(PWM_pin, duty_out)
        # do we need to increment the setpoint?
        if( (setpoint - setpoint_precision) ... # omitted logic here
        # Here we return to the top

只要您同意在每次中断后"从顶部"重新启动(而不是返回到信号引发时循环中的确切点,这是一个更难的问题):

while True:
    try:
        controller.main_loop()
    except KeyboardInterrupt:
        controller.set_coefficients()

如果你不想要一个单独的IO线程,可以使用生成器来保存跨KeyboardInterrupts的循环状态。

some_parameter = 1
def do_pid_stuff():
    while True:
        sensor_data1 = 'data'
        sensor_data2 = 'data'
        sensor_data3 = 'data'
        yield 'based on sensor_data1 ' * some_parameter
        yield 'based on sensor_data2 ' * some_parameter
        yield 'based on sensor_data3 ' * some_parameter

stuff = do_pid_stuff()
while True:
    try:
        for control_signal in stuff:
            print(control_signal)
    except KeyboardInterrupt:
        some_parameter = int(input())

所以主循环将继续使用上次执行的yield的新参数。然而,这需要重写循环。也许,它应该被拆分为一个生成器,它将为您提供传感器数据,并进入一个函数,它将根据传感器值实际做的事情。

您已经有了几种与循环交互的方法,我想指出另一种方法:select()。使用select(),可以等待任意一个用户的输入。如果您添加了一个超时,那么您可以在没有用户输入可用的情况下进入正常循环,并在那里与您的硬件进行交互。

指出:

  • 下面是select的文档,但是考虑顶部的警告并查看selectors模块。
  • 这个解决方案,像一个使用键盘中断,将停止与硬件交互,而参数被改变。如果无法接受,则必须使用后台线程。
  • 使用select()更普遍适用,您也可以等待网络流量。
  • 您的硬件将不会尽可能频繁地提供服务,但在两者之间有固定的暂停。从好的方面来说,你也不用使用一个完整的CPU。