【问题标题】:Talking to an Arduino: works in C#, fails in Python与 Arduino 交谈:在 C# 中工作,在 Python 中失败
【发布时间】:2017-12-27 11:26:56
【问题描述】:

我需要与连接到 USB 端口的 Arduino Pro 微控制器通话。上传到它的草图应该响应带有调试响应的标准 C# 字符串:

> #NAME
>>> ARDUINO

(请求字符串没有换行符。)Arduino IDE中的串口监视器从连接的Arduino获得正确的响应。

我自己编写了一个 C# 程序来测试通信,它也得到了正确的响应:

using System;
using System.IO.Ports;
using System.Threading;

class Program {
    static SerialPort port;

    // static void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    //    // Show all the incoming data in the port's buffer
    //    Console.WriteLine(port.ReadExisting());
    //}

    static void Main(string[] args) {

        port = new SerialPort("COM5", 115200, Parity.None, 8, StopBits.One);

        //            port.DataReceived += port_DataReceived;

        Console.WriteLine("Port: " + port.PortName);

        port.Open();

        if (!port.IsOpen) {
            Console.WriteLine("Can't open port.");
            return;
        }

        Console.WriteLine("Writing '#NAME' to port...");
        port.Write("#NAME");

        Thread.Sleep(500);

        string ans = port.ReadExisting();
        Console.WriteLine("Response: " + ans + "| " + ans.Length);

        port.Close();
    }
}

输出:

Port: COM5
Writing '#NAME' to port...
Response: ARDUINO | 9

我尝试使用 Python 和 pySerial 模块与控制器对话:

import serial
from time import sleep

# msg = b'\x00\x23\x00\x4e\x00\x41\x00\x4d\x00\x45\n'
# msg = b'\x23\x4e\x41\x4d\x45\n'
# msg = b'#NAME\n'
# msg = b'\xff\xfe\x00\x00#\x00\x00\x00N\x00\x00\x00A\x00\x00\x00M\x00\x00\x00E\x00\x00\x00'
# msg = b'\xff\xfe#\x00N\x00A\x00M\x00E\x00'
# msg = bytes('#NAME', encoding="utf-8")
# msg = bytes('#NAME', encoding="utf-16")
# msg = bytearray([0x23, 0x4E, 0x41, 0x4D, 0x45])
# msg = bytearray(b"#NAME")
msg = "#NAME".encode("utf-16")

port = serial.Serial("COM5", baudrate=115200, parity=serial.PARITY_NONE, bytesize=8, stopbits=serial.STOPBITS_ONE, timeout=2)

print("Port:", port.name)
print("Is open?:", port.is_open)
print("Writing:", msg)

# port.writelines([msg])
port.write(msg)

sleep(1)

output = port.read_until(size=len(msg))
# output = port.read_all()
print("Reading:", output)

port.close()

但我无法让它正确响应:

Port: COM5
Is open? True
Writing: b'\xff\xfe#\x00N\x00A\x00M\x00E\x00'
Reading: b''

pySerial 的 write 方法不适用于字符串,只接受字节序列,所以我尝试用不同的方法转换字符串。

由于端口和控制器都正常工作,我认为这可能是我的 Python 或 pySerial 安装的问题,所以我尝试测试它们。我有另一个控制器,它简单地回显它获得的任何输入字节序列。使用相同的 Python 程序测试运行:

Port: COM5
Is open? True
Writing: b'\xff\xfe#\x00N\x00A\x00M\x00E\x00'
Reading: b'\xff\xfe#\x00N\x00A\x00M\x00E\x00'

请有人解释一下,发生了什么,我如何使用 Python 与第一个控制器对话?

更新:

我使用了一个串口监控程序来观察数据流:

Arduino IDE 串口监视器数据交换日志('#NAME',无尾行字节,波特率=115200):

Port opened by process "javaw.exe" (PID: 2792)

Request: 27.12.2017 16:24:37.38864
 23 4E 41 4D 45                                    #NAME           

Answer: 27.12.2017 16:24:37.58964 (+0.2010 seconds)
 41 52 44 55 49 4E 4F 0D 0A                        ARDUINO..       

Port closed

C# 程序交换日志('#NAME',无尾行字节,波特率=115200):

Port opened by process "ConsoleApplication1.exe" (PID: 7004)

Request: 27.12.2017 16:31:24.69564 (+26.5445 seconds)
 23 4E 41 4D 45                                    #NAME           

Answer: 27.12.2017 16:31:26.72564 (+2.0291 seconds)
 41 52 44 55 49 4E 4F 0D 0A                        ARDUINO..       

Port closed

Python 程序交换日志(b'#NAME',无尾行字节,波特率=115200):

Port opened by process "python.exe" (PID: 2416)

Request: 27.12.2017 16:39:32.00464 (+139.8020 seconds)
 23 4E 41 4D 45                                    #NAME           

Port closed

三个程序都写了相同的字节序列,我不明白,为什么Python程序没有得到响应。

【问题讨论】:

    标签: c# python arduino


    【解决方案1】:

    您正在使用带有 BOM 的 UTF16 编码,这很可能是不正确的。通常这些协议需要带有换行符的 ASCII:

    import serial
    from time import sleep
    
    msg = "#NAME\r\n".encode('ascii')
    port = serial.Serial("COM5", baudrate=115200, parity=serial.PARITY_NONE, bytesize=8, stopbits=serial.STOPBITS_ONE, timeout=2)
    
    print("Port:", port.name)
    print("Is open?:", port.is_open)
    print("Writing:", msg)
    
    port.write(msg)
    sleep(1)
    
    output = port.read_until(size=len(msg))
    print("Reading:", output)
    
    port.close()
    

    【讨论】:

    • 是的,我担心输入字节序列格式不匹配。不幸的是,它是一个遗留草图,它是在没有考虑标准实践的情况下编写的。测试序列不使用任何尾行字节。事实证明,问题可能不仅仅是编码不匹配。我已经更新了我的帖子,如果你有时间请看一下。
    【解决方案2】:

    在打印结果之前尝试msg = msg.decode('ascii')msg = msg.decode('utf-16')。那是在print("Writing:", msg) 行之前。 我遇到了类似的问题并尝试了这个,它对我有用。

    【讨论】:

      【解决方案3】:

      原来,我的控制器设备有问题。我仍然不知道为什么它没有响应使用 Python 发送的请求,而它使用 C# 和 Arduino IDE 都响应了,但是用新设备替换它后,我在所有环境中都得到了所需的响应。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多