2015-07-04 3 views
0

Это определение, которое используется для обновления меток в графическом интерфейсе:Невозможно получить Arduino последовательной связи, работающий в WxPython 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); 
} 

Я использую это определение для обновления своих меток для моего графического интерфейса. Недавно я начал настраивать последовательную связь в моем графическом интерфейсе с помощью этого кода. Логически используя mainloop() библиотеки wx, я думал, что могу обновить значение «x» и распечатать его в графическом интерфейсе. Но все окна GUI показывают в 0.0, хотя пульт python печатает 5 регулярно. Пожалуйста помоги! Я довольно новичок в этом.

ответ

0

Ваша проблема заключается в том, что ser.read() будет заблокирован. Даже если вы настроите тайм-аут своего экземпляра serial.Serial, он все равно будет поддерживать графический интерфейс. В этой ситуации я не знаю способ «принудительно» обновить/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() 

EDIT: Не надо возиться с DSR/DTR на Arduinos с USB на чипе (например, Arduino микро), поэтому удалить строку

self.serial_cfg['dsrdtr'] = True 

, и она будет работать должным образом.

Смежные вопросы