Python serial communication

2020-06-16 01:14发布

问题:

I'm working on an Arduino project, and I am interfacing it with a Python script due to memory limitations. On the Python side I have a 2 dimensional matrix containing respective x, y values for coordinates, and in this list is 26000 coordinate pairs. So, in interest of clarifying the data structure for all of you, pathlist[0][0], would return the X value of the first coordinate of my list. Performing different operations, etc. on this list in Python is posing no problems. Where I am running into trouble however is sending these values to Arduino over serial, in a way that is useful.

Due to the nature of serial communication (at least I think this is the case) I must send each each integer as a string, and only one digit at a time. So, a number like 345 would be sent over as 3 individual characters, those being of course, 3, 4, then 5.

What I am struggling with is finding a way to rebuild those integers on the Arduino.

Whenever I send a value over, it's receiving the data and outputting it like so:

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

The Arduino code is:

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);
    }
}

And the Python code looks like this:

 import serial

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

 s.write(str(25))

I'm almost certain that the problem isn't stemming from the output method (Serial.print), seeing as when I declare another int, it formats fine on output, so I am assuming the problem lies in how the intdata variable is constructed.

One thing of note that may help diagnose this problem is that if I change Serial.print(intdata) to Serial.print(intdata+5) my result is 2ÿÿ57, where I would expect 30 (25+5). This 7 is present regardless of the input. For instance I could write 271 to the serial and my result would look as follows:

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

It appears to me that Arduino is chunking the values into pairs of two and appending the length to the end. I can't understand why that would happen though.

It also seems to me that the ÿ are being added in the for loop. Meaning that they are added because nothing is being sent at that current moment. But even fixing that by adding yet another if(Serial.available()>0) conditional, the result is still not treated like an integer.

Also, would using Pickle be appropriate here? What am I doing wrong?

回答1:

You should wait a bit for the serial data to arrive.

The Arduino code should be:

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

Also you have to clear your string before re-using it.

[Edit]

I forgot to mention ÿ == -1 == 255 which means Serial.read() it is saying it can't read anything.



回答2:

I would change the communication so python sends newlines between numbers, so you're not as dependent on the timing:

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

and then on the receiving side:

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);
        }
    }
}