# convert 32 bit long to 4 bytes and back again - CAN Bus

So after 2 days attempting this I can't get my head round it.

So I am using CAN bus to transfer accelerometer data and time data (the micros() function if under 71 minutes will output data that can be an unsigned long), however I have to send the data as bytes. I have managed to bit shift a 16-bit int into 2 bytes but I am having trouble extrapolating that method (will add later) to using longs. I am having trouble understanding the union method as I am new to creating my own functions, so, how would you guys accomplish this? As simple as possible please :)

• you subtract the maximum byte 3 can be from the total, and from that subtract the maximum byte 2 can be to get byte 3. byte 4 is just max byte 4 minus number minus max byte 3 +1. Dec 13, 2018 at 17:27

You can achieve what you want by using bitshifting and bit-wise and operators.

Here is an example that lets you extract the individual bytes of your `long` variable. I think it should be straigtforward to extend it to variables of different length:

``````void loop() {
long a=0x12345678, c=0;
byte b;
Serial.println("Original:");
Serial.println(a,HEX);
delay(1000);
Serial.println("Individual bytes:");
for (int i=0; i<4; i++)
{
b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable
Serial.println(b[i],HEX);
delay(1000);
}

for (int i=0; i<4; i++)
{
c+=b[i]<<(i*8);
}
Serial.println("Reconstructed:");
Serial.println(c,HEX);
delay(1000);
}
``````

Depending on what byte ordering (big or little endian) is expected, you might need to reorder the bytes before sending or after receiving.

• Very straightforward and easy to understand the principle so thankyou, however under "reconstructed" it only prints 5678? Dec 14, 2018 at 8:00
• Did you copy the code snippet from my answer? Because if I run the code on my nodemcu I get the right answer. Dec 14, 2018 at 8:20
• Yes, i copied and pasted the code, added void setup(); and Serial.begin(9600); to get the code to run on my arduino nano Dec 14, 2018 at 13:57
• by default on an 8 bit AVR, to the right hand side of the equals defaults to int arithmetic which is signed sixteen bit. So i cast the array to a uint32_t in the loop. Unsure of if that is the most efficient way, but it works! Thankyou for your help Dec 14, 2018 at 19:40
• yes right. I didn't think about the arduino controller, when I tried on the nodemcu. Dec 14, 2018 at 19:49

The `union` type is similar to a `struct` except that each of the members of the element occupy the same memory. If you define a `struct` so that it has 2 members -- one 4-byte type and one 4-element array of a single byte type, then you can easily refer to the same data as a whole 4-byte element, or byte-wise as you desire.

``````union packed_long {
long l;
byte b;
};
``````

This is the type, so you have to declare the variable to be of that type:

``````packed_long mydata;
``````

Now, you have two sub-elements of `mydata`: `l` and `b[]`.

To save your `long` value, write to the `l` part:

``````mydata.l = myaccel.getY();
``````

To access each of the 4 bytes:

``````byte1 = mydata.b;
byte2 = mydata.b;
byte3 = mydata.b;
byte4 = mydata.b;
``````

On the receiving end, you take each of the 4 bytes:

``````mydata.b = canbus.read();
``````

As long as you receive the bytes in the same order in which you sent them, you can now access your `long` value in `mydata.l`.

The actual size of different types is dependent on the compiler and architecture, so you may also wish to define your value as a definite-sized variable to ensure you are always working with 32 bits: `int32_t` (signed 32-bit integer) or `uint32_t` (unsigned 32-bit integer).

A way to send a long is to mask off and send the LSB byte (CAN standard), then shift the next one into LSB position, for 4 bytes:

``````uint32_t data;

// Send to CAN bus LSB-first
// This method is destructive; data should be a temp if the
// Arduino is to retain the data after sending it.
for( uint8_t b = 4; b > 0; --b ){
sendByte(data & 0xFF);  // send curr byte
data >>= 8;             // shift that byte away
}