Converting Int's to Big Endian

Hope somone can help here.
I am reading serial data such as "42A60000" the data is in Big Endian and need to convert to decimal.

Code:
unsigned long sResult;
while (Serial.available() >0)
{
for(int i=0; i < 3; i++) {
sResult = Serial.read();
sResult =+ sResult;
} // checking the value here = "42A600"
// if i set sResult = 0x42A60000; it works perfectly.
sResult = ((float)&sResult);
}

What am i doing wrong here?

sResult = Serial.read();
sResult =+ sResult;

Whatever you try to do, this is garbage. If you want to multiply sResult by 2, the operator is +=, not =+. Also, in ever iteration of the loop you destroy any trace of what you read in previous iterations. The final sResult depends only on the last byte red.

Korman

Korman,

You are correct, my post was a result of a late night post, and typing free hand. Sorry for the mistakes in the example code.

Any suggestions on a better approach, or corrections to make this would be great.

Code:
unsigned long sResult;
while (Serial.available() >0)
{
for(int i=0; i < 4; i++) {
inbyte = Serial.read();
sResult += inbyte;
}
// sResult here = "42A600"
sResult = ((float)&sResult);
// sResult here = 0
}

while (Serial.available() >0) 
{
 for(int i=0; i < 4; i++) {

This isn't going to work.
1 is > 0, so what happens after one iteration of this loop?

I only posted part of the code.
I have conditioning that check to make sure the proper string is being received. I pick out all of the values i need.

The serial data I need is received as "42A60000"
With the provided example, my sResult = 42A600

sResult = ((float)&sResult); // returns a value of 0

If i manually set sResult = 0x42A60000; then it works perfectly.
Not sure what i need to change to get it to work properly.

I only posted part of the code

Well, thanks for wasting my time.

What you write is all very confusing and I can't really make sense out of your code. The only thing I'm certain is that your code won't do anything useful.

I assume you're getting some 4 byte floating point values over the serial connection and want them converted back to float to check them. If you want to do something else, please be more clearer next time.

This isn't necessarily easy to understand but it should work:

float resfloat;
for (int i = 0; i < sizeof(float); i++) {
    ((unsigned char *) &resfloat)[i] = Serial.read();
}
if (resfloat > 12.34) ...

If you want to reverse the order of the bytes use:

float resfloat;
for (int i = sizeof(float) - 1; i >= 0 ; i--) {
    ((unsigned char *) &resfloat)[i] = Serial.read();
}
if (resfloat > 12.34) ...

What that thing does in all its ugliness is to treat the float as a character buffer and writes byte by byte into it. If you mess up with your buffer arithmetic, you mess up your memory and strange things start to happen - none of them good.

Korman

sResult += inbyte,

Nope, can't see that working.
There's no way you can receive four bytes and sum them to make a six hex digit value.
That's simple arithmetic.

Guys,
I am new to the Arduino and I am trying to learn.
I am not trying to waste anyones time, just trying to solve this problem.

I need to receive a serial string from equipment and decode the results into decimal. The data i need to decode is in Big Endian. I am trying to find the most efficient way to parse the string, and obtain the data.
Programming is not my best strength. I have been making attempts to retrieve the serial string and pull the values only to be told I'm dumb. I agree, I am dumb and why i am asking for help from all of you so that I can learn something new.

Here is the format, here is a capture of the data I receive.
"042220207020051001222020702020100242A6000010037683"
Data needing converted starts here ^ after instance of "1002" and ends before instance of "1003"
The data always starts with "04"
The values are in HEX, such as 04,22, 20, 20, 70

The only way i know to grab the information is pulling in the Serial.read() into an integer. I do not know how to work with the unsigned long to process the data "42A60000". When reading the serial data the "00" is only a single "0" and i end up with "42A600" which doesn't help me.

I do appreciate any help, i am sorry i do not know how to ask the question in a less confusing manner.

Ok, please again and in more detail. Those 4 bytes, what are they? Are they 4 values from 0-255 you want to add together, are they an integer, are they an float?

If you read the character sequence "04,22, 20, 20, 70", what will be the value you want to have in your variable when decoded correctly?

As long as this isn't perfectly clear and you don't tell us, you're just messing around blindly without any chance of success.

Korman

Someone with a virtually identical problem here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1284150516/7#7

What was it someone said about time-wasting?

Korman,

"042220207020051001222020702020100242A6000010037683"
The data i need is here in the string 42A60000
This data is in IEEE-754 32-bit float representation, with the MSB received first (Big Endian)
In this example the "42A60000" = 83 decimal.

The problem i am having is being able to read the serial string, and have the value convert properly.

The problem you are having is understanding that addition alone will not work.
Example:
0x10+0x00+0x00+0x03 == 0x13, not 0x10000003

You need either a multiply or a shift operation also, as pointed out by Grumpy Mike in the other thread.
If you're not seeing a zero, maybe it is because you aren't sending it in the first place.
I don't know how you think your code posted above works even partially, because it doesn't make sense.
Or maybe you didn't actually post what you wrote.

It looks like he's reading in an ASCII hex dump of the bytes that make up a 32-bit floating point number.

If this is the case, and the IEEE-754 format is the same one that Arduino uses (I'm too lazy to look it up), then he just needs to define a union containing an array of four bytes and a float, read the four bytes, convert them from ASCII to binary, and stuff them into the array in the correct order, and the float will have his number.

-Mike

Mike,

Yes i am reading in an ASCII hex dump that makes up the 32 bit float.
Any details on how to do as you are suggesting?

Looking into the Union, I found this example.
I understand I need to re-work my serial routine to grab the bytes I need for the Union. So after obtaining the value, as in the example, do i still need to do a Ascii to binary conversion, or can i simply set sResult with the pointer to value? like this ? >> sResult = ((float)&value);

// Example code.
union u_tag {
byte b[4];
float ival;
} u;

float value;

void setup()
{
Serial.begin(9600);
}

void loop()
{

if(Serial.available() > 3)
{

//read the 4 bytes into the union
u.b[0] = Serial.read();
u.b[1] = Serial.read();
u.b[2] = Serial.read();
u.b[3] = Serial.read();

//retrieve the float value of the union
//(based on the bytes passed in)
value = u.ival;

The union example you've posted doesn't do any ASCII conversion - you need to do that before you assign to the union's byte array, converting each ASCII hex digit to binary and shifting to the the appropriate place in the byte.

First off, it's not Big Endian. If you're unsure about something, please don't put it in your post. It was very confusing and made the problem very difficult to solve efficiently (since we'd have needed to reverse the bit ordering). Traditional convention is that the MSB is on the left side - this is different from arrays which are viewed as least significant to most significant.

Anyhow, the solution is as follows:

The main loop:

void loop()
{
  if(Serial.available())
  {
    delay(10);               //Short wait to ensure complete data transfer
    float num = getData();   //Call on function to decode HEX into Decimal
    Serial.println(num);     //Print to Serial to verify
  }
}

The "getData() function:

float getData()
{
  long longData = 0;                  //Start with long data type which allows bit operations
  for(int i = 0; i < 8; i++)          //Long and float are 32 bits, each read returns 4 data bits therefore 8 reads
  {
    byte temp = Serial.read();        //Store the DEC value of the ASCII character
    if(temp <= '9')                   //Convert char to HEX from ['0'(48) - '9'] to [0 - 9]
      temp -= 48;
    else
      temp -= 55;                     //Converts chat to HEX from ['A' to 'F'] to [10 - 15]
    longData <<= 4;                   //Bit shifts the long left by 4
    longData |= temp;                 //Appends the new HEX
  }
  return *(float*) &longData;         //Change interpretation of bits from long to float
}

It's not the most elegant solution as I was unsure how to convert a char to hex since the atoi function only works with numbers.

I inputted "42A60000" and got the proper value (83.00) back. I did not include code to determine when to start reading the data as one of the links posted already explained that. Good luck!

EDIT: Just saw the other posters' suggestion of unions. If you were to do that, then you wouldn't need the casting in the end. Simply use a long or byte array to build up the float in your U object then return it. Refer to "iVal" whenever you want the float value.

delay(10); //Short wait to ensure complete data transfer

No, no, and for full effect, NO!
Use "Serial.available"

For those who don't carry ASCII tables around with them:

if(temp <= '9')                   //Convert char to HEX from ['0'(48) - '9'] to [0 - 9]
      temp -= '0';
    else
      temp -= 'A' - 10;   // will not cope with lower case

No, no, and for full effect, NO!
Use "Serial.available"

Ooops, sorry, my bad. Delay is an inefficient use of resources (not to mention unsafe...). Serial.available() to ensure that all the bytes are present would be a better solution. However, I was unsure of the size of OP's input stream. It was a sloppy solution to get the coding done... my bad.