Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I use the Arduino compatible chipKIT WF32 board. I want to transfer structure data between my board and a Linux PC. Can I do it like the following?

struct data d;
char *tx = (char*)d;
Serial.print(tx);

Even if the above code works, the data type size in Arduino and on Linux will vary. Is there a way to serialize the data, like Protocol Buffers on Arduino?

share|improve this question
1  
Casting to a char* will make Serial.print expect a null terminated string. So the amount of data transferred will depend on the next zero byte in memory(arbitrary). – user2973 Apr 7 '15 at 15:49
up vote 0 down vote accepted

The following solution isn't strictly portable, but it should work as long as both ends are little-endian (most platforms).

You can use the GCC attribute packed to tell the compiler not to pad the fields like this:

struct __attribute__ ((packed)) my_struct {
  char c;
  int32_t n;
};

Then you can send your struct like this:

Serial.write((uint8_t*) a_my_struct_ptr, sizeof(my_struct));

On the receiving end you just copy the received data to a similarly packed struct. If you would rather use Python over C/C++ you can use the struct module to unserialize the data.


I just googled your product and the MIPS processor is bi-endian, but I will assume that it is configured for little-endian by default. You can try and see if ints keep their value after transmit. Also remember to use explicit size types such as int16_t, uint64_t, etc.

share|improve this answer
    
This may get messy - is an int 32 bits on the chipkit reflecting its processor's actual word width, or is it 16 bits for compatibility with ATmega-insipired Arduinos? It probably makes sense to use explicit width types on both ends. – Chris Stratton Apr 8 '15 at 12:41
    
Yes you are right I forgot to consider that, I've updated the answer to use fixed size types. – user2973 Apr 8 '15 at 20:32

I usually send structures from arduino via serial port to PC and use the memcpy function to do it. Let's say you have the struct data d:

 struct data d;
 len = sizeof(d);
 char aux[len];
 memcpy(&aux,&d,len);
 Serial.write((uint8_t *)&aux,len);

It is useful to create a starting and ending character to delimit your important data and make sure you receive all data and good information. Let me give you one of my recent work example:

...

void send_state(){
 char aux[39];
 memcpy(&aux, &state, Comm_size);
 Serial.write('S');
 Serial.write((uint8_t *)&aux, Comm_size);
 Serial.write('E');
 return;
}
...

In this example the struct state is preceded with "S" (start) and suceded with "E". Then in python, for example, you can get the data using the unpack function. In my case:

...

# wait for data from arduino
myByte = port.read(1)
if myByte == 'S':
    data = port.read(39)
    myByte = port.read(1)
    if myByte == 'E':
        # is  a valid message struct
        new_values = unpack('<c6BH14B4f', data)

...

See if arduino sends data in little endian. The one I have used to send it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.