Go Down

### Topic: Convert byte array to uint32_t (Read 7933 times)previous topic - next topic

#### jphs

##### Aug 19, 2012, 09:01 pm
Hello,

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

Thanks

#### AWOL

#1
##### Aug 19, 2012, 09:18 pm
Little or big-endian?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

#### Tom Carpenter

#2
##### Aug 19, 2012, 09:23 pmLast Edit: Aug 19, 2012, 09:26 pm by Tom Carpenter Reason: 1
Sounds like a job for a union.

Code: [Select]
`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):
Code: [Select]
`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(){}`
~Tom~

#### jphs

#3
##### Aug 19, 2012, 09:49 pm

@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 http://code.google.com/p/xbee-arduino/). An example of a XBee address: sh=13A200 sl=40214AC5.

Thanks once again

#### drone

#4
##### Aug 19, 2012, 10:36 pm
Use the 'left shift' operator:

Code: [Select]
`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.

#### Tom Carpenter

#5
##### Aug 19, 2012, 10:46 pmLast Edit: Aug 19, 2012, 10:51 pm by Tom Carpenter Reason: 1
drone, the union achieves the same, but with a much smaller Ram and program memory footprint - unions are ace!

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?

Code: [Select]
`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~

#### jphs

#6
##### Aug 20, 2012, 01:53 amLast Edit: Aug 20, 2012, 01:54 am by jphs Reason: 1
@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

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

Code: [Select]
`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

#### Tom Carpenter

#7
##### Aug 20, 2012, 02:02 am
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:
Code: [Select]
`  for(int i=0; i < sizeof(inputStream); i++){    converter.array[sizeof(inputStream) - i - 1]=inputStream[i]; //reverse the byte order here.  }`
~Tom~

#### GoForSmoke

#8
##### Aug 20, 2012, 04:28 am
OP, are you trying to convert ascii text to a numeric value?