Pages: [1]   Go Down
Author Topic: Convert byte array to uint32_t  (Read 1920 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

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

Thanks smiley-wink
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26455
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Little or big-endian?
Logged

"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.

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like a job for a union.

Code:
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:
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(){

}
« Last Edit: August 19, 2012, 02:26:52 pm by Tom Carpenter » Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your replies guys.

@AWOL it's big-endian.

@Tom Carpenter I've tried your code, but it's not working smiley-sad. 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 smiley-wink
Logged

0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Use the 'left shift' operator:

Code:
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.
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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:
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(){

}
« Last Edit: August 19, 2012, 03:51:11 pm by Tom Carpenter » Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@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 smiley-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 smiley-wink

Code:

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
« Last Edit: August 19, 2012, 06:54:42 pm by jphs » Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
  for(int i=0; i < sizeof(inputStream); i++){
    converter.array[sizeof(inputStream) - i - 1]=inputStream[i]; //reverse the byte order here.
  }
Logged

~Tom~

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Pages: [1]   Go Up
Jump to: