这是用于更新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上。但是所有的GUI窗口都显示为0.0,即使python控制台定期打印5。请帮忙!我对此很陌生。
您的问题是ser.read()
将阻塞。即使您调整了serial.Serial
实例的超时,它仍然会使GUI繁忙。在这种情况下,我不知道有什么方法可以"强制"刷新/wx.Yield()
,它根本不起作用。阻止调用的标准解决方案是启动线程或者定期轮询(例如使用wx.Timer
(。然而,我只能让线程工作。该示例基于pyserial中的wxTerminal。
# -*- coding: utf-8 -*-
import wx
import serial
from threading import Thread
ARDUINO_NEWLINE = 'rn'
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的Arduino上修改DSR/DTR(例如Arduino micro(,因此删除行
self.serial_cfg['dsrdtr'] = True
它仍然可以正常工作。