运行Invensense demo python客户端时出现serialwin32.py和serialutil.py错误

时间:2017-07-16 09:55:31

标签: python python-2.x pyserial

好日子,我是python的新手,并尝试运行Invensense提供的演示。(9轴MPU9250连接STM32F407G发现板,我使用了代码和python客户端在motion_driver_6.12,从Invensense网站下载。) 整个python部分是python2.7,pysearil,pygame。 我在Stackoverflow中搜索了我的问题,但具体情况有点不同,大多数解决方案对我来说都没用。 首先,我展示了我的问题。

UART连接PC,通过cmd.exe运行Invensense的python客户端,短暂出现pygame窗口并消失,我收到以下错误

D:\motion_driver_6.12\eMPL-pythonclient>python eMPL-client.py 7
Traceback (most recent call last):
File "eMPL-client.py", line 273, in <module>
def four_bytes(d1, d2, d3, d4):
File "eMPL-client.py", line 12, in __init__

File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 31, in 
__init__
super(Serial, self).__init__(*args, **kwargs)
File "C:\Python27\lib\site-packages\serial\serialutil.py", line 218, in 
__init__
self.port = port
File "C:\Python27\lib\site-packages\serial\serialutil.py", line 264, in port
raise ValueError('"port" must be None or a string, not 
{}'.format(type(port)))
ValueError: "port" must be None or a string, not <type 'int'>

其次,通过类似的问题,我到目前为止做了什么:

  1. 打开文件&#34; serialwin32.py&#34; 。将port = self.name更改为port = str(self.name)。它不起作用,相同的错误信息。
  2. 使用pyserial2.7卸载pyserial3.3(最新版本)。错误消息已经消失,但是Pygmae现在只是坐在那里黑屏。old answer说&#34; Invensense告诉我这意味着它已连接并等待数据&#34;。
  3. ----------------紧随其后的是eMPL-client.py,第21行和第273行被标记为-----

    #!/usr/bin/python
    
    
    
    # eMPL_client.py
    
    # A PC application for use with Embedded MotionApps.
    
    # Copyright 2012 InvenSense, Inc. All Rights Reserved.
    
    
    
    import serial, sys, time, string, pygame
    
    from ponycube import *
    
    
    
    class eMPL_packet_reader:
    //*********************line 21 __init__ begins********************//
        def __init__(self, port, quat_delegate=None, debug_delegate=None, data_delegate=None ):
    
            self.s = serial.Serial(port,115200)
    
            self.s.setTimeout(0.1)
    
            self.s.setWriteTimeout(0.2)
    
    # TODO: Will this break anything?
    
                ##Client attempts to write to eMPL.
    
                #try:
    
                #self.s.write("\n")
    
                #except serial.serialutil.SerialTimeoutException:
    
                #pass # write will timeout if umpl app is already started.
    
    
    
            if quat_delegate:
    
                self.quat_delegate = quat_delegate
    
            else:
    
                self.quat_delegate = empty_packet_delegate()
    
    
    
            if debug_delegate:
    
                self.debug_delegate = debug_delegate
    
            else:
    
                self.debug_delegate = empty_packet_delegate()
    
    
    
            if data_delegate:
    
                self.data_delegate = data_delegate
    
            else:
    
                self.data_delegate = empty_packet_delegate()
    
    
    
            self.packets = []
    
            self.length = 0
    
            self.previous = None
    
    
    
        def read(self):
    
            NUM_BYTES = 23
    
            p = None
    
            while self.s.inWaiting() >= NUM_BYTES:
    
                rs = self.s.read(NUM_BYTES)
    
                if ord(rs[0]) == ord('$'):
    
                    pkt_code = ord(rs[1])
    
                    if pkt_code == 1:
    
                        d = debug_packet(rs)
    
                        self.debug_delegate.dispatch(d)
    
                    elif pkt_code == 2:
    
                        p = quat_packet(rs)
    
                        self.quat_delegate.dispatch(p) 
    
                    elif pkt_code == 3:
    
                        d = data_packet(rs)
    
                        self.data_delegate.dispatch(d)
    
                    else:
    
                        print "no handler for pkt_code",pkt_code
    
                else:
    
                    c = ' '
    
                    print "serial misaligned!"
    
                    while not ord(c) == ord('$'):
    
                        c = self.s.read(1)
    
                    self.s.read(NUM_BYTES-1)
    
    
    
        def write(self,a):
    
            self.s.write(a)
    
    
    
        def close(self):
    
            self.s.close()
    
    
    
        def write_log(self,fname):
    
            f = open(fname,'w')
    
            for p in self.packets:
    
                f.write(p.logfile_line())
    
            f.close()
    
    
    
    # ===========  PACKET DELEGATES  ==========
    
    
    
    class packet_delegate(object):
    
        def loop(self,event):
    
            print "generic packet_delegate loop w/event",event
    
        def dispatch(self,p):
    
            print "generic packet_delegate dispatched",p
    
    
    
    class empty_packet_delegate(packet_delegate):
    
        def loop(self,event):
    
            pass
    
        def dispatch(self,p):
    
            pass
    
    
    
    class cube_packet_viewer (packet_delegate):
    
        def __init__(self):
    
            self.screen = Screen(480,400,scale=1.5)
    
            self.cube = Cube(30,60,10)
    
            self.q = Quaternion(1,0,0,0)
    
            self.previous = None  # previous quaternion
    
            self.latest = None    # latest packet (get in dispatch, use in loop)
    
    
    
        def loop(self,event):
    
            packet = self.latest
    
            if packet:
    
                q = packet.to_q().normalized()
    
                self.cube.erase(self.screen)
    
                self.cube.draw(self.screen,q)
    
                pygame.display.flip()
    
                self.latest = None
    
    
    
        def dispatch(self,p):
    
            if isinstance(p,quat_packet):
    
                self.latest = p
    
    
    
    class debug_packet_viewer (packet_delegate):
    
        def loop(self,event):
    
            pass
    
        def dispatch(self,p):
    
            assert isinstance(p,debug_packet);
    
            p.display()
    
    
    
    class data_packet_viewer (packet_delegate):
    
        def loop(self,event):
    
            pass
    
        def dispatch(self,p):
    
            assert isinstance(p,data_packet);
    
            p.display()
    
    
    
    # =============== PACKETS ================= 
    
    
    
    # For 16-bit signed integers.
    
    def two_bytes(d1,d2):
    
        d = ord(d1)*256 + ord(d2)
    
        if d > 32767:
    
            d -= 65536
    
        return d
    
    
    
    # For 32-bit signed integers.
    //**************************273 begins*********************************//
    def four_bytes(d1, d2, d3, d4):
    
        d = ord(d1)*(1<<24) + ord(d2)*(1<<16) + ord(d3)*(1<<8) + ord(d4)
    
        if d > 2147483648:
    
            d-= 4294967296
    
        return d
    

    ----------------其后是serialutil.py(版本3.3),从第1行到第272行,218和264被标记为------------ -

    #! python
    #
    # Base class and support functions used by various backends.
    #
    # This file is part of pySerial. https://github.com/pyserial/pyserial
    # (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
    #
    # SPDX-License-Identifier:    BSD-3-Clause
    
    import io
    import time
    
    # ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
    # isn't returning the contents (very unfortunate). Therefore we need special
    # cases and test for it. Ensure that there is a ``memoryview`` object for older
    # Python versions. This is easier than making every test dependent on its
    # existence.
    try:
        memoryview
    except (NameError, AttributeError):
        # implementation does not matter as we do not really use it.
        # it just must not inherit from something else we might care for.
        class memoryview(object):   # pylint: disable=redefined-builtin,invalid-name
            pass
    
    try:
        unicode
    except (NameError, AttributeError):
        unicode = str       # for Python 3, pylint: disable=redefined-builtin,invalid-name
    
    try:
        basestring
    except (NameError, AttributeError):
        basestring = (str,)    # for Python 3, pylint: disable=redefined-builtin,invalid-name
    
    
    # "for byte in data" fails for python3 as it returns ints instead of bytes
    def iterbytes(b):
        """Iterate over bytes, returning bytes instead of ints (python3)"""
        if isinstance(b, memoryview):
            b = b.tobytes()
        i = 0
        while True:
            a = b[i:i + 1]
            i += 1
            if a:
                yield a
            else:
                break
    
    
    # all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
    # so a simple ``bytes(sequence)`` doesn't work for all versions
    def to_bytes(seq):
        """convert a sequence to a bytes type"""
        if isinstance(seq, bytes):
            return seq
        elif isinstance(seq, bytearray):
            return bytes(seq)
        elif isinstance(seq, memoryview):
            return seq.tobytes()
        elif isinstance(seq, unicode):
            raise TypeError('unicode strings are not supported, please encode to bytes: {!r}'.format(seq))
        else:
            # handle list of integers and bytes (one or more items) for Python 2 and 3
            return bytes(bytearray(seq))
    
    
    # create control bytes
    XON = to_bytes([17])
    XOFF = to_bytes([19])
    
    CR = to_bytes([13])
    LF = to_bytes([10])
    
    
    PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
    STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
    FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
    
    PARITY_NAMES = {
        PARITY_NONE: 'None',
        PARITY_EVEN: 'Even',
        PARITY_ODD: 'Odd',
        PARITY_MARK: 'Mark',
        PARITY_SPACE: 'Space',
    }
    
    
    class SerialException(IOError):
        """Base class for serial port related exceptions."""
    
    
    class SerialTimeoutException(SerialException):
        """Write timeouts give an exception"""
    
    
    writeTimeoutError = SerialTimeoutException('Write timeout')
    portNotOpenError = SerialException('Attempting to use a port that is not open')
    
    
    class Timeout(object):
        """\
        Abstraction for timeout operations. Using time.monotonic() if available
        or time.time() in all other cases.
    
        The class can also be initialized with 0 or None, in order to support
        non-blocking and fully blocking I/O operations. The attributes
        is_non_blocking and is_infinite are set accordingly.
        """
        if hasattr(time, 'monotonic'):
            # Timeout implementation with time.monotonic(). This function is only
            # supported by Python 3.3 and above. It returns a time in seconds
            # (float) just as time.time(), but is not affected by system clock
            # adjustments.
            TIME = time.monotonic
        else:
            # Timeout implementation with time.time(). This is compatible with all
            # Python versions but has issues if the clock is adjusted while the
            # timeout is running.
            TIME = time.time
    
        def __init__(self, duration):
            """Initialize a timeout with given duration"""
            self.is_infinite = (duration is None)
            self.is_non_blocking = (duration == 0)
            self.duration = duration
            if duration is not None:
                self.target_time = self.TIME() + duration
            else:
                self.target_time = None
    
        def expired(self):
            """Return a boolean, telling if the timeout has expired"""
            return self.target_time is not None and self.time_left() <= 0
    
        def time_left(self):
            """Return how many seconds are left until the timeout expires"""
            if self.is_non_blocking:
                return 0
            elif self.is_infinite:
                return None
            else:
                delta = self.target_time - self.TIME()
                if delta > self.duration:
                    # clock jumped, recalculate
                    self.target_time = self.TIME() + self.duration
                    return self.duration
                else:
                    return max(0, delta)
    
        def restart(self, duration):
            """\
            Restart a timeout, only supported if a timeout was already set up
            before.
            """
            self.duration = duration
            self.target_time = self.TIME() + duration
    
    
    class SerialBase(io.RawIOBase):
        """\
        Serial port base class. Provides __init__ function and properties to
        get/set port settings.
        """
    
        # default values, may be overridden in subclasses that do not support all values
        BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
                     9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
                     576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
                     3000000, 3500000, 4000000)
        BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
        PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
        STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
    
        def __init__(self,
                     port=None,
                     baudrate=9600,
                     bytesize=EIGHTBITS,
                     parity=PARITY_NONE,
                     stopbits=STOPBITS_ONE,
                     timeout=None,
                     xonxoff=False,
                     rtscts=False,
                     write_timeout=None,
                     dsrdtr=False,
                     inter_byte_timeout=None,
                     exclusive=None,
                     **kwargs):
            """\
            Initialize comm port object. If a "port" is given, then the port will be
            opened immediately. Otherwise a Serial port object in closed state
            is returned.
            """
    
            self.is_open = False
            self.portstr = None
            self.name = None
            # correct values are assigned below through properties
            self._port = None
            self._baudrate = None
            self._bytesize = None
            self._parity = None
            self._stopbits = None
            self._timeout = None
            self._write_timeout = None
            self._xonxoff = None
            self._rtscts = None
            self._dsrdtr = None
            self._inter_byte_timeout = None
            self._rs485_mode = None  # disabled by default
            self._rts_state = True
            self._dtr_state = True
            self._break_state = False
            self._exclusive = None
    
            # assign values using get/set methods using the properties feature
    //**************218**************//
            self.port = port 
    //**************218**************//
            self.baudrate = baudrate
            self.bytesize = bytesize
            self.parity = parity
            self.stopbits = stopbits
            self.timeout = timeout
            self.write_timeout = write_timeout
            self.xonxoff = xonxoff
            self.rtscts = rtscts
            self.dsrdtr = dsrdtr
            self.inter_byte_timeout = inter_byte_timeout
            self.exclusive = exclusive
    
            # watch for backward compatible kwargs
            if 'writeTimeout' in kwargs:
                self.write_timeout = kwargs.pop('writeTimeout')
            if 'interCharTimeout' in kwargs:
                self.inter_byte_timeout = kwargs.pop('interCharTimeout')
            if kwargs:
                raise ValueError('unexpected keyword arguments: {!r}'.format(kwargs))
    
            if port is not None:
                self.open()
    
        #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    
        # to be implemented by subclasses:
        # def open(self):
        # def close(self):
    
        #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    
        @property
        def port(self):
            """\
            Get the current port setting. The value that was passed on init or using
            setPort() is passed back.
            """
            return self._port
    
        @port.setter
        def port(self, port):
            """\
            Change the port.
            """
    //*************************line 263**********************//
            if port is not None and not isinstance(port, basestring):
                raise ValueError('"port" must be None or a string, not {}'.format(type(port)))
            was_open = self.is_open
            if was_open:
                self.close()
            self.portstr = port
            self._port = port
            self.name = self.portstr
            if was_open:
                self.open()
    

    -------------其次是serialwin32.py(版本3.3),31标记为--------------------- --------------------

    #! python
    #
    # backend for Windows ("win32" incl. 32/64 bit support)
    #
    # (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
    #
    # This file is part of pySerial. https://github.com/pyserial/pyserial
    # SPDX-License-Identifier:    BSD-3-Clause
    #
    # Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>
    
    # pylint: disable=invalid-name,too-few-public-methods
    import ctypes
    import time
    from serial import win32
    
    import serial
    from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
    
    
    class Serial(SerialBase):
        """Serial port implementation for Win32 based on ctypes."""
    
        BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
                     9600, 19200, 38400, 57600, 115200)
    
        def __init__(self, *args, **kwargs):
            self._port_handle = None
            self._overlapped_read = None
            self._overlapped_write = None
    //**************31**************//
            super(Serial, self).__init__(*args, **kwargs)
    //**************31**************//
    

    问题:

1 个答案:

答案 0 :(得分:0)

在线查看,我发现this Github repo似乎与您正在使用的代码相对应。似乎eMPL-client.py与较新版本的pyserial不兼容。具体而言,__main__例程requires numeric port identifiers,但pyserial 3.3 serial.Serial requires textual port identifiers。我没有设置测试这个,但你可以尝试以下。

  1. 安装 Python 2.7的新副本,这是eMPL-client.py定位的内容。这与 pyserial 2.7。
  2. 无关
  3. 在新副本中,安装 pyserial 2.7和其他依赖项。每the source,pyserial 2.7使用端口号。 Pyserial 3.3使用端口名称,因为“端口必须是字符串”错误。
  4. 这应该会让您超过初始错误,这与您链接的问题的this answer类似。此时,可能是时候拔出示波器并确保电路板产生信号。如果是,请检查速度/波特率/奇偶校验。我看到the source运行速度为115200bps;如果您的硬件支持,可以尝试使用57600。

    另一种选择

    要在eMPL-client.py中使用eMPL-client.py和pyserial 3.3,请查找以下行:

    if __name__ == "__main__":
        if len(sys.argv) == 2:
            comport = int(sys.argv[1]) - 1      #### This is the line that triggers the issue
        else:
            print "usage: " + sys.argv[0] + " port"
            sys.exit(-1)
    

    #### - 标记的行更改为

            comport = sys.argv[1]
    

    (确保缩进保持不变!)

    然后,在cmd.exe中,运行

    python eMPL-client.py COM7
    

    使用字符串端口名称,例如COM7,而不是端口号,例如7