4

I am trying to send & receive data between Raspberry Pi (using C programming) & Arduino (using Arduino IDE).

Based on what I can find on the internet, it points to me that both are in little endian format.

I am sending integers between them using a serial communication (RS232) with the library "RS-232 for Linux and Windows" at teuniz.net/RS-232

Based on my knowledge, if both are in little endian format, I do not need to do any shifting on the bits. However, in my case with the codes below, there is a need for me to shift the bits read in by Arduino. I am not sure why I need to perform the bit shifting when both are little endian (in order to get the correct data). Without further ado....

C Code:

unsigned char buf[4];
int g = 100;
memcpy(buf, (char*)&g, sizeof(int));

// port 24 for ttyACM0
if(RS232_SendBuf(24, buf, sizeof(int)) == -1)
{
    // error processing here
}

Arduino Code:

long a[4];
long value = 0;

 void loop(){
   if(Serial.available()>=4){
    for(int i = 0; i < 4 ; i++){
      a[i] = Serial.read();
    }

    // Over here i need to shift the LSB of the byte received to the MSB of the long var until the MSB of byte becomes LSB of long var
    // i do not have the code which is faulty right now as its already past midnight and my group mates are already asleep so I will post again in the morning
    value += a[0];
    value += a[1] << 8;
    value += a[2] << 16;
    value += a[3] << 24;

    Serial.println(value); // now it prints out 100 correctly

    value = 0;
   }

 }

Would appreciate all help! Sorry still new to C and endian!

UPDATE: I think i know why the above is happening! Please comment below to let me know if my assumption is right/wrong!

I am sending an int value of 170 in C. 170 is 0x000000aa in HEX. When i memcpy (this is where little endian comes in), it is stored as aa 00 00 00 (LSB to MSB). So when i get the value in arduino, i will definitely need to do the shifting as an integer is read from MSB to LSB (and because there is no memory copy/read in arduino, i do not care any endian problem here).

However, as Arduino is slow in processing (it has a lot of other stuffs to calculate!!), can i make my C code such that:

int g = 170;
unsigned char buf[4];
// below line not needed anymore??
//memcpy(buf, (char*)&g, sizeof(long));

if(RS232_SendBuf(24, (char *)&g, sizeof(int)) == -1)
{ ... }

Would like to hear more so I can learn more! Looks like I got my basics wrong at the beginning when I asked this question!

Doe Joe
  • 127
  • 1
  • 3
  • 11
  • related: http://stackoverflow.com/questions/17461623/byte-order-of-serial-communication-to-arduino – msw Mar 01 '16 at 16:17
  • 1
    Why do you comment that `value += a[0]; value += a[1] << 8;` is "big endian to little endian". Looks like reading little endian to me. No "big endian" involved. – chux - Reinstate Monica Mar 01 '16 at 16:30
  • @chux i commented it because I am now trying to make the least significant bit to go all the way to the left and MSB all the way to right! However when I'm sending from raspberry pi I already made sure that it is LSB to MSB from buf[0] to buf[3]! So not very sure why on Arduino side I am receiving MSB to LSB and had to do that conversion to read the integer correctly! – Doe Joe Mar 01 '16 at 16:38
  • How does `value += a[0];` apply to "trying to make the least significant bit to go all the way to the left"? The LSBit is in `a[0]`. – chux - Reinstate Monica Mar 01 '16 at 16:44
  • @chux sorry my bad! it should be "it is shifting the MSB all the way to the left!" If I send AA 0 0 0 (170) from Raspberry, when I print out on Arduino, it is 0 0 0 AA if I do not do the bit shifting! – Doe Joe Mar 01 '16 at 16:46
  • "shifting the MSB all the way to the left" is _not_ changing endian. The MSB is supposed on the "left". Don't you write/read numbers with the MSByte on the left? – chux - Reinstate Monica Mar 01 '16 at 16:51
  • You didn't show the code that allegedly fails! Since your shifting is collecting bytes in little-endian format, what did you do that went wrong? – Weather Vane Mar 01 '16 at 16:52
  • You have not posted how you do "when I print out on Arduino, it is 0 0 0 AA if I do not do the bit shifting!" so how can SO comment on what is not shown? – chux - Reinstate Monica Mar 01 '16 at 16:52
  • @WeatherVane unfortunately i do not have the code that went wrong right now! but what that code does is basically a for loop printing values of a[0] to a[3]. I will update the faulty code later once I have it – Doe Joe Mar 01 '16 at 16:57
  • @chux sorry am still new to all this!! can I clarify: if RPi saves integer in LSB to MSB format, when I'm reading from Arduino, i shift the MSB to the left and so on till LSB is on the right, is this operation/process totally normal? Should I instead send MSB to LSB from RPi side so I don't have to shift the MSB and LSB in Arduino? And does this mean that Arduino reads int from MSB to LSB format? (because RPi has no problem reading a LSB to MSB as an integer correctly) – Doe Joe Mar 01 '16 at 17:03
  • Let's say the data was sent in the opposite order, would you still have code `value += a[3]; value += a[2] << 8; value += a[1] << 16; value += a[0] << 24;`? In other words, code is still shifting in Arduino! – chux - Reinstate Monica Mar 01 '16 at 17:24
  • @chux theoretically speaking, if data is sent in opposite order, i will remove that code from Arduino (otherwise i would be doing the shifting twice in total!!!) I need to test this out further but not at this moment as its already past 1am! will try and update here when my group meets at about 9am later. – Doe Joe Mar 01 '16 at 17:26
  • If you remove that code, how would yo do `Serial.println(value);`? That is the only posted output of the function. – chux - Reinstate Monica Mar 01 '16 at 17:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105035/discussion-between-doe-joe-and-chux). – Doe Joe Mar 01 '16 at 18:04

2 Answers2

2

Your code looks fine to me (I haven't run it).

  • Suppose you had the integer 0xaabbccdd.
  • On the Pi, "buf" would contain dd, cc, bb, aa. They would be sent down the wire in that order.
  • On the arduino, a would also contain dd, cc, bb, aa.
  • Then you create value as (dd << 0) + (cc << 8) + (bb << 16) + (aa << 24), giving 0xaabbccdd.
peterpi
  • 575
  • 2
  • 11
  • Yes this is frustrating! We sent in dd,cc,bb,aa from Raspberry pi to Arduino. However when Arduino is reading in from the serial, it prints aa,bb,cc,dd if we do not perform the bit shifting! – Doe Joe Mar 01 '16 at 16:36
  • That is probably because your `RS232_SendBuf()` sends the bytes that way. At the receiving end you read each **byte** separately (and not as **long** type). So it is not the question if your Arduino is little endian or big endian. As long as you store the bytes in the order you want, Arduino will see what you have written as little endian. – jada12276 Mar 01 '16 at 17:11
0

You are parsing a 32 bit little endian value, not a big endian value. The first byte ends up in the least significant bits; the last byte ends up in the most significant bytes.

If you were converting a buffer which contained a big endian value, the code would look like:

uint8_t a[4];
int value = 0;
for ( int i = 0; i < 4; ++i )
{
    value << 8 * i;  // shift everything over one byte
    value += a[ i ]; // add the next byte to the LSByte
}

You see the difference?

Rob K
  • 8,757
  • 2
  • 32
  • 36