Python 通过串口与 Arduino 交互的代码在 Raspberry Pi 上不起作用

Python code to interface with Arduino over serial not working on Raspberry Pi

我有一个 python 脚本可以通过串口与 arduino 通信。它在我的电脑上按预期工作,但是当我 运行 我的 Raspberry Pi 上的脚本时,它不起作用。打印 "Sent: 1" 后卡住。我认为它一直在等待来自 arduino 的一个字节(来自 sendValue 的第一行)。但是,我不知道为什么会发生这种情况,因为它在我的计算机或 Pi 的串行监视器上运行良好 运行。

Python 脚本:

import serial
ser = serial.Serial('/dev/ttyACM0', 9600)

def sendValue(value):
    ser.read(1) # Arduino will send one byte when it's ready for the value
    ser.write(value) # Send value
    print("Sent: {}".format(value))
    return;

ser.write('1') # Select function '1'
print("Sent: 1")

sendValue('5000') # Send 1st parameter to function '1'
sendValue('4000') # Send 2nd parameter to function '1'

while True:
    print(ser.readline())

Arduino 代码:

int task = 0;

int val = 0;
int val2 = 0;
int val3 = 0;

void task1(int length){
    Serial.println(length);
    digitalWrite(13, HIGH);
    delay(length);
    digitalWrite(13, LOW);
}

void task2(int length1, int length2){
    Serial.print("Running task2 with parameters ");
    Serial.print(length1);
    Serial.print(" and ");
    Serial.println(length2);
    digitalWrite(13, HIGH);
    delay(length1);
    digitalWrite(13, LOW);
    delay(500);
    digitalWrite(13, HIGH);
    delay(length2);
    digitalWrite(13, LOW);
}

void waitForSerial(){
    while(Serial.available() == 0);
}

int getValue(){
    Serial.write(48);
    waitForSerial();
    return Serial.parseInt();
}

int getCommand(){
    if(Serial.available() == 0){
        return -1;
    }

    String in = "";

    in += (char)Serial.read();

    return in.toInt();
}

void setup() {
    Serial.begin(9600);
    pinMode(13, OUTPUT);
}

void loop() {
    task = getCommand();

    switch(task){
        case 0:
            val = getValue();
            task1(val);
            val = 0;
            break;
        case 1:
            val = getValue();
            val2 = getValue();

            task2(val, val2);
            val = val2 = 0;
            break;
    }
}

我试过延迟而不是 ser.read(1) 我认为它卡住了,但仍然不起作用。

我无法决定是把它放在 Raspberry Pi 社区还是 Arduino 社区,所以我把它放在这里。

更好的方法是使用这样一个事实,即给定一个无效字符 Serial.parseInt(),解析停止。

Initial characters that are not digits or a minus sign, are skipped; Parsing stops when no characters have been read for a configurable time-out value, or a non-digit is read; If no valid digits were read when the time-out (see Serial.setTimeout()) occurs, 0 is returned;

https://www.arduino.cc/en/Reference/ParseInt

那么你可以这样做:

var1 = Serial.read();
var2 = Serial.read();
var3 = Serial.read();

并在 python 中:

ser.write('<number1>a<number2>a<number3>a')

您可能遇到与 Arduino 自动重置相关的问题。当 Arduino 被重置时,需要几秒钟 "reboot" 并启动 运行 它的主程序 (loop())。当您使用 Unix OS(例如 Raspberry Pi)连接到 Arduino 时,它会触发自动重置。如果您的 Python 脚本在连接后立即向 Arduino 发送数据,则该数据可能会被引导加载程序而不是 Arduino 处理器代码捕获,因为处理器尚未准备就绪,因此 Arduino 就像什么都没发生一样。如果您在 Windows 上测试 Arduino,您可能看不到这种行为;一些 Windows 配置不会在初始连接时触发自动重置,串行监视器也是如此。

我的解决方案是在 python 脚本中创建串行连接之后,但在传输任何数据之前,简单地添加 5 秒的延迟。如果这解决了问题,那么您可以在 Arduino 准备就绪时告诉主机的解决方案更有创意。例如,您可以在 Arduino 草图 (Serial.println('READY');) 的 setup() 部分末尾向主机打印一行。您还可以放置几行代码,使板载 LED 在 setup() 例程结束时闪烁,作为故障排除的视觉提示:

pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
delay(150);
digitalWrite(13, LOW);
delay(150);
digitalWrite(13, HIGH);
delay(150);
digitalWrite(13, LOW);

当您看到双闪烁时,您就知道处理器已准备好接收来自主机程序的通信。