Go Down

### Topic: How to convert 4 bytes into a long? (Read 9231 times)previous topic - next topic

#### prairiemystic

##### Sep 01, 2011, 12:28 am
I have a 24-bit A/D and put four 8-bit reads into a byte array:

byte d[4];

d[0]=shiftIn(SPI_MISO,SPI_CLK,MSBFIRST);
d[1]=shiftIn(SPI_MISO,SPI_CLK,MSBFIRST);
d[2]=shiftIn(SPI_MISO,SPI_CLK,MSBFIRST);
d[3]=shiftIn(SPI_MISO,SPI_CLK,MSBFIRST);

adc_value=long(d[]);  // <-- sketch does not compile

So the conversion function "long" does not seem to accept arrays and I wonder how to use it?

#### PaulS

#1
##### Sep 01, 2011, 12:33 am
Quote
So the conversion function "long" does not seem to accept arrays and I wonder how to use it?

You don't, because that is not what it is for.

The long that you want to construct is done by shifting one of the bytes in the array 24 places to the next. Then, the next byte is shifted 16 bits to the left, and added. Then, the next byte is shifted 8 bits to the left, and added. Then, the final byte is added.

Code: [Select]
`long val = 0;val += d[0] << 24;val += d[1] << 16;val += d[2] << 8;val += d[3];`

Depending on how the bytes were sent, the array may need to be used in the other order (3, 2, 1, 0).

#2
Or use a union?

Lefty

#### gardner

#3
##### Sep 01, 2011, 01:39 am
Something like this should so the job.

Code: [Select]
`long adc_value;byte d[4];/* Put the low byte in d[0]. */ d[0]= shiftIn()  // THE LOW BYTE   : d[3] = shiftIn()  // THE HIGH BYTEadc_value = *((long *)d);`

#### prairiemystic

#4
##### Sep 01, 2011, 06:17 pm
I do get interesting results and am still looking for a solution. It looks like the shift operator is only 16 bit. The cast to a long swaps nibbles on some of the bytes, which is strange. Thanks everyone for your help so far.

byte d[4];

d[0]=0x87;
d[1]=0x65;
d[2]=0x43;
d[3]=0x21;

Serial.println(adc_value,HEX); //--> prints 4321 (expected 87654321)

Serial.println(adc_value,HEX); // --> prints 21346587 (expected 21436587)

d[0]=0x12;
d[1]=0x34;
d[2]=0x56;
d[3]=0x78;

Serial.println(adc_value,HEX); //--> prints 5678 (expected 12345678)

Serial.println(adc_value,HEX); // --> prints 78563412 (expected 87654321)

#### PaulS

#5
##### Sep 01, 2011, 06:46 pm
What kind of results do you get if adc_value is unsigned long? Does it make sense for it not to be unsigned long?

#### prairiemystic

#6
##### Sep 01, 2011, 06:54 pm
Yes it should be: unsigned long adc_value; but I get the same results.

#### AWOL

#7
##### Sep 01, 2011, 07:14 pm
What if you cast the bytes to long before shifting?
"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.

#8
##### Sep 01, 2011, 07:23 pm

these operations need to be cast to a long.  Your left operand is of type byte, and your right operand is a const that the compiler defaults to type int, so the operation is performed as a 16 bit operation.  change it to:

Code: [Select]
`  adc_value += (long)d[0] << 24;  adc_value += (long)d[1] << 16;  adc_value += (long)d[2] << 8;  adc_value += (long)d[3];`

And you'll get the expected outcome.

Serial.println(adc_value,HEX); // --> prints 21346587 (expected 21436587)

Serial.println(adc_value,HEX); // --> prints 78563412 (expected 87654321)

The printouts for these are as I would expect them.

#### gardner

#9
##### Sep 01, 2011, 08:25 pm

I do get interesting results...

Code: [Select]
`  d[0]=0x87;    d[1]=0x65;    d[2]=0x43;    d[3]=0x21;        :   adc_value = *((long *)d);  Serial.println(adc_value,HEX); // --> prints 21346587 (expected 21436587)`

21346587

I do not believe this is possible.  If this is really what you got, there's something wonky about your methodology.

What I get is:  0x21436587 which is the right answer.

#### prairiemystic

#10
##### Sep 03, 2011, 01:50 am
byte d[4];

<.... stuff deleted>

This code works fine now. (Without proper casting to a long, I get swapped nibbles i.e. 21346587)
Thanks to everyone, esp. jraskell for the help.

#### paulfer

#11
##### Jul 29, 2016, 10:31 pm
OH MY WORD! I spent an entire evening searching thru many forum posts. If only I saw this one 1st!

#### septillion

#12
##### Jul 30, 2016, 12:03 am
Just shifting them as you go is way easier...

Code: [Select]
`long adc_value = 0;digitalWrite(ADC_CS,LOW);for(byte i = 0; i < 4; i++){  adc_value =<< 8;  adc_value |= shiftIn(SPI_MISO,SPI_CLK,MSBFIRST);}digitalWrite(ADC_CS,HIGH);`

And if you are already calling it SPI, why not USE the SPI?
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake

#### PaulMurrayCbr

#13
##### Jul 30, 2016, 03:35 amLast Edit: Jul 30, 2016, 03:41 am by PaulMurrayCbr
If you take care to get the order of the bytes correct (not sure about the AVR endianness), then you can cast the array as a pointer to long and dereference it:

Code: [Select]
`adc_value=long(d[]);  // <-- sketch does not compileadc_value = * (long *) d; // try this instead`

An equivalent way to do this is using a union

Code: [Select]
`union foo {  byte as_array[4];  long as_long;}d;  d.as_array[0]=0x87;   d.as_array[1]=0x65;   d.as_array[2]=0x43;   d.as_array[3]=0x21;  Serial.println(d.as_long,HEX); `

If you get weird values, just put in one byte to work out if it goes into element 0 or element 3 of the array.

http://paulmurraycbr.github.io/ArduinoTheOOWay.html

Go Up