简体   繁体   English

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

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

I have a python script that communicates with an arduino over serial. 我有一个通过串行与arduino通信的python脚本。 It works as expected on my computer but when I run the script on my Raspberry Pi, it does not work. 它可以在计算机上按预期工作,但是当我在Raspberry Pi上运行脚本时,它不起作用。 It gets stuck after printing "Sent: 1". 打印“发送:1”后卡住。 I think it is stuck waiting for one byte from the arduino (first line from sendValue). 我认为它在等待来自arduino的一个字节(sendValue的第一行)。 However, I don't know why this is happening as it works fine running it from my computer or the Pi's serial monitor. 但是,我不知道为什么会这样,因为通过我的计算机或Pi的串行监视器运行它可以正常工作。

Python script: 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 code: 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;
    }
}

I have tried putting a delay in instead of the ser.read(1) where I think it is getting stuck but that still doesn't work. 我尝试放置一个延迟,而不是ser.read(1) ,我认为它被卡住了,但仍然不起作用。

I could not decide whether to put this on the Raspberry Pi community or Arduino community so I put it here. 我无法决定是将它放在Raspberry Pi社区还是Arduino社区,所以我把它放在这里。

A better way to do this would be to use the fact that an invalid character given so Serial.parseInt() , parsing stops. 更好的方法是使用这样的事实,即给定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; 如果在发生超时(请参见Serial.setTimeout())时未读取到有效数字,则返回0;否则返回0。

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

Then you could do something like this: 然后,您可以执行以下操作:

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

and in python: 并在python中:

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

You may have an issue related to the Arduino auto-reset. 您可能遇到与Arduino自动重置有关的问题。 When the Arduino is reset, it takes a few seconds to "reboot" and start running its main program ( loop() ). 重置Arduino后,需要几秒钟的时间来“重新启动”并开始运行其主程序( loop() )。 When you connect to an Arduino with a Unix OS (eg Raspberry Pi), it triggers the auto-reset. 当您使用Unix OS(例如Raspberry Pi)连接到Arduino时,它将触发自动重置。 If your Python script immediately sends data to the Arduino after the connection, this data may get captured by the boot loader instead of the Arduino processor code because the processor is not ready, so the Arduino acts like nothing is happening. 如果您的Python脚本在连接后立即将数据发送到Arduino,则该数据可能会被引导加载程序而不是Arduino处理器代码捕获,因为处理器尚未就绪,因此Arduino就像什么都没有发生。 You might not see this behavior if you test the Arduino on Windows; 如果您在Windows上测试Arduino,则可能看不到此行为。 some Windows configurations do not trigger the auto-reset on the initial connection, and the same for the serial monitor. 某些Windows配置不会在初始连接上触发自动重置,串行监视器也是如此。

My solution is simply to add a delay of 5 seconds after the serial connection is created in your python script, but before any data is transmitted. 我的解决方案是在您的python脚本中创建串行连接之后,但在传输任何数据之前,仅添加5秒的延迟。 If this solves the problem, then you can get more creative about solutions to tell the host when the Arduino is ready. 如果这样可以解决问题,那么您可以在解决方案上更具创意,以便在Arduino准备就绪时告诉主机。 For example, you can print a line to the host at the end of the setup() portion of the Arduino sketch ( Serial.println('READY'); ). 例如,您可以在Arduino草图( Serial.println('READY'); )的setup()部分的末尾向主机打印一行。 You can also put a few lines of code that makes the onboard LED blink at the end of the setup() routine, as a visual cue for troubleshooting: 您还可以在setup()例程的末尾添加几行代码,使板载LED闪烁,作为进行故障排除的直观提示:

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

When you see the double-blink, you know the processor is ready to receive communication from your host program. 当您看到双闪烁时,您就知道处理器已准备就绪,可以接收来自主机程序的通信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM