Pages: 1 2 [3]   Go Down
Author Topic: Ard <--> Pi serial data transfer(unsolved)  (Read 4563 times)
0 Members and 1 Guest are viewing this topic.
Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49385
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
        sDA = serialDataAvail(fd);
         while (cChar != '>' ){
           if (sDA > 0){
             printf("Getting data!\n ");
             cChar = serialGetchar(fd);
             recBuff[x] = cChar;
             x++;
             }
          else if(sDA == 0){
             printf("Got no Data\n");
             }
            break;
            }
So, suppose 3 bytes arrive before this function gets called. It just keeps reading and reading - most likely getting garbage, until finally the > trickles in. No! No! No!

You know how many bytes are available to read. Do NOT read more than than without updating the count of bytes available to be read.
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i understand the words you used i however do not see where exactly you want the count. should it be like
Code:
sDA = serialDataAvail(fd);
         while (cChar != '>' ){
           if (x <= sizeof(recBuff)-1){ // read only 22 then pass to end and get the \0 null for 23?
             printf("Getting data!\n ");
             cChar = serialGetchar(fd);
             recBuff[x] = cChar;
             x++;
             }
          else if(sDA == 0){
             printf("Got no Data\n");
             }
            break;
            }
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i still have my doubts on this being the best way to send data to the Pi for processing and back and in time for the bot not to drive off a cliff or into traffic or a wall.
but i guess ill try and see what the speed of data is this way.

FYI here is a sample of the REAL struct. it occurred to me you might be thinking to small

Code:
struct StructBuff_t {
  float imuRoll;  //MinIMU-9 data
  float imuPitch;//MinIMU-9 data
  float imuYaw; //MinIMU-9 data
  long flAt;  // GPS latitude
  long flOn; // GPS Longitude
  unsigned long Speed; //GPS speed
  unsigned long Date;  //GPS date
  unsigned long Course; //GPS curent course
  unsigned long Time;   //GPS Time
  unsigned long Fix_age; //GPS age of signal fix 
  unsigned int FC_AP;     //Front Center Ultrasonic Avrage Ping
  unsigned int FL_AP;     //Front Left Ultrasonic Avrage Ping
  unsigned int FR_AP;     //Front Rgith Ultrasonic Avrage Ping
  unsigned int RC_AP;     //Rear Center Ultrasonic Avrage Ping
  int FCir;       //Front Center Infrared sen
  int FLir;       //Front Left Infrared sen
  int FRir;       //Front Right Infrared sen
  int RCir;       //Rear  Center Infrared sen
  int BSTempature;       //Barometric sen tempature
  int BSPressure;      //Barometric sen pressure
  int Heading;         //LM303 mag heading
}
StructBuff;

so that is the struct as it stands there most certainly will be more data being processed back and forth i assure you.
BUT i do want to see this buffed and send over serial and parse it just to see how it's done. so lead on!  smiley-grin
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok so one has even a little clue on sending structs that size to a Linux ARM system?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

(missedskipped a lot of the discussion)
To reduce size you could create 2 or more structs with an identifier as extra field to divide the 21 fields in e.g. 5 groups.

Each struct has another update frequency (if you split them well)

ultimate you send the fields per field (+ identifier) only when they are changed.

just an idea...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nice idea but i seem to be having trouble sending any stuct to the Pi and reading it back into the stuct. think it has to do with how big the bytes for vars are on Pi and Arduino. int on arduino is 2 and 4 on PI but floats are both 4 bytes so it's very confusing to me at this point. was hoping some one had sent structs back and forth and had some code for it.
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So this is my sending (arduino) side
Code:

struct MyStruct_t {
  double imuRoll;  //MinIMU-9 data
  double imuPitch;//MinIMU-9 data
  double imuYaw; //MinIMU-9 data
  long flAt;  // GPS latitude
  long flOn; // GPS Longitude
  //char GPSs{300]="";
  unsigned int FC_AP;     //Front Center Ultrasonic Avrage Ping
  unsigned int FL_AP;     //Front Left Ultrasonic Avrage Ping
  unsigned int FR_AP;     //Front Rgith Ultrasonic Avrage Ping
  unsigned int RC_AP;     //Rear Center Ultrasonic Avrage Ping
  int FCir;       //Front Center Infrared sen
  int FLir;       //Front Left Infrared sen
  int FRir;       //Front Right Infrared sen
  int RCir;       //Rear  Center Infrared sen
  double BSTempature;       //Barometric sen tempature
  int BSPressure;      //Barometric sen pressure
  int Heading;         //LM303 mag heading
}MyStruct;
void setup(){
 Serial.begin(57600);
 Serial3.begin(57600);
}
char sendBuff[90], tmpbuff[10];
void loop() {
    fillStruct();
    makeString();
    sendStr();
}

void sendStr(){
//   for (int i = 0; i < sizeof(sendBuff); i++){
   Serial.println(sendBuff);
   Serial3.println(sendBuff);
  // } 
// Serial.println("");
// Serial3.println("");   
 }
void fillStruct(){
    MyStruct.imuYaw = 111.456;
    MyStruct.imuPitch = -222.679;
    MyStruct.imuRoll = 333.012;
    MyStruct.flAt = 43.475743;
    MyStruct.flOn = -76.429243;
    MyStruct.FC_AP = 00;     //Front Center Ultrasonic Avrage Ping
    MyStruct.FL_AP = 11;     //Front Left Ultrasonic Avrage Ping
    MyStruct.FR_AP = 22;     //Front Rgith Ultrasonic Avrage Ping
    MyStruct.RC_AP = 33;     //Rear Center Ultrasonic Avrage Ping
    MyStruct.FCir = 1;       //Front Center Infrared sen
    MyStruct.FLir = 1;       //Front Left Infrared sen
    MyStruct.FRir = 0;       //Front Right Infrared sen
    MyStruct.RCir = 1;       //Rear  Center Infrared sen
    MyStruct.BSTempature = 99.1;       //Barometric sen tempature
    MyStruct.BSPressure = 30000;      //Barometric sen pressure
    MyStruct.Heading = 292;         //LM303 mag heading
   
}
void makeString(){
  strcpy(sendBuff, "<");
  dtostrf(MyStruct.imuYaw, 4,2, tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  dtostrf(MyStruct.imuPitch, 4,2, tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  dtostrf(MyStruct.imuRoll, 4,2, tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, "::");
  (MyStruct.flAt,3,6,tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  dtostrf(MyStruct.flOn,3,6,tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.Heading,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, "::");
  itoa(MyStruct.FC_AP,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.FL_AP,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.FR_AP,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.RC_AP,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, "::");
  itoa(MyStruct.FCir,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.FLir,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.FRir,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.RCir,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, "::");
  dtostrf(MyStruct.BSTempature,2,2,tmpbuff);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ",");
  itoa(MyStruct.BSPressure,tmpbuff,10);
  strcat(sendBuff, tmpbuff);
  strcat(sendBuff, ">");
  sendBuff[90] = '\0';

}
Arduino output is
Code:
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
<111.46,-222.68,333.01::333.01,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000>
dunno why lat and long are so empty after the dec but o well for now.
minicom on Pi shows the data the same at /dev/ttyAMA0 so i know it's hooked up right.


this is my PI side
Code:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringSerial.h>

void serialRead();
void prntBuff();

float yaw, pitch, roll;
int fd, z, x, sDA;
char cChar, recBuff[90];
int main ()
{
  if ((fd = serialOpen ("/dev/ttyAMA0", 57600)) < 0)
  {
   fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
    return 1 ;
  }

 for (;;)
        {
         x = 0;
         cChar = serialGetchar(fd);
        printf("Wating for data\n");
        if(cChar == '<') serialRead();
         serialRead();
 }
}

void serialRead(){
        sDA = serialDataAvail(fd);
        while (cChar != '>'  ){
           if (x < sizeof(recBuff)-1){
             printf("Getting data!\n ");
             cChar = serialGetchar(fd);
             recBuff[x] = cChar;
             x++;
             }
          else if(sDA == 0){
             printf("Got no Data\n");
             }
            break;
            }

        if(cChar == '>'){
        printf("End of data\n");
        x++;
        recBuff[x] = '0';
        serialFlush(fd);
        prntBuff();

    }
 }
void prntBuff(){
//          for(z = 0;z < sizeof(recBuff);z++){
            printf("%s\n",recBuff);
//              }
}

Pi output is this.
Code:
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 End of data
>00
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!

am i filling the array wrong or printing it wrong?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49385
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  long flAt;  // GPS latitude
  long flOn; // GPS Longitude

and yet you are assigning float values to them and using dtostrf (in one case, anyway) to convert them to strings. Why?

Code:
  (MyStruct.flAt,3,6,tmpbuff);
What's this supposed to do?
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  long flAt;  // GPS latitude
  long flOn; // GPS Longitude

and yet you are assigning float values to them and using dtostrf (in one case, anyway) to convert them to strings. Why?

Code:
  (MyStruct.flAt,3,6,tmpbuff);
What's this supposed to do?
LOL was in the middle of editing when i cut and pasted the code. as for the dtostrf it was in there from the cut and past for the fill buffer part and i passed it at this point -74.00000 is fine i am more interested in parsing the string back into values on the Pi side. ill look into fixing the dtostrf or what ever i need to use on the GPS data. prob just going to append the full GPRMC on anyhow or trans it every other send.
any who all moot when my RX code is failing.
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

so im kind of reading it in now. here is the PI side output
Code:
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
End of data
30000>
<111.46,-222.68,333.01::43.000000,-76.000000,292::0,11,22,33::1,1,0,1::99.10,30000
Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
 Wating for data
Getting data!
here is the Pi code
Code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <wiringSerial.h>

void serialRead();
void prntBuff();

int fd, sDA;
char cChar, recBuff[90];
int main ()
{
  if ((fd = serialOpen ("/dev/ttyAMA0", 57600)) < 0)
  {
   fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
    return 1 ;
  }

 for (;;)
        {
        cChar = serialGetchar(fd);
        printf("Wating for data\n");
        if(cChar == '<') serialRead();
         serialRead();
 }
}

void serialRead(){
        sDA = serialDataAvail(fd);
        while (cChar != '>'  ){
             cChar = serialGetchar(fd);
             printf("Getting data!\n ");
             read(fd,recBuff,sizeof(recBuff));

        if(sDA == 0){
          printf("Got no Data\n");
          }
            break;
            }

        if(cChar == '>'){
        printf("End of data\n");
        serialFlush(fd);
        prntBuff();
    }
 }
void prntBuff(){
            printf("%s\n",recBuff);
}
decided to try using read and write to the buffer now i need to "sync"? and better "start /stop" bits?any ideas would be great. ( thinking i need to flush my buffer, so like tmpbuff sizeof (recBuff) get the start bit to the stop bit parse the actual data into recBuff then NULL tempbuff and start over yes?. "maybe even set a value to tell the function how many chars to expect coming so like
 $tart[77]::bla bla bla::[77]$top ,using 2 of them to make sure i got the rite values and has not been corrupted?") any how now i need a better trigger and end system tho. but the read/write to fd should be good yes?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49385
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
now i need to "sync"? and better "start /stop" bits?
Syncing simply means that you start storing data when the start marker arrives and stop when the end marker arrives.

What's wrong with < and > as the markers?

You really should work on one side at a time. Get the Arduino sending data properly. Mixing types is a bad idea. Do it right. Once the Arduino sends the data correctly, reading and parsing it on the Pi should be trivial.

Code:
             read(fd,recBuff,sizeof(recBuff));
This will read whatever is there, not sizeof(recBuff) bytes, unless there are more than sizeof(recBuff) bytes available to read. Since you only sending (ssslllooowwwlllyyy) 80 characters or so, this function should never read 90 characters. If it does, it will have gobbled the end of one packet and part of the next packet.

Reading data ONE character at a time is the only way to ensure that you stop reading when the end of packet marker arrives.

Code:
        while (cChar != '>'  ){
             cChar = serialGetchar(fd);
             printf("Getting data!\n ");
             read(fd,recBuff,sizeof(recBuff));
Read a character. If its not the end of packet marker, read an throw away a character. Then, read a whole bunch of stuff. Don't bother with how much was actually read.

There is so much wrong there that I can't even begin to figure out where to start. Except over.
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 131
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
now i need to "sync"? and better "start /stop" bits?
Syncing simply means that you start storing data when the start marker arrives and stop when the end marker arrives.

What's wrong with < and > as the markers?
was thinking it would be better is all but it seems simpler to use single char delimiters so i am good with that
Quote
You really should work on one side at a time. Get the Arduino sending data properly. Mixing types is a bad idea. Do it right. Once the Arduino sends the data correctly, reading and parsing it on the Pi should be trivial.
the data on the ard side is just junk data i mixed up to have stuff to send i scraped the bot and using the bits in other things at the moment. I just wanted to send the amount and various types of data being gathered the setup of gathering -> buffering -> printing. works so no need to worry about arduino sending side at the moment.
Quote
Code:
             read(fd,recBuff,sizeof(recBuff));
This will read whatever is there, not sizeof(recBuff) bytes, unless there are more than sizeof(recBuff) bytes available to read. Since you only sending (ssslllooowwwlllyyy) 80 characters or so, this function should never read 90 characters. If it does, it will have gobbled the end of one packet and part of the next packet.
Reading data ONE character at a time is the only way to ensure that you stop reading when the end of packet marker arrives.
i get that would be the best have been trying to trigger that to happen. so read after < and stop at >.
Quote
Code:
        while (cChar != '>'  ){
             cChar = serialGetchar(fd);
             printf("Getting data!\n ");
             read(fd,recBuff,sizeof(recBuff));
Read a character. If its not the end of packet marker, read an throw away a character. Then, read a whole bunch of stuff. Don't bother with how much was actually read.
well i cant tell read how many to read because it's going to very in size by a little under 13.34% +/- each packet ( the char width of IMU and UltraSonic data is dynamic not static + not all GPS data will be same size) so any ideas on how to know ahead of when i get's there how big the amount to read would be great
Quote
There is so much wrong there that I can't even begin to figure out where to start. Except over.
got an example i know that is not working because well it's not working  smiley-grin so how would you structure the read loop to trigger on < read a dynamic amount of data and stop at >.

 not to mention this only buffers the data i have not even tried to read these into actual variables to use yet cant wait to see how fun that is  smiley-twist. thanks for replying PaulS and thank you so much for you guidance in this and past projects.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49385
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
well i cant tell read how many to read because it's going to very in size by a little under 13.34% +/- each packet ( the char width of IMU and UltraSonic data is dynamic not static + not all GPS data will be same size) so any ideas on how to know ahead of when i get's there how big the amount to read would be great
You don't need to know how many to read.

Here is some Arduino code that collects data from the serial port using the same delimiters you are using.
Code:
#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

You should easily be able to adapt this, using the methods available on the Pi to read serial data one character at a time and to tell how many characters there are waiting to be read.
Logged

Pages: 1 2 [3]   Go Up
Jump to: