9

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?

Micke
  • 2,251
  • 5
  • 33
  • 48
danem
  • 1,495
  • 5
  • 19
  • 35
  • @aix Well, I thought that Arduino was based off of java and therefore Java knowledge would be applicable to it. Ill gladly change it if I'm wrong though :D – danem May 18 '11 at 17:12
  • 1
    It's just the Arduino IDE that happens to be written in Java. Your code that runs on the Arduino is in C, so Java isn't relevant to the question. – NPE May 18 '11 at 17:15
  • Oh, my mistake. I just thought that since Arduino was based on processing (or so I thought, maybe just the IDE is) it was in turn based upon Java. But I'll change it. Not trying to add irrelevant tags to get more exposure or anything... D: – danem May 18 '11 at 17:18

2 Answers2

5

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JBernardo
  • 32,262
  • 10
  • 90
  • 115
  • 1
    Gah. I feel like this was needlessly complex post for a simple problem. Heh, I feel silly. Well it works! Thanks a lot I really appreciate it. – danem May 18 '11 at 17:26
  • One problem I am running into however is that when I try to use this on my giant list of coordinates it fails. For instance if I was only send over the first 40 x and y vals I get the result `-5062`. Am I overloading it with input or something? – danem May 18 '11 at 17:39
  • I've had this problem once. I think it was because when you send lots of data, the Arduino might no have ended the loop (notice I've added extra 100ms to the processing time by calling delay). One solution is to add an end line character and process the loop until it arrives. – JBernardo May 18 '11 at 17:44
  • I think I figured it out. I Added 2 delays on the Python side. Thanks for all your help! – danem May 18 '11 at 18:29
  • Yeah, I think you are just sending too much data too fast. Delays should help. – user1557602 Oct 23 '12 at 20:56
5

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);
        }
    }
}
Mu Mind
  • 10,935
  • 4
  • 38
  • 69