converting 3 single byte variables into a single variable

This may be a very basic coding question...

How can I go about taking 3 single byte variables, converting them into a single variable, and then converting that back to the original 3 single byte variables?

I have looked at concatenating, converting to text, looked at arrays... but just cannot grasp how to do this...

byte SmVal_1 = 0x25;
byte SmVal_2 = 0xFF;
byte SmVal_3 = 0x63;

long BigValue = SmVal_1;  // BigValue = 0x00000025
BigValue = (BigValue << 8) | SmVal_2; // BigValue = 0x000025FF
BigValue = (BigValue << 8) | SmVal_3; // BigValue = 0x0025FF63

BigValue now contains 0x0025FF63

This is the long written way to do it without casting anything. The other way would be to have the 3 bytes in an array and using a FOR loop, you just loop through them like so.

for(byte i = 0; i < 3; i++)
{
BigValue = (BigValue << 8 ) | myArray[ i ]; // with my array containing those 3 values above.
}

I think I understand what you did. Is it required to first convert my 3 variables to hex... or is there another way to do this while leaving them as base10 numbers?

Also, how would I disassemble this back to the original 3 variables?

I corrected my initial title and question... the assembled variable doesn't necessarily need to be 3 bytes.

My application: I am obtaining 3 temperatures (each with values between 0-255). I am sending them via RF which requires a single write statement with a single variable of known byte length. Then on the other end I need to disassemble it back to the original 3 temperatures.

The easy way, although reviled by purists, is to use a union.

aarg: The easy way, although reviled by purists, is to use a union.

I researched Unions as well. I believe I understand how they are created... but could not understand how to disassemble it back into the original 3 variables once it was sent serially.

byte b1 = 0x25;
byte b2 = 0xFF;
byte b3 = 0x63;

Assemble:

long BigValue = (BigValue + b3 << 16) + (BigValue + b2 << 8) + b1;

Disassemble:
  
b1 = BigValue & 0xFF;
b2 = BigValue >> 8 & 0xFF;
b3 = BigValue >> 16 & 0xFF;

Just math…

byte b1 = 0x25;
byte b2 = 0xFF;
byte b3 = 0x63;

Assemble:

long BigValue = (BigValue + b3) * 0x10000 + (BigValue + b2) * 0x100 + b1;

Disassemble:

b1 = BigValue & 0xFF;
b2 = BigValue / 0x100 & 0xFF;
b3 = BigValue / 0x10000 & 0xFF;

You do

da40flyer: I think I understand what you did. Is it required to first convert my 3 variables to hex... or is there another way to do this while leaving them as base10 numbers?

My application: I am obtaining 3 temperatures (each with values between 0-255). I am sending them via RF which requires a single write statement with a single variable of known byte length. Then on the other end I need to disassemble it back to the original 3 temperatures.

byte a=0x20;

is identical to

byte a=32;

32 is the same as 0x20 - just a different way of writing the same thing (not to be confused with "0x20" in quotes, which is a char array/c string)

Can you send an array? That might make the most sense, if the library you're writing to is okay with it.

No need to convert anything, just use Serial.write

Why does it have to be a single variable? Why not just a three-byte array:

byte myBytes[3];

It’s a single variable (albeit, an array), and it uses less storage than a long. You don’t mention needing to manipulate the single variable, so why won’t an array work?

I think he want to send 3 bytes with Serial, hence my previous comment.

The hex values were just an example. If You can use the exact same method and it will work just the same.

To get them back you need to do the reverse.

BigValue = 0x0025FF63;
SmVal_3 = BigValue & 0xFF; //SmVal_3 = 0x63
SmVal_2 = (BigValue >> 8 ) & 0xFF; //SmVal_2 = 0xFF
SmVal_1 = (BigValue >> 16) & 0xFF; //SmVal_1 = 0x25

You can save yourself the work and use aarg’s suggestion and look into how Unions work.
See this example.

// Example program
union myValues
{
  char SmallVal[3];
  long BigVal; // 00, SmallVal[2], SmallVal[1], SmallVal[0] 
} value;

void setup()
{
  Serial.begin(115200);
  value.BigVal = 0; // make sure this is zero first

  value.SmallVal[0] = 'A';
  value.SmallVal[1] = 'B';
  value.SmallVal[2] = 'C';

  Serial.println( value.BigVal, HEX);

  value.BigVal = 4407873;
 
  for (int i = 0; i < 3; i++)
  {
    Serial.println( value.SmallVal[i]);
  }
}

void loop() {}

Thank you all for these suggestions/examples. I will work through each to understand...

econjack: Why does it have to be a single variable? Why not just a three-byte array:

byte myBytes[3];

It's a single variable (albeit, an array), and it uses less storage than a long. You don't mention needing to manipulate the single variable, so why won't an array work?

I am using tmhr20's RF24 Network library. RF24Network::write I am not sure if I can use an array. So far I have been able to send single variables.

HazardsMind: The hex values were just an example. If You can use the exact same method and it will work just the same.

To get them back you need to do the reverse.

BigValue = 0x0025FF63; SmVal_3 = BigValue & 0xFF; //SmVal_3 = 0x63 SmVal_2 = (BigValue >> 8 ) & 0xFF; //SmVal_2 = 0xFF SmVal_1 = (BigValue >> 16) & 0xFF; //SmVal_1 = 0x25

I understand how this works now... and it worked perfectly in my application!

I will work on understanding the Union and see if I can get it to work as well.

You all are awesome! I love learning new things ... Thank you.

Of course you can use an array. They are no different then separate variables but more useful.

And “converting something to hex” does not exist. A variable is a variable, only difference is the way we represent it. Think about is as languages, with one, 1, één, uno, ein, un we alle mean the same thing only in another representation. Same goes for a varaible only we are really used to decimal. But no matter we represent it in decimal, hexadecimal, octal or binary, it’s still the same value. We only need to tell the compiler which it is when we enter it.

197 = 0xC5 (hex, 0x is to tell it’s hex) = 0305 (octal, leading 0 tells it’s octal) = 0b11000101 (0b for binary)

After we assigned it to a variable we can choose how to represent it:

Serial.print(var); //or Serial.print(var, DEC) normal decimal
Serial.print(var, OCT); //octal
Serial.print(var, HEX); //hex
Serial.print(var, BIN); //binary

And can we do stuff like:

var = (0x0F << 4)  && (0b10101010 || 0100);

Not very clear but very valid :smiley: