wxpythonpython:串行端口问题

wxpythonpython:串行端口问题,python,python-2.7,wxpython,arduino,pyserial,Python,Python 2.7,Wxpython,Arduino,Pyserial,我已经创建了一个代码,打开一个串行端口,其中连接了arduino并获取了一些数据,目前为止还不错,我的问题是当我打开程序并按下开始按钮(打开串行端口并等待接收来自arduino的数据)时,出于某种原因,我忘记了连接arduino,但显然它什么都没做,当我插上插头而不关闭并再次打开时,程序和按“开始”键仍然无法运行。显然,如果我重新启动程序,没有问题,但我如何在不重新启动程序的情况下解决此问题?我的第二个问题是,当我的程序工作并接收数据时,我断开USB连接,我的程序即使按“停止”和“停止”键也无法

我已经创建了一个代码,打开一个串行端口,其中连接了arduino并获取了一些数据,目前为止还不错,我的问题是当我打开程序并按下开始按钮(打开串行端口并等待接收来自arduino的数据)时,出于某种原因,我忘记了连接arduino,但显然它什么都没做,当我插上插头而不关闭并再次打开时,程序和按“开始”键仍然无法运行。显然,如果我重新启动程序,没有问题,但我如何在不重新启动程序的情况下解决此问题?我的第二个问题是,当我的程序工作并接收数据时,我断开USB连接,我的程序即使按“停止”和“停止”键也无法关闭尝试关闭,或者如果我再次连接USB,然后尝试关闭,唯一的方法是从任务管理器关闭。为什么会发生这种情况,我如何解决它?对于第二个问题,我不明白为什么当我从任务管理器关闭程序并再次运行它时,它仍然不工作,只有当我拔下USB并再次连接,然后重新运行程序时,它才能工作

附言:我知道没有明显的理由去做这些事情,但我很好奇,我不想学

以下是启动/停止按钮的代码:

def onStartStopButton(self, event):
    global a2
    global q
    global i
    if not self.isLogging:
        self.isLogging = True
        self.ser = serial.Serial()
        self.ser.baudrate = 38400
        self.ser.timeout=0.25
        # Try serial ports one by one starting
        for m in range(29, 0, -1):
            self.ser.port = m
            try:
                self.ser.open()
                break
            except:
                # We end up here if this port number
                # failed to open
                pass
        if self.ser.isOpen():
            i=0
            # We successfully opened a port, so start
            self.timer.IsRunning()
            self.t=time.time() -self.tZero
            self.tZero=time.time()
            self.timer.Stop()
            self.timer.Start(100)
            self.startbtn.SetLabel("Stop")        
    else:
        i=1
        self.timer.Stop()
        self.ser.close()
        self.isLogging = False
        self.startbtn.SetLabel("Start")
        a2 = True 

def GetSample(self,event=None):
    global a2
    global a4
    global a5
    global b1
    global b2
    global b7
    global h
    global q
    global arduinoDelay     
    global last_received1
    global now
    global array

    a1=0
    a3=0

    self.t=time.time() -self.tZero      
    tiTuple=time.gmtime(self.t)    
    reste=self.t-tiTuple[3]*3600.0-tiTuple[4]*60.0-tiTuple[5]*1.0
    resteS=("%.2f" % reste )[-2::] 
    tt=time.strftime("%H:%M:%S",tiTuple)
    self.tAff.SetLabel(tt)

    while a2:#send to arduino time refresh
        for a1 in range (2):
            self.ser.write(arduinoDelay)
            time.sleep(0.5)
            h=0
            print "write to arduino delay ",arduinoDelay
        a2=False
        arduinoSensorNum = 'E'
        if '1' in sensor_select:
            arduinoSensorNum += '1'
        if '2' in sensor_select:
            arduinoSensorNum += '2'
        if '3' in sensor_select:
            arduinoSensorNum += '3'
        if '4' in sensor_select:
            arduinoSensorNum += '4'
        if '5' in sensor_select:
            arduinoSensorNum += '5'
        if '6' in sensor_select:
            arduinoSensorNum += '6'
        arduinoSensorNum += '/'
        a4=True
    if (sensor_select == ''):#if no one sensor select--> enable all
        arduinoSensorNum = 'E123456/'


    while a4:#send arduino enable num sensors
        for a3 in range (1):               
            self.ser.write(arduinoSensorNum)
            time.sleep(0.5)
            print "write to arduino sensor Num ",arduinoSensorNum
        a4=False

    if not h==1:
        q=1
        self.ser.write('S')
        print "send S "

    sample_string = self.ser.readline()
    now = datetime.datetime.now()

    if len(sample_string) == 15:#
        sample_string = sample_string[0:-1]
        sample_values = sample_string.split()

        for m in range(self.M):
            # get one value from sample
            value = int(sample_values[m])
            self.x[m][0:99] = self.x[m][1:]
            self.x[m][99] = value

        # Update plot
        self.ax.cla()
        self.ax.autoscale(False)
        self.ax.set_xlim(0, self.N - 1)
        self.ax.set_ylim(-100, 1100)
        for m in range(self.M):
            self.ax.plot(self.n, self.x[m])
        self.canvas.draw()#

    if not sample_string =='':
        h=1#stop send start to arduino
        if not b2 == True:
            file_date = open("C:/TMS Data/date.txt","a")
            file_date.write(now.strftime("%Y-%m-%d\n"))
            file_date.write(now.strftime("%H:%M:%S\n"))
            print "######################"
            b2 = True
        file_sensors = open("C:/TMS Data/sensors.txt","a")
        file_sensors.write(sample_string)
        print q
        array[q]=sample_string
        print array[q]
        q=q+1

        """if q == 7 and i==1:
            self.timer.Stop()
            self.ser.close()
            self.isLogging = False
            #self.startbtn.SetLabel("Start")
            a2 = True"""

        if q == 7:
            q=1
            b2 = False
            b7=True

    if b7 == True:
        self.textctrl0.Clear()
        self.textctrl0.AppendText(array[1])
        self.textctrl1.Clear()
        self.textctrl1.AppendText(array[2])
        self.textctrl2.Clear()
        self.textctrl2.AppendText(array[3])   
        self.textctrl3.Clear()
        self.textctrl3.AppendText(array[4])
        self.textctrl4.Clear()
        self.textctrl4.AppendText(array[5])
        self.textctrl5.Clear()
        self.textctrl5.AppendText(array[6])
        b7=False
好的,我想出来了,问题是有引号的部分,这个部分的使用是当用户按下停止按钮时,代码继续,直到从最后一个传感器获取最后一个值。当我在onStartButtons define中添加这些行时,上述问题得到了解决


我现在的新问题是,如果用户按stop,arduino从传感器3发送值,我如何使其继续并从传感器4-5-6获取其他3个值,然后关闭串行通信?

我觉得这是有关UNIX串行设备访问的旧限制的一个示例(由Linux继承的)没有操作系统本机原语阻止设备上的争用。如果多个进程在Linux或UNIX下打开一个串行设备,则通常情况下,它们将始终争用来自设备的任何输入(一个或另一个进程将不确定地接收字符)对于写入设备的所有进程,输出将偶尔交错和阻塞

典型的UNIX和Linux程序使用锁定文件(如
/var/log/LCK..ttyS0
)来协调对这些设备的访问。这在以下地方进行了解释,并在StackOverflow上讨论了几次


我觉得这是一个关于UNIX串行设备访问的旧限制的例子(Linux继承了这个限制)。没有操作系统本机原语阻止设备上的争用。如果多个进程在Linux或UNIX下打开一个串行设备,则通常情况下,它们将始终争用设备的任何输入(一个或另一个进程将不确定地接收字符)对于写入设备的所有进程,输出将偶尔交错和阻塞

典型的UNIX和Linux程序使用锁定文件(如
/var/log/LCK..ttyS0
)来协调对这些设备的访问。这在以下地方进行了解释,并在StackOverflow上讨论了几次


如果对串行代码的调用导致程序无响应,则串行调用可能会阻塞GUI的主循环。在这种情况下,您将希望在单独的线程中执行所有串行工作,并使用wxPython的线程安全方法更新显示。这些方法是wx.CallAfter、wx.CallLater和wx.PostEvent。您可以有关wxPython和线程的更多信息,请参见以下内容:

如果您确实尝试从线程调用wxPython方法,那么行为将是未定义的,您可能会或可能不会立即出现问题


对于串行问题,我建议您阅读库的文档和/或与他们的邮件列表或开发团队联系,提出问题。

如果对串行代码的调用导致程序无响应,那么串行调用可能会阻塞GUI的主循环。在这种情况下,您需要在separa中完成所有串行工作te thread并使用wxPython的线程安全方法更新显示。这些方法是wx.CallAfter、wx.CallLater和wx.PostEvent。您可以在以下位置阅读有关wxPython和线程的更多信息:

如果您确实尝试从线程调用wxPython方法,那么行为将是未定义的,您可能会或可能不会立即出现问题


对于串行问题,我建议阅读库的文档和/或与他们的邮件列表或开发团队联系以提出问题。

我对串行或USB不太了解,但是,如果问题在程序运行期间持续存在,则它必须与库或操作系统驱动程序有关。了解如何重置串行端口(或COM或VCOM)并尝试该操作。对于无响应问题,对串行库的调用正在停止GUI线程(当您从GUI线程进行调用时)。将所有串行交互委托给另一个线程,并使用某种类型的消息传递(即:wxevents)在GUI中触发响应。如果将此工作线程设置为守护进程线程,则应能够在不停止的情况下关闭GUI。我对串行或USB不太了解,但是,如果问题在程序运行期间持续存在,则它必须与库或操作系统驱动程序相关。了解如何重置串行端口(或COM或VCOM)对于无响应问题,对串行库的调用正在停止GUI线程(当您从GUI线程进行调用时)。将所有串行交互委托给另一个线程,并使用某种类型的消息传递(即:wxevents)在GUI中触发响应。如果将此工作线程设置为守护进程线程,则应该能够关闭GUI而不会停止。