Data type troubles

I'm trying to put four bytes together to an unsigned long like this:

unsigned long param = mBytes[3];
param += mBytes[2]*256;
param += mBytes[1]*256*256;
param += mBytes[0]*256*256*256;

This did not give me the expected result. So I tried the following as an example:

char buf[12];
unsigned long param = 2*256*256 + 203*256 + 102;
sprintf(buf, "%lu", param); 
Serial.write(buf);

I was expecting to see "183142" in the console. Instead I got "4294953830".
So something is definately wrong here - either with the creation of the unsigned long and/or with my conversion to a string.

Sign extension due to "int" arithmetic.

I'm not sure what you mean?

203 × 256 is a negative number in sixteen bit "int" arithmetic.

It doesn't matter that the left hand side of the expression is being assigned to an unsignedlong. The arithmetic on the right hand side is going to be accomplished using 16 bits. 256*256 is going to be too big and will roll over to a negative value.

Try this:

unsigned long param = 2*256UL*256 + 203*256 + 102;

and this:

unsigned long param = mBytes[3];
param += mBytes[2]*256UL;
param += mBytes[1]*256UL*256;
param += mBytes[0]*256UL*256*256;

You didn't provide all of your code so I cannot provide an entirely correct answer. I may have one too many UL in the above, but it will only cost a little time.

You are better off shifting your bytes to the correct position, than trying to do those multiplications.

The compiler is pretty good at doing that particular optimization for you.

Try this:

Serial.println (mBytes[0], HEX); // leading 0 may get dropped, do not panic!
Serial.println (mBytes[1], HEX);
Serial.println (mBytes[2], HEX);
Serial.println (mBytes[3], HEX);

unsigned long param =  (mBytes[0]<<24) + (mBytes[1]<<16) + (mBytes[2]<<8) + mbytes[3];
Serial.println (param, HEX);

What is the type of "mBytes"?

I checked my sketchbook of examples and found one that I had written a while ago. This example shows using both pointers and unions to access the individual bytes of a multi-byte datatype. The example uses unsigned int, but it can easily be extended to unsigned long.

/*
 * Test of using a pointer array to directly access different bytes of a multi-byte datatype.
 * Also concurrently show using a union to do the same thing.
 */

void setup()
{
  Serial.begin(115200); // Change this to whatever your like running your Serial Monitor at.
  while (!Serial) { // Wait for serial port to connect. Needed for Leonardo only.
  }
  delay(1000); // Simply to allow time for the ERW versions of the IDE time to automagically open the Serial Monitor. 1 second chosen arbitrarily.
  // put your setup code here, to run once:
  Serial.println(F("Test of using a pointer array and a union to directly access different bytes of a multi-byte datatype."));
  Serial.println();
  Serial.println();

  // Here is the union. Remember that each part of the union access the same memory location.
  // See http://www.cplusplus.com/doc/tutorial/other_data_types/ for reference.
  union optional_name
  {
    byte ub[2];
    unsigned int ui;
    // } integerUnion; // If only one variable uses this union, one can skip the optional name and simply define the variable here as part of the union declaration.
  };
  union optional_name integerUnion; // Or define one or more variables after the union is declared.

  unsigned int integerValue = 0xD5AA; // Both bytes have MSb == 1 to trap accidental sign issues.
  integerUnion.ui = integerValue;

  Serial.print(F("0x")); // using the F() macro is just a habit I've gotten into to not waste valuable SRAM with diagnostic character strings...
  Serial.print(integerValue,HEX); // the HEX keyword converts to the ASCII representation of the hex value
  Serial.println(F(" == the starting integer value in Hex."));

  // Here is the magic for the array of pointers to access the individual bytes of integerValue
  byte* integerPointer; // Setup the pointer variable. Datatype "byte*" means it is a pointer datatype pointing to the location of a "byte" sized variable
  integerPointer = (byte*)&integerValue; // make the value of the pointer the address of the first byte of our integer

  Serial.print(F("0x"));
  Serial.print(integerPointer[0],HEX);
  Serial.println(F(" == the first byte of the integer value in Hex."));

  Serial.print(F("0x"));
  Serial.print(integerPointer[1],HEX);
  Serial.println(F(" == the second byte of the integer value in Hex."));

  Serial.print(F("0x"));
  Serial.print(integerUnion.ub[0],HEX);
  Serial.println(F(" == the first byte of the integer union in Hex."));

  Serial.print(F("0x"));
  Serial.print(integerUnion.ub[1],HEX);
  Serial.println(F(" == the second byte of the integer union in Hex."));


  Serial.println();
  Serial.println(F("Lets change the integer value to 0x4546 using the pointers and the union."));

  integerPointer[0] = 0x46; // Watch this. This order is correct for "little-endian" architectures where the right-most byte is stored first
  integerPointer[1] = 0x45; // See http://en.wikipedia.org/wiki/Endianness for big vs little endian

  integerUnion.ub[0] = integerPointer[0]; // Make the same changes to integerUnion.
  integerUnion.ub[1] = integerPointer[1];

  Serial.print(F("0x"));
  Serial.print(integerValue,HEX);
  Serial.println(F(" == the final integer value in Hex."));

  Serial.print(F("0x"));
  Serial.print(integerUnion.ui,HEX);
  Serial.println(F(" == the final integer union in Hex."));

}

void loop()
{
  // put your main code here, to run repeatedly:

}

Personally, I'd probably use the union method but that is because it logically makes more sense to me as well as me not being as familiar with using pointers.

Enjoy.

They are defined like this:

byte mBytes[4];

I tried bit shifting like suggested here:

unsigned long param =  (mBytes[0]<<24) + (mBytes[1]<<16) + (mBytes[2]<<8) + mBytes[3];

or this:

unsigned long param = 0;
param += mBytes[3];
param += mBytes[2] <<  8;
param += mBytes[1] << 16;
param += mBytes[0] << 24;

But still the INT-Arithmetic seems to kick in. Everything > INT MAX results in wrong numbers...

But still the INT-Arithmetic seems to kick in.

So, tell the compiler that's not what you want.
Either cast the operands to unsigned, or add the "UL" suffix to the constants.