I'm sure i'm missing something obvious here , but cant find it...
Ive a sketch here, where I convert a an unsigned long into a 4 byte array and then try and turn it back to a long, But as you can see from the output, the re-assembly of the variable doesn't work . I have tried two routes as shown.
thx.
( Arduino UNO. IDE 1.8) -i know i got hex/dec the wrong way on the end print
unsigned long VolFlow = 123456789;
unsigned long MassFlow;// do this one later!
void setup()
{
Serial.begin(9600);
delay(200);
Serial.print(" Check Volume flow = ");
Serial.print(VolFlow, DEC);
Serial.print(" and in HEX... ");
Serial.println(VolFlow, HEX);
Serial.println("!!");
//convert each to 4 byte sized VolFlow numbers)
byte Voldata[4];
Voldata[0] = (VolFlow);
Voldata[1] = (VolFlow >> 8);
Voldata[2] = (VolFlow >> 16);
Voldata[3] = (VolFlow >> 24);
Serial.println("");
Serial.println(" These Vol flow bytes are, starting at Voldata[0] = ");
Serial.println(Voldata[0], HEX);
Serial.println(Voldata[1], HEX);
Serial.println(Voldata[2], HEX);
Serial.println(Voldata[3], HEX);
Serial.println("");
//check its worked ! (it doesn't :( )
unsigned long VolFlow2 = ((Voldata[3] << 24) | (Voldata[2] << 16) | (Voldata[1] << 8) | Voldata[0]);
Serial.print("Vol flow recovered = ");
Serial.print(VolFlow2, HEX);
Serial.print(" and in HEX... ");
Serial.println(VolFlow2, DEC);
// and try other way around:
byte AltVoldata[4];// try another way
AltVoldata[0] = (VolFlow >> 24);
AltVoldata[1] = (VolFlow >> 16);
AltVoldata[2] = (VolFlow >> 8);
AltVoldata[3] = (VolFlow);
Serial.println(""); Serial.println("");
Serial.println(" These AltVol flow bytes are , starting at AltVoldata[0]= ");
Serial.println(AltVoldata[0], HEX);
Serial.println(AltVoldata[1], HEX);
Serial.println(AltVoldata[2], HEX);
Serial.println(AltVoldata[3], HEX);
Serial.println("");
//check its worked ! (it doesn't :( )
unsigned long VolFlow3 = (unsigned long)((AltVoldata[0] << 24) | (unsigned long)(AltVoldata[1] << 16) | (unsigned long)(AltVoldata[2] << 8) | (unsigned long)AltVoldata[3]);
Serial.print("AltVol flow recovered = ");
Serial.print(VolFlow3, HEX);
Serial.print(" and in HEX... ");
Serial.println(VolFlow3, DEC);
}
void loop()
{
}
and the output is:
Check Volume flow = 123456789 and in HEX... 75BCD15
!!
These Vol flow bytes are, starting at Voldata[0] =
15
CD
5B
7
Vol flow recovered = FFFFCD15 and in HEX... 4294954261
These AltVol flow bytes are , starting at AltVoldata[0]=
7
5B
CD
15
AltVol flow recovered = FFFFCD15 and in HEX... 4294954261
On a Arduino Uno ? Then the compiler promotes the byte to integer when shifting, so the first two will work. There might be a difference when the compiler can do it with a constant or when you do this runtime.
I see code that shifts a byte more that 8 position a lot
VolFlow is an unsigned long, when you shift its content right it remains an unsigned long. So you are trying to stuff 32 bits into 8 and the specification says you'll get the least significant byte in that case
β that's what you wanted
details = the C++ specification is clear on what happens when you try to stuff a wider integral type into a narrower intergral type. it's described in Implicit conversions - cppreference.com under Integral conversions
Check Volume flow = 123456789 and in HEX... 75BCD15
!!
These Vol flow bytes are, starting at Voldata[0] =
15
CD
5B
7
Vol flow recovered = 75BCD15 and in HEX... 123456789
These AltVol flow bytes are , starting at AltVoldata[0]=
7
5B
CD
15
AltVol flow recovered = 75BCD15 and in HEX... 123456789
// Extract/manipulate bytes from 32-bit variable with a pointer
// https://forum.arduino.cc/index.php?topic=630682.msg4279573#msg4279573
// This approach can replace the use of a union to accomplish the same thing.
unsigned long bigVar = 0x55cc33aa; // 4 bytes in RAM interpreted as an unsigned long
// Take the address of bigVar and cast it to a byte pointer which can
// point to any byte in RAM as a byte regardless of how it was declared
byte *bp = (byte *)(&bigVar);
// *bp is now the low order byte of bigVar
// *bp+1 is the next byte
// *bp+2 is the next
// *bp+3 is high order byte of bigVar
// Do the same thing except cast to an unsigned pointer
// Take the address of bigVar and cast it to a word pointer which can
// point to any word in RAM as a word regardless of how it was declared
uint16_t *wp = (uint16_t *)(&bigVar);
// *wp is now the low order word of bigVar
// *wp+1 is the high order byte // verify this next byte
// xxx *bp+2 is the next
// xxx *bp+3 is high order byte of bigVar
void setup() {
Serial.begin(115200);
Serial.flush();
Serial.print("\n bigVar - \t");
Serial.println(bigVar, HEX);
Serial.println("\n*bp+i\tbp[i]\twhich byte\taddress");
for (byte i = 0; i < sizeof(bigVar); i++) {
Serial.print(*(bp + i), HEX); // Display contents of the pointed address within bigVar
Serial.print("\t");
Serial.print(bp[i], HEX); // Same result using array notation
Serial.print("\t");
Serial.print((int) ((bp + i) - bp), HEX); // subtraction of pointers
Serial.print("\t\t");
Serial.println((int)( bp + i ), HEX); // Show physical memory location of byte
}
*bp = 0x66; // Modify the low order byte of bigVar
Serial.print("\nmodified bigVar ");
Serial.println(bigVar, HEX);
bp[3] = 0x80; // Modify high byte of bigVar
Serial.print("modified again\t");
Serial.println(bigVar, HEX);
Serial.println("-----------------\nbigVar's bytes in reverse order");
// print bigVar's bytes in reverse order
Serial.println("\n*bp+i\tbp[i]\twhich byte\taddress");
for (char i = sizeof(bigVar) - 1; i >= 0 ; --i) {
Serial.print(*(bp + i), HEX); // Display contents of the pointed address within bigVar
Serial.print("\t");
Serial.print(bp[i], HEX); // Same result using array notation
Serial.print("\t");
Serial.print((int) ((bp + i) - bp), HEX); // subtraction of pointers
Serial.print("\t\t");
Serial.println((int)( bp + i ), HEX); // Show physical memory location of byte
}
Serial.println("\n-------- 16-bit operations ------");
// -------- word pointer --------
Serial.print("\n bigVar - \t");
Serial.println(bigVar, HEX);
Serial.println("\n*bp+i\tbp[i]\twhich byte\taddress");
for (byte i = 0; i < sizeof(bigVar) / 2; i++) {
Serial.print(*(wp + i), HEX); // Display contents of the pointed address within bigVar
Serial.print("\t");
Serial.print(wp[i], HEX); // Same result using array notation
Serial.print("\t");
Serial.print((int) ((wp + i) - wp), HEX); // subtraction of pointers
Serial.print("\t\t");
Serial.println((int)( wp + i ), HEX); // Show physical memory location of byte
}
*wp = 0x9900; // Modify the low order word of bigVar
Serial.print("\nlow word modified ");
Serial.println(bigVar, HEX);
wp[1] = 0x1144; // Modify high byte of bigVar
Serial.print("hi word modified ");
Serial.println(bigVar, HEX);
}
void loop() {
}