Windows 或 Ubuntu VBox 上的串行端口可通过 Python 与 Arduino 通信

发布于 2024-10-19 18:51:15 字数 1770 浏览 4 评论 0原文

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

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

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

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

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

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

但我不知道您如何知道/dev/ttyS1 是有效的端口名称。

有没有好的文档可以帮助您开始这方面的工作?

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

该程序正在 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

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

I have an Arduino microcontroller listening on COM3. Using the arduino IDE and the Serial monitor works fine to send and receive data.

I would like to send and receive data from Python, but it's not immediately obvious how to do so. (I'd also be fine doing it in C# if it was substantially easier.)

I found arduino_serial.py, but it only works for Unix. Fortunately, I have a Ubuntu 10.10 VBox set up. However, I have no idea if that VM can access serial ports or if special steps are required to do so.

I also found pySerial, which looks pretty legitimate. However, I'm also unsure how to use it. It wants serial port names. How do I find out what valid values for these are?

For example, pySerial mentions that you can "Open named port at “19200,8,N,1”, 1s timeout" with the following command:

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

But I have no idea how you would know that /dev/ttyS1 was a valid port name.

Is there good documentation for getting started on this?

Update: I'm using Ubuntu with arduino_serial, but still having trouble.

This program is running on the Arduino:

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

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

I see that a port called tty0 is available:

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

I then try to connect with 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

Why am I getting this error? What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅忆流年 2024-10-26 18:51:15

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 串行设备转换器现在连接到 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")

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

pySerial may or may not be built in to Python. Regardless, if it's not, pySerial is the library to download and install.

And since you already know the Arduino is on COM3, just use this:

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

For a Linux box, it's relatively easy to find out what serial port your Arduino is using:

dmesg | grep tty

This will give you some output similar to this: [ 7.944654] usb 1-1.6: FTDI USB Serial Device converter now attached to ttyUSB0

So my Arduino is on ttyUSB0. This means you can use the following code to talk to the Arduino on a Linux box:

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

Note: If you use a baud rate of 9600 on the Arduino, as most people do, you can simply use serial.Serial("COM3") or serial.Serial("/dev/ttyUSB0") without any other parameters.

EDIT:
You should also keep in mind that in the real world, it may take a second to actually open the port and get it ready for transmitting data. This means that performing a write IMMEDIATELY after the serial.Serial() call may not actually do anything. So the code I would use is as follows:

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

Kind of a hack, but it's the only way I know how to get it to work on my system.

断舍离 2024-10-26 18:51:15

在 Windows 上,串行端口被命名为 COM1,即 /dev/ttyS0->COM1。我用 Python 为我们的四轴飞行器编写了一些代码使用 Pyserial 在 Windows 和 Linux 上运行的控制器(假设您正确提供了端口名称)。

尝试将 COM3 传递到 Windows 上的 Pyserial。在虚拟机上,您必须首先将 USB 转串口适配器传递到虚拟机或设置串行端口部分(我使用 VirtualBox)。如果您选择 USB 路线,则串行设备将在 /dev/ttyUSBxx 下枚举。

The serial ports are named COM1 onwards on Windows, /dev/ttyS0->COM1. I wrote some code in Python for our Quadcopter controller which works both on Windows and Linux (given you supply the port name properly) using Pyserial.

Try passing COM3 to Pyserial on Windows. On the VM you will have to first pass the USB-to-serial adapter to the VM or set up the serial ports section (I use VirtualBox). If you go the USB route the serial devices are enumerated under /dev/ttyUSBxx.

人海汹涌 2024-10-26 18:51:15

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

I have a project called Yaam on CodePlex that uses C# to send data through the serial port. Check that out for an example. On the C# side (see Yaam\Yaam.xaml.cs), simply use the SerialPort class in the System.IO.Ports namespace. Once you instantiate the object and set the properties (baud rate, com port, etc), simply call.Open() . There are also plenty of other examples on the web. Take a look at these:

靖瑶 2024-10-26 18:51:15

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

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

这并不总能发现模拟端口(使用 socatcom0com 创建)或 USB 端口,因此对于这些端口,您需要使用 glob 模块(我认为无论您对 dev/ 使用 globbing 还是索引,都没有很大的区别ttySX 设备节点)。这就是 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

"But I have no idea how you would know that /dev/ttyS1 was a valid port name."

PySerial's serial port initialiser accepts a number instead of a name as an argument. These numbers will correspond to "normal" serial ports (/dev/ttySX on Linux, COMX on Windows). You can then get the name from the created object. There's no way to know in advance what numbers to try, though, so as you'll see in the following code, you just have to try and fail.

This won't always discover simulated ports (created using socat or com0com), or USB ports though, so for those you need to use the glob module (I don't think it makes a huge difference whether you use globbing or indices for the dev/ttySX device nodes). This is what pySerial's own examples do. The following code is adapted from those examples:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文