【问题标题】:Unable to get arduino serial communication working in wxpython GUI无法让 arduino 串行通信在 wxpython GUI 中工作
【发布时间】:2015-07-04 15:25:43
【问题描述】:

这是用于在 GUI 中更新标签的定义:

    def updateV(self, event):
    """"""
    global v
    ser = serial.Serial( port='COM3', baudrate=9600)
    x = ser.read()          # read one byte
    ser.close()
    print x
    if v>3:
        self.labelOne.SetBackgroundColour('red')
        self.labelOne.SetLabel('Battery Voltage : ' + x)

    else:
        self.labelOne.SetBackgroundColour('white')
        self.labelOne.SetLabel('Battery Voltage : ' + str(v))


    self.Refresh()

这是我一直在使用的简单 arduino 代码:

int a;
void setup() {
Serial.begin(9600);// put your setup code here, to run once:

}

void loop() {
a=5;
Serial.println(a);
delay(10);
}

我一直在使用这个定义来更新我的 GUI 标签。我最近开始使用该代码在我的 GUI 上设置串行通信。逻辑上使用 wx 库的 mainloop(),我想我可以更新“x”值并将其打印在 GUI 上。但即使 python 控制台定期打印 5,所有 GUI 窗口都显示为 0.0。请帮忙!我对此很陌生。

【问题讨论】:

    标签: user-interface arduino serial-port wxpython pyserial


    【解决方案1】:

    您的问题是 ser.read() 将被阻止。即使您调整了serial.Serial 实例的超时时间,它仍然会使 GUI 保持忙碌状态。在那种情况下,我不知道“强制”刷新/wx.Yield() 的方法,它根本行不通。阻塞调用的标准解决方案是启动一个线程 或定期轮询(例如使用wx.Timer)。但是,我只能使线程工作。该示例基于wxTerminal in pyserial

    # -*- coding: utf-8 -*-
    
    import wx
    import serial
    from threading import Thread
    
    ARDUINO_NEWLINE = '\r\n'
    
    class serial_reader(object):
        def __init__(self, callback=None):
            """Creates serial reader.
    
            :param callback: callable, gets called when byte on serial arrives.
            """
            self.callback = callback
    
            self.thread = None
    
            # Signal if serial is alive and should be read
            self.alive = False
    
        def start_reader(self, serial_cfg):
            """Start the receiver thread.
    
            :param serial_cfg: dictionary, gets unpacked to parameters for :class:`serial.Serial`
            """
    
            self.ser_cfg = serial_cfg
            self.serial = serial.Serial(**serial_cfg)
            # set != None so it will not block for longer than timeout on shutdown
            self.serial.timeout = 0.1
            self.alive = True
    
            self.thread = Thread(target=self.serial_read)
            self.thread.daemon = True
            self.thread.start()
    
        def stop_reader(self):
            """Stop the receiver thread, wait util it is finished."""
            if self.thread is not None:
                # signal no more reads
                self.alive = False
                # wait until thread has finished
                self.thread.join()
                self.thread = None
    
            # cleanup
            self.serial.close()
    
        def serial_read(self):
            """Thread that handles the incoming traffic."""
    
            while self.alive:
                try:
                    text = self.serial.read()
                    if text and self.callback:
                        # return value to main loop in thread-safe manner
                        wx.CallAfter(self.callback, text)
                except serial.serialutil.SerialException:
                    # will happen when Windows goes in sleep mode
                    print 'serial.serialutil.SerialException'
    
    
    class ser_frm(wx.Frame):
        def __init__(self, *args, **kwds):
            wx.Frame.__init__(self, *args, **kwds)        
            self.txt = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE)
    
    class serial_controller(object):
        def __init__(self, app):
            self.app = app
    
            # buffer for serial data
            self.ser_buf = ''
    
            self.frm = ser_frm(None, -1, 'testfrm')
    
            # setup serial configuration
            self.serial_cfg = {'port': 'COM4', 'baudrate': 9600}        
            # When parameter dsrdtr is set to True, the Arduino
            # will not reset on serial open, for details see
            # http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection
            self.serial_cfg['dsrdtr'] = True
    
            self.ser_rd = serial_reader(callback=self.on_serial)
            tit = 'Arduino on port {port} at baudrate {baudrate}'.format(**self.serial_cfg)
            self.frm.SetTitle(tit)
            self.ser_rd.start_reader(self.serial_cfg)
    
            self.frm.Show()
    
            self.frm.Bind(wx.EVT_CLOSE, self.on_close)
    
        def on_close(self, evt):
            """Shutdown serial read thread before closing."""
            if self.ser_rd.alive:
                self.ser_rd.stop_reader()
            evt.Skip()
    
        def on_serial(self, text):
            """Handle input from the serial port."""
            self.ser_buf += text
            if self.ser_buf.endswith(ARDUINO_NEWLINE):
                if self.frm.txt.GetInsertionPoint() > 1000:
                    self.frm.txt.SetValue('')
                self.frm.txt.AppendText(self.ser_buf)
                self.ser_buf = ''
    
    
    if __name__ == "__main__":
        app = wx.App(redirect=False)
        serialctr = serial_controller(app)
        app.MainLoop()
    

    编辑:没有必要在带有片上 USB 的 Arduinos 上修改 DSR/DTR(例如 Arduino micro),因此删除该行

    self.serial_cfg['dsrdtr'] = True
    

    它仍然可以正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多