0

I have written a program for the Arnuino that sends a struct witin a union to a program on the PC. The struct has to integers but i dont't get the right output. The program on the PC makes use of the boost library for the serial conection. And is build and compiled in 64bit (with vs2010).

The code works if i have a single integer variable within a union. But a struct witin a union doesn't work. Only one integer gets data and that data is wrong.

I it maby a 64 bit(pc) and 32bit(Ardunio) problem? And can anyone help me with this. Thanks in advance.

The PC code snippet (serial settings are omitted):

union packed{
  struct test{
  unsigned int data;
  unsigned int data2;
} struc;

 unsigned char bytes[8];
}SerialPacked;

  SerialPacked.struc.data = 0;
  SerialPacked.struc.data2 = 0;

  cout << "Data before: " << SerialPacked.struc.data << endl;
  cout << "Data2 before: " << SerialPacked.struc.data2 << endl;

  read(port,buffer((unsigned char*)&SerialPacked.bytes[0], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[1], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[2], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[3], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[4], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[5], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[6], 1));
  read(port,buffer((unsigned char*)&SerialPacked.bytes[7], 1));

  cout << "Data after: " << SerialPacked.struc.data << endl;
  cout << "Data2 after: " << SerialPacked.struc.data2 << endl;

The Arduino code:

int ledPin = 13;


union packed{
    struct test{
      unsigned int data;
      unsigned int data2;
}struc;
    unsigned char bytes[8];
} 
SerialPacked;

void setup() {  
    pinMode(ledPin, OUTPUT); 
    Serial.begin(9600); 

   SerialPacked.struc.data = 0;
   SerialPacked.struc.data2 = 0;
};




void loop() {

while(1){
  digitalWrite(ledPin,HIGH);
  SerialPacked.struc.data = SerialPacked.struc.data + 1;
  SerialPacked.struc.data2 = SerialPacked.struc.data2 + 1;;

  for(int i=0;i <8; i++){ 
    Serial.write(SerialPacked.bytes[i]);
  };

    digitalWrite(ledPin,LOW);
    delay(1000);
 };

}
RSNL
  • 213
  • 3
  • 15
  • 3
    Can you accept answers to your other questions? Also, format and indent your code properly? Thanks. – netcoder Sep 26 '12 at 15:54
  • Mabybe a very supid question but where do i accept answers? – RSNL Sep 26 '12 at 16:02
  • 1
    Go to your previous questions. For each answer, there's a checkmark icon next to it. Click on it to accept the answer as the best answer. – netcoder Sep 26 '12 at 16:03
  • As a first step I would definitely compile your program to be 32 bit only. If your 64 bit program is trying to read a 64 bit long int from a 32 bit long structure it probably won't be happy. The size of the integers may not map properly. You also should check your boost library and make sure its reading for 32 bit send off the wire. If boost is expecting 64 bit on the other end things will also be screwy. – devshorts Sep 26 '12 at 16:09
  • 1
    @devshorts: There's no point doing that. You could just force the integers to fixed sizes like `int16_t`, etc. You'd still have problems with padding though, since each CPU may have different alignments. – netcoder Sep 26 '12 at 16:10
  • @netcoder, good point, thanks! Either way having the types not match bit lengths would cause a problem like roy describes. – devshorts Sep 26 '12 at 16:14
  • You guys can't answer the question, i looked under the user page->questions and answers but i can't find any checkmarks? – RSNL Sep 26 '12 at 16:14
  • 1
    @RoyStegers: Open up each of your question separately. – netcoder Sep 26 '12 at 16:16
  • 1
    @devshorts: True. Although I'm pretty sure [padding will eventually cause problems, according to other questions](http://stackoverflow.com/questions/11346350/sizeof-difference-between-c-on-pc-and-arduino). – netcoder Sep 26 '12 at 16:16
  • @netcoder, cool! learned something new – devshorts Sep 26 '12 at 16:21
  • Proper byte-by-byte protocol needed.. – Martin James Sep 26 '12 at 16:27

2 Answers2

1

The issue is that int on Arduino is two bytes, but an int on your PC is probably four bytes. Depending on your compiler, there may be a switch that you can use to set the size for int, or you can just use a more explicit type. The idea with int is that it's supposed to allow easy adaptation of code from one platform to another by adopting whatever the natural size is for the host platform. For that same reason, though, it's not a good choice for transferring data between platforms.

To confirm that this is the problem, try reading the bytes out of SerialPacked instead of accessing struc. I'm sure you'll find that all the data is there -- it's just the way you're trying to read it that's the problem.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • So for both the pc and arduino struct i need to use something like int16_t? Do i need to cast it then after transmition to integer? Or can i preform logical operations on int16_t? like +? – RSNL Sep 26 '12 at 16:24
  • You have to make sure that both platforms use the same size for each field. What size you choose is up to you; since you've got 8 bytes and two ints, using 32-bit ints (`int32_t`) might make more sense. – Caleb Sep 26 '12 at 16:35
  • Thanks for the feedback! One more follow up question if you don't mind. I it true that because the struct is in a union that there are no padding issuses because there is union is just one memory space with no seperations between the variables? – RSNL Sep 26 '12 at 17:07
  • 1
    @RoyStegers: No that's not true. The `union` there doesn't change anything in regards to padding. You can prevent padding using `#pragma pack` or `__attribute((packed))` on most compilers, although it may cause problems on some CPUs. – netcoder Sep 26 '12 at 17:40
0

I have solved it wel sort off... I changed the integers in the stuct in the Arduino code to longs. Data comes correct over the line.

Is this because the long on the 32 bit Ardunio is the same size as the integer on the 64 bit vs2010 code? Or am i missing something here? Thanks for the feedback!

RSNL
  • 213
  • 3
  • 15