4

我有一个 Arduino 微控制器在 COM3 上监听。使用 arduino IDE 和串行监视器可以很好地发送和接收数据。

我想从 Python 发送和接收数据,但如何做到这一点并不是很明显。(如果它更容易的话,我也可以在 C# 中这样做。)

我找到了 arduino_serial.py,但它只适用于 Unix。幸运的是,我安装了 Ubuntu 10.10 VBox。但是,我不知道该 VM 是否可以访问串行端口,或者是否需要特殊步骤才能这样做。

我还发现了 pySerial,它看起来很合法。但是,我也不确定如何使用它。它需要串行端口名称。我如何找出这些的有效值是什么?

例如,pySerial提到您可以使用以下命令“在“19200,8,N,1”处打开命名端口,1s 超时”:

>>> ser = serial.Serial('/dev/ttyS1', 19200, timeout=1)

但我不知道你怎么知道这/dev/ttyS1是一个有效的端口名称。

是否有很好的文档可以开始这方面的工作?

更新:我正在使用带有 arduino_serial 的 Ubuntu,但仍然遇到问题。

该程序在 Arduino 上运行:

void setup() { 
  Serial.begin(9600);
}

void loop() { 
  if (Serial.available()) {
    Serial.print((char)Serial.read());
  }
}

我看到一个名为的端口tty0可用:

foo@bar:~/baz$ dmesg | grep tty
[    0.000000] console [tty0] enabled

然后我尝试连接arduino_serial

foo@bar:~/baz$ sudo python
[sudo] password for foo: 
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import arduino_serial
>>> sp = arduino_serial.SerialPort("/dev/tty0", 9600)
>>> sp.write("foo")
>>> sp.read_until("\n")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "arduino_serial.py", line 107, in read_until
    n = os.read(self.fd, 1)
OSError: [Errno 11] Resource temporarily unavailable

为什么我会收到此错误?我究竟做错了什么?

4

4 回答 4

4

pySerial可能会或可能不会内置到 Python 中。无论如何,如果不是,pySerial 是要下载和安装的库。

既然你已经知道 Arduino 在 COM3 上,那就用这个:

import serial
ser = serial.Serial("COM3", 19200, timeout=1)
ser.write("Whatever")

对于 Linux 机器,查找 Arduino 使用的串行端口相对容易:

dmesg | grep tty

这将为您提供一些类似于此的输出:[ 7.944654] usb 1-1.6: FTDI USB Serial Device converter now attached to ttyUSB0

所以我的 Arduino 在 ttyUSB0 上。这意味着您可以使用以下代码与 Linux 机器上的 Arduino 对话:

import serial
ser = serial.Serial("/dev/ttyUSB0", 19200, timeout=1)
ser.write("Whatever")

注意:如果您在 Arduino 上使用 9600 的波特率,就像大多数人一样,您可以简单地使用serial.Serial("COM3")serial.Serial("/dev/ttyUSB0")不使用任何其他参数。

编辑:您还应该记住,在现实世界中,实际打开端口并准备好传输数据可能需要一秒钟。这意味着在 serial.Serial() 调用之后立即执行写入可能实际上不会做任何事情。所以我将使用的代码如下:

import serial
import time
ser = serial.Serial("/dev/ttyUSB0", 19200, timeout=1)
time.sleep(1.5)
ser.write("Whatever")

有点黑客,但这是我知道如何让它在我的系统上工作的唯一方法。

于 2011-03-03T04:24:27.237 回答
2

串行端口在 Windows 上被命名为 COM1,/dev/ttyS0->COM1。我用 Python 为我们的 Quadcopter 控制器编写了一些代码,该控制器使用 Pyserial 在 Windows 和 Linux 上都可以工作(假设你提供了正确的端口名称)。

尝试在 Windows 上将 COM3 传递给 Pyserial。在 VM 上,您必须首先将 USB 转串口适配器传递给 VM 或设置串口部分(我使用VirtualBox)。如果您使用 USB 路由,则串行设备将在/dev/ttyUSBxx.

于 2011-03-03T04:03:12.580 回答
0

“但我不知道你怎么会知道 /dev/ttyS1 是一个有效的端口名称。”

PySerial 的串行端口初始化程序接受数字而不是名称作为参数。这些数字将对应于“普通”串行端口(/dev/ttySX在 Linux 上,COMX在 Windows 上)。然后,您可以从创建的对象中获取名称。但是,没有办法提前知道要尝试哪些数字,因此正如您将在下面的代码中看到的那样,您只需要尝试并失败。

这不会总是发现模拟端口(使用socator创建com0com)或 USB 端口,所以对于那些你需要使用glob模块的人(我认为无论你对dev/ttySX设备节点使用 glob 还是索引都没有太大的区别)。这就是pySerial 自己的示例所做的。以下代码改编自这些示例:

import glob, os

import serial

USB_SERIAL_GLOB = "/dev/ttyUSB*"

def try_open(port, args = (), kwargs = {}):
    try:
        port = serial.Serial(port, *args, **kwargs)
    except serial.SerialException:
        return None
    else:
        return port

def serial_scan(max_range = 32, args = (), kwargs = {}):
    for i in range(max_range):
        port = try_open(i, args, kwargs)
        if port is not None:
            yield port

    # Look for USB serial ports:     
    if os.name == 'posix':
        for fn in glob.glob(USB_SERIAL_GLOB):
            port = try_open(fn)
            if port is not None:
                yield port

if __name__ == "__main__":
    for port in serial_scan(kwargs = {'baudrate':9600, 'timeout':0.5}):
        port.close()
        print "Found: %s" % port.name
于 2011-03-03T07:48:06.000 回答
0

在 CodePlex 上有一个名为 Yaam的项目,它使用 C# 通过串口发送数据。看看这个例子。在 C# 端(请参阅 Yaam\Yaam.xaml.cs),只需使用命名空间SerialPort中的类System.IO.Ports。实例化对象并设置属性(波特率、com 端口等)后,只需调用.Open(). 网上还有很多其他的例子。看看这些:

于 2011-03-03T03:40:51.983 回答