Convert byte array to uint32_t

Hello,

I'm trying to convert a byte array into uint32_t value. Can anyone give me an help?

Thanks :wink:

Little or big-endian?

Sounds like a job for a union.

union ArrayToInteger {
  byte array[4];
  uint32_t integer;
};

void setup(){
  Serial.begin(115200);
  
  ArrayToInteger converter; //Create a converter

  converter.array[0] = 1 ; //save something to each byte in the array
  converter.array[1] = 1 ; //save something to each byte in the array
  converter.array[2] = 1 ; //save something to each byte in the array
  converter.array[3] = 1 ; //save something to each byte in the array

  Serial.println(converter.integer); //Read the 32bit integer value.  
}

void loop(){

}

This would convert the array {1,1,1,1} into the long integer 16843009.

Basically the union defines a type which is made up in this case of a uint32_t member called 'integer' and a member which is an array of four bytes. The clever thing about unions is, both these two variables share the same memory space, which means no conversion is necessary - if you change one, the other changes to match.

Interestingly, you can also use array constructors with this (same code as before, but simplified):

union ArrayToInteger {
  byte array[4];
  uint32_t integer;
};

void setup(){
  Serial.begin(115200);
  
  ArrayToInteger converter = {1,1,1,1}; //Create a converter
  Serial.println(converter.integer); //Read the 32bit integer value.  
}

void loop(){

}

Thanks for your replies guys.

@AWOL it's big-endian.

@Tom Carpenter I've tried your code, but it's not working :(. I have "letters" in my byte array.

I'll explain what I'm trying to do so you can understand better.

I'm trying to make a connection between an Android device and an Arduino (with a XBee attached) and then a connection between that Arduino and another Arduino (with another XBee attached).
The Android device sends the data in bytes and the Arduino stores that data in a byte array. Sometimes I need to retrieve the address of a XBee to send a message to it. The XBee address it's in uint32_t (I'm using the XBee library from here GitHub - andrewrapp/xbee-arduino: Arduino library for communicating with XBee radios in API mode). An example of a XBee address: sh=13A200 sl=40214AC5.

Thanks once again :wink:

Use the 'left shift' operator:

byte[4] x = {...};
uint32_t foo;

...

foo = (uint32_t) x[0] << 24;
foo |=  (uint32_t) x[1] << 16;
foo |= (uint32_t) x[2] << 8;
foo |= (uint32_t) x[3];

There are other ways to skin the cat, you can use addition instead of the 'or' operator, etc.

drone, the union achieves the same, but with a much smaller Ram and program memory footprint - unions are ace! :smiley:

Those numbers are just the hexadecimal equivalent. You don't need them to have the letters as really everything is stored inside the atmega chip as binary anyway.

I presume you are trying to convert it into an XBeeAddress64 class instance?

union ArrayToInteger {
  byte array[4];
  uint32_t integer;
};

void setup(){
  Serial.begin(115200);
  
  ArrayToInteger sh; //Create a converter. 4 bytes of the high address
  ArrayToInteger sl; //Create a converter. 4 bytes of the low address

  ...
  //Set the 4 bytes...
  sh.array[0] = ...; //high
  sh.array[1] = ...;
  ...
  sl.array[0] = ...;//low
  sl.array[1] = ...;
  ...

  XBeeAddress64 address(sh.integer,sl.integer); //create the address.
  Serial.println(address.getMsb(),HEX); //Print it to the serial monitor.
  Serial.println(address.getLsb(),HEX); //Print it to the serial monitor.
}

void loop(){

}

@Tom Carpenter

Oh my god, I was being so stupid lol. I forgot that every "pair" was a byte. I was doing every single "character" as a byte. Example: 00 13 A2 00, every pair is a byte and I was doing 0 0 1 3 A 2 0 0 as a single byte. I feel so ashamed.

Yes, you presume it right :wink:

But now I'm having a problem with my code. It's switching the order of 0x13 and 0xA2. I'll paste my code (for now I'm just simulating)

Tom you are being a big help, thank you so much :wink:

byte inputStream[]={0x00 ,0x13, 0xA2, 0x00};

uint32_t expectedValue=0x0013A200;


union ArrayToInteger {
  uint32_t integer;
  byte array[4];
};

void setup(){
  Serial.begin(115200);
}
   
   
void loop(){
  
  ArrayToInteger converter; //Create a converter
  
  
  for(int i=0; i < sizeof(inputStream); i++){
    converter.array[i]=inputStream[i];
  }
  
  
  Serial.println();
  Serial.print("UNION RESULT: ");
  
  Serial.println(converter.integer, HEX);
  
  Serial.print("EXPECTED VALUE: ");
  Serial.println(expectedValue, HEX);
  Serial.println();
  Serial.print("Is it the same? ");
  Serial.println(converter.integer==expectedValue);

  
  while(true){
  }
}

Edit:
Of course I can switch the order manually, but I want to know if I'm doing something wrong

Yeah, it will do, should have mentioned that. gcc uses Little Endian, which means the byte 0 in the array is the least significant (i.e. the right most byte in the integer).

In fact it is not just the 0x13 and 0xA2 that are being switched, but the two 0x00's as well.

All you need to do is reverse the byte order to convert from big to little endian. This should do it:

  for(int i=0; i < sizeof(inputStream); i++){
    converter.array[sizeof(inputStream) - i - 1]=inputStream[i]; //reverse the byte order here.
  }

OP, are you trying to convert ascii text to a numeric value?

Thank you Tom, it's working great and you were a great help, thank you so much :wink: