Python代码通过串行方式与Arduino接口不在Raspberry Pi上工作

Python代码通过串行方式与Arduino接口不在Raspberry Pi上工作,python,arduino,raspberry-pi,arduino-uno,Python,Arduino,Raspberry Pi,Arduino Uno,我有一个python脚本,可以通过串口与arduino通信。它在我的计算机上按预期工作,但当我在我的Raspberry Pi上运行脚本时,它不工作。打印“已发送:1”后会卡住。我认为它一直在等待arduino的一个字节(sendValue的第一行)。然而,我不知道为什么会发生这种情况,因为它可以从我的计算机或Pi的串行监视器上正常运行 Python脚本: import serial ser = serial.Serial('/dev/ttyACM0', 9600) def sendValue(

我有一个python脚本,可以通过串口与arduino通信。它在我的计算机上按预期工作,但当我在我的Raspberry Pi上运行脚本时,它不工作。打印“已发送: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社区,所以我把它放在这里。

更好的方法是使用给定的无效字符so
Serial.parseInt()
,解析停止

跳过不是数字或减号的初始字符; 当未读取可配置超时值的字符或读取非数字时,解析停止; 如果发生超时(请参阅Serial.setTimeout())时未读取有效数字,则返回0

然后你可以这样做:

var1 = Serial.read();
var2 = Serial.read();
var3 = Serial.read();
在python中:

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

您可能遇到与Arduino自动复位相关的问题。重置Arduino后,需要几秒钟“重新启动”并开始运行其主程序(
loop()
)。当您使用Unix操作系统(如Raspberry Pi)连接到Arduino时,它会触发自动重置。如果Python脚本在连接后立即将数据发送到Arduino,则启动加载程序可能会捕获该数据,而不是捕获Arduino处理器代码,因为处理器尚未就绪,因此Arduino的行为就像什么都没有发生一样。如果在Windows上测试Arduino,则可能看不到此行为;某些Windows配置不会在初始连接时触发自动重置,串行监视器也是如此

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

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

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

您说过我应该将
Serial.println('ready')
添加到
setup()
setup()
是否每次通过串行连接时都运行?处理器每次启动时都会运行
setup()
例程,即:1)通电,2)按主板上的重置按钮,或3)通过内置USB端口打开串行连接(“自动重置”)。自动复位允许您通过USB连接对电路板进行编程。请参阅详细信息或谷歌“arduino autoreset”。注意,在某些情况下,Windows主机不会触发自动重置,但Linux或OS X将始终触发自动重置。完美。谢谢我的团队大部分人都是开玩笑的。应该没问题。我终于有机会再次玩这个了。它几乎起作用了。第一次运行脚本时效果很好。但是,当我第二次使用python连接时,
setup()
函数似乎不会再次运行。有什么建议吗?