Python串口通信

9 投票
2 回答
24097 浏览
提问于 2025-04-16 17:54

我正在做一个Arduino项目,因为内存有限,所以需要用Python脚本来配合。在Python这边,我有一个二维矩阵,里面存储了坐标的x和y值,这个列表里有26000对坐标。为了让大家更清楚这个数据结构,pathlist[0][0]会返回我列表中第一个坐标的X值。在Python中对这个列表进行各种操作都没有问题。但是,我在把这些值通过串口发送给Arduino时遇到了麻烦,想要以有用的方式发送。

由于串口通信的特点(至少我认为是这样),我必须把每个整数作为字符串发送,而且一次只能发送一个数字。所以像345这样的数字会被分成3个单独的字符,依次是3、4和5。

我现在的问题是,如何在Arduino上重新构建这些整数。

每当我发送一个值时,Arduino接收到的数据输出是这样的:

  //Python is sending over the number '25'
  2ÿÿ52
  //Python is sending the number 431.
  4ÿÿ321ÿÿÿ2

Arduino的代码是:

String str;
int ds = 4;

void setup() {
    Serial.begin(9600);
}

void loop(){
    if (Serial.available()>0) {
        for (int i=0; i<4; i=i+1) {
            char d= Serial.read();
            str.concat(d);
        }

        char t[str.length()+1];
        str.toCharArray(t, (sizeof(t)));
        int intdata = atoi(t);
        Serial.print(intdata);
    }
}

Python的代码看起来是这样的:

 import serial

 s = serial.Serial(port='/dev/tty.usbmodemfd131', baudrate=9600)

 s.write(str(25))

我几乎可以肯定问题不在于输出方法(Serial.print),因为当我声明另一个整数时,输出格式正常,所以我认为问题出在intdata变量的构建上。

值得注意的是,如果我把Serial.print(intdata)改成Serial.print(intdata+5),结果是2ÿÿ57,我本来期待的是30(25+5)。这个7无论输入什么都会出现。例如,我可以把271发送到串口,结果看起来是这样的:

//For input 271.
2ÿÿ771ÿÿÿ7

我觉得Arduino把值分成了两两一组,并在末尾附加了长度。但我不明白为什么会这样。

我还觉得ÿ是在for循环中添加的。这意味着它们是因为当前没有发送任何东西而被添加的。但是即使通过再加一个if(Serial.available()>0)条件来修复这个问题,结果仍然没有被当作整数处理。

另外,使用Pickle在这里合适吗?我到底哪里做错了?

2 个回答

4

我会改变一下通信方式,让Python在数字之间发送换行符,这样你就不那么依赖于时间的控制了:

s.write(str(25)+'\n')

然后在接收端:

void loop(){
    while (Serial.available() > 0) {
        char d = Serial.read();
        if (d == '\n') {
            char t[str.length()+1];
            str.toCharArray(t, (sizeof(t)));
            int intdata = atoi(t);
            Serial.print(intdata);
            str = String();
        }
        else {
            str.concat(d);
        }
    }
}
5

你需要等一会儿,才能接收到串口数据。

Arduino的代码应该是:

if (Serial.available()){
    delay(100); // Wait for all data.
    while (Serial.available()) {
        char d = Serial.read();
        str.concat(d);
    }
}

另外,在重新使用字符串之前,你得先把它清空。

[编辑]

我忘了提到,ÿ等于-1,也等于255,这意味着Serial.read()在说它什么都读不到。

撰写回答