无法在wxpython GUI中使用arduino串行通信

时间:2015-07-04 15:25:44

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

这是用于更新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。请帮忙!我对此很新。

1 个答案:

答案 0 :(得分:0)

您的问题是<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="subheader active"> <p>Hello, click to toggle</p> </div> <div class="subheader"> <p>Goodbye</p> </div> <div class="subheader"> <p>Hello Again</p> </div>会阻止。即使您调整ser.read()实例的超时,它仍然会使GUI保持忙碌状态。在那种情况下,我不知道一种方法来强迫&#34;刷新/ serial.Serial,它根本行不通。阻止调用的标准解决方案是启动一个线程 或定期民意调查(例如wx.Yield())。但是,我只能使线程工作。该示例基于wxTerminal in pyserial

wx.Timer

编辑:没有必要使用片上USB(例如Arduino micro)修改Arduinos上的DSR / DTR,所以删除该行

# -*- 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()

它仍然可以正常工作。