【问题标题】:Python code to interface with Arduino over serial not working on Raspberry Pi通过串行与 Arduino 交互的 Python 代码在 Raspberry Pi 上不起作用
【发布时间】:2016-03-26 04:53:03
【问题描述】:

我有一个 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 社区,所以我把它放在这里。

【问题讨论】:

    标签: python arduino raspberry-pi arduino-uno


    【解决方案1】:

    您可能遇到与 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 连接对电路板进行编程。查看详情here 或谷歌“arduino autoreset”。
    • 请注意,在某些种情况下,Windows 主机不会触发自动重置,但 Linux 或 OS X 将始终这样做。
    • 完美。谢谢。我的大部分团队都在 *nix 上。应该不是问题。
    • 我终于有机会再次玩这个了。它几乎可以工作。我第一次运行脚本时工作正常。但是,当我第二次使用 python 连接时,setup() 函数似乎没有再次运行。有什么建议吗?
    【解决方案2】:

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

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

    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')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-27
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多