wxPython-Python:串口问题

Posted

技术标签:

【中文标题】wxPython-Python:串口问题【英文标题】:wxPython-Python:Serial port problems 【发布时间】:2013-11-20 01:23:31 【问题描述】:

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

P.S:我知道做这些事情没有明显的理由,但我很好奇,我不会去学习。

这是开始/停止按钮的代码:

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 定义中添加此行时,上述问题已解决!

我现在的新问题是,如果用户按下停止并且 arduino 正在从传感器 3 发送值,我怎样才能让它继续并从传感器 4-5-6 获取其他 3 个值,然后关闭串行沟通?

【问题讨论】:

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

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

http://wiki.wxpython.org/LongRunningTasks http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

如果您确实尝试从线程调用 wxPython 方法,则该行为将是未定义的,您可能会或可能不会立即遇到问题。

对于连续问题,我建议阅读图书馆的文档和/或联系他们的邮件列表或开发团队以解决问题/问题。

【讨论】:

【参考方案2】:

在我看来,这是一个关于 UNIX 串行设备访问(由 Linux 继承)的旧限制的示例。没有操作系统本机原语可以防止设备上的争用。如果多个进程在 Linux 或 UNIX 下打开一个串行设备,那么通常,它们将始终竞相获取来自设备的任何输入(一个或另一个进程将不确定地接收字符)并且输出将偶尔交错并阻塞所有处理写入设备。

传统的 UNIX 和 Linux 程序使用锁定文件(例如 /var/log/LCK..ttyS0)来协调对这些设备的访问。这在以下位置进行了解释:Linux Serial HOWTO: Lockfiles,并且已经在 *** 上讨论过几次Stack Overflow: How can you access a serial port from two different processes (Python)

Serial Communication one to one

【讨论】:

以上是关于wxPython-Python:串口问题的主要内容,如果未能解决你的问题,请参考以下文章

电脑串口怎么设置?

arduino 软串口

attiny85软串口乱码

C# Winform 串口问题

matlab读串口数据问题

关于HAL库中用DMA方式使用串口的问题,串口中断用开吗