Serial connection question [SOLVED]

Hi all,

I have a serial connection question:

I have a serial arduino program that recieves and sends data to a client on the pc. in the arduino program i wait unitl 28 or more bytes are avalible for the serial. The data struct that it recieves is 28 bytes big.

The sketch is as followed:

#include <Servo.h>
#include <CommunicationModule.h>

// ObjectInfo struct definition
struct ObjectInfo {
	int32_t ObjectXCor;
	int32_t ObjectYCor;
	int32_t ObjectMass;
};

// ObjectInfo struct definition
struct SensorDataStruct{
	int32_t PingData;
	int32_t IRData;
	int32_t ForceData;
	int32_t CompassData;
};

// ObjectInfo struct definition
union PackedSend{
	struct CommStruct{
		ObjectInfo VisionData;
		SensorDataStruct SensorData;
	} CommData;
	unsigned char bytes[28];
}SendData;

// ObjectInfo struct definition
union PackedRecieve{
	struct CommStruct{
		ObjectInfo VisionData;
		SensorDataStruct SensorData;
	} CommData;
	unsigned char bytes[28];
}RecieveData;



void Send(){
  
  for(int i=0;i <sizeof(SendData); i++){ 
    Serial.write(SendData.bytes[i]);
  };
};

void Recieve(){
  for(int i=0;i <sizeof(RecieveData); i++){ 
    RecieveData.bytes[i] = Serial.read();
  };
};

void setup() {  

  Serial.begin(9600); 
  Serial.flush();
};

void loop() {
  
  SendData.CommData.SensorData.CompassData = 100;
  SendData.CommData.SensorData.IRData = 222;
  SendData.CommData.SensorData.ForceData = 333;
  SendData.CommData.SensorData.PingData = 444;
  SendData.CommData.VisionData.ObjectXCor = 555;
  SendData.CommData.VisionData.ObjectYCor = 666;
  SendData.CommData.VisionData.ObjectMass = 777;
  
  RecieveData.CommData.SensorData.CompassData = 0;
    RecieveData.CommData.SensorData.CompassData = 0;
   RecieveData.CommData.SensorData.IRData = 0;
   RecieveData.CommData.SensorData.ForceData = 0;
   RecieveData.CommData.SensorData.PingData = 0;
   RecieveData.CommData.VisionData.ObjectXCor = 0;
   RecieveData.CommData.VisionData.ObjectYCor = 0;
   RecieveData.CommData.VisionData.ObjectMass = 0;
  
  
  while(1){
     // SendData.CommData.SensorData.CompassData++;//   SendData.CommData.SensorData.CompassData + 1;
    //Check if packed size is 28
    if (Serial.available() >= 28) {
     Recieve();   
     SendData.CommData.SensorData.CompassData =  RecieveData.CommData.SensorData.CompassData;
     Send();
    };
     
     //delay(1000);
     Serial.flush();
  };
}

If i remove the serial check the there is a send and recieve on de pc an Arduino but the data is wrong.

The PC program that sends an recieves the struct back is as followed (it uses Boost):

	if (Serial1.Connect() != 0) {
	    cout << "Connection failed" << endl;
	   return 0;
                  }

                  cout << "Connected" << endl;


                while (1) {

	               cout << "Before send" << endl;
	              cout << "Size of packet that will be send: " << sizeof(Serial1.SendDataPacked) << endl;

	                Serial1.SendData();
	
	                Serial1.RecieveData();
		
                                    cout << "Compassdata recieve: "	<<  Serial1.RecieveDataPacked.CommData.SensorData.CompassData
	                << endl;

}

It keeps waiting for data that needs to be recieved back. Does anyone have a idea? All suggestions are welcome! If i need to supply more information or code please say so!

  };
};

The only blocks that end with a semicolon are class and struct definition blocks. for loops and functions do not. if statements and while loops do not, either.

If i remove the serial check the there is a send and recieve on de pc an Arduino but the data is wrong.

What "serial check" are you referring to? If you mean the one the involves Serial.available() returning a value greater than or equal 28, I would not expect you to get good data, because then you try to read data that hasn't arrived yet. If you mean something else, quit being vague.

@PaulS:

Thank you for your reply, i removed the semicolons. What i mean with serial check is indeed the Serial.available(). If i flush the line before and after a send and recieve operation then the next 28 bytes are a new data struct? Or is this not true.

What is te correct way to only read if data when new data has been completely send over when sending form PC to Arduino and visa versa?

Hi All,

I solved my problem, when i read the documantation. The Arduino serial buffer is 64 bytes big so checking for a value greater then 63 (counting starts form 0) will never be true.

Thanks PaulS, your comments pointed me in the right direction.

Also on the PC i have to wait a bit to let the PC and Arduino set up te connection after connect (on the PC).

You can read serial data as it arrives, rather than waiting for it all to arrive. You simply need to keep track of the number of bytes you have read, and put the next byte in the next position and increment the counter.

You make no attempt to use the data until the full packet has been received. You know when this happens when the received byte count is right.

Or do you? No. Serial data delivery is not guaranteed. If a byte gets lost, your whole communication process is hosed. That's why sending binary data over serial is not a good idea. You have no way of knowing when a byte is lost. Therefore you have no way of knowing that a packet is, or is not, complete. You could do something like send some known value as the first element in the structure and some known value as the last element in the structure. Then, if the received values, after the proper number of bytes has been read, are not correct, you know to discard the packet.

Unfortunately, getting back in sync then is a real bitch.

Even though it is faster, sending binary data of any size/complexity is not a good idea.