Go Down

### Topic: HEX and BIn conversion for unsigned long data type wrong (Closed) (Read 425 times)previous topic - next topic

#### ffokke

##### Sep 24, 2018, 04:56 pmLast Edit: Sep 24, 2018, 08:33 pm by ffokke
For some project I'd like to store boolean parameters into eeprom.
However, I ran into a problem when I got returned a different number than I put in.
After some testing it seems that some conversions are calculated wrong.
In those cases the 1st bit of the second most significant byte is set to 0.
It gets even worse if a variable is used for the most to least significant bytes.
Am I doing something wrong? It ain't a bug?
I can't find anything where this is mentioned.
Nobody would probably use these kind of notations (it's for testing now), but it should work shouldn't it?

Code: [Select]
`// When composing a long data type, in certain cases the 1st bit of the 2nd most significant byte (byte 2) is set to 0// Using a variable for the multiplier even sets all bits of bytes 2 and 3 to 1.unsigned long calculatedvalue=(B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFF * 65536) + (0xFF * 256) + (0xFF);                     //Hex conversion: bit 1 of byte 2 is wrong//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFFFFFF);                                                 //Hex conversion: correct.//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFF * 65536) + (0xFFFF);                                  //Hex conversion: correct.//unsigned long calculatedvalue=(0xFFFF * 65536) + (0xFF * 256) + (0xFF);                                       //Hex conversion: bit 1 of byte 2 is wrong//unsigned long calculatedvalue=(0xFFFF * 65536) + (0xFFFF);                                                    //Hex conversion: correct.//unsigned long calculatedvalue=0xFFFFFFFF;                                                                     //Hex conversion: correct.//unsigned long calculatedvalue=(255 * 16777216) + (255 * 65536) + (255 * 256) + (255);                         //Decimal: bit 1 of byte 2 is wrong//unsigned long calculatedvalue=(255 * 16777216) + (16777215);                                                  //Decimal: correct.//unsigned long calculatedvalue=(255 * 16777216) + (255 * 65536) + (65535);                                     //Decimal: correct.//unsigned long calculatedvalue=(65535 * 65536) + (255 * 256) + (255);                                          //Decimal: bit 1 of byte 2 is wrong//unsigned long calculatedvalue=(65535 * 65536) + (65535);                                                      //Decimal: correct.//unsigned long calculatedvalue=4278190080 + 16711680 + 65280 + 255;                                            //Decimal: correct.unsigned long expectedValue=4294967295;// Testing with multiplier via variable.// Now bytes 2 and 3 are converted to all ones.// It doesn't matter if the value of the multiplier is in Hex of decimal notation.int multiplierB0=0x1;       //Multiplier least significant byteint multiplierB1=0x100;     //Multiplier 2nd least significant byteint multiplierB2=0x10000;   //Multiplier 2nd most significant byteint multiplierB3=0x1000000; //Multiplier most significant byte//unsigned long calculatedvalue=(B10001111 * multiplierB3) + (B10000111 * multiplierB2) + (B10000011 * multiplierB1) + (B10000001);//unsigned long expectedValue=2407957377;void setup() {  Serial.begin(9600);  while (!Serial) {    ;  }  Serial.println("Binairy:\t\tMost to least significant byte -->");  Serial.println("\t\t\t3       2       1       0");  Serial.println("\t\t\t76543210765432107654321076543210");  Serial.print("Expected value :\t");  Serial.println(expectedValue, BIN);  Serial.print("Calculated value :\t");  Serial.println(calculatedvalue, BIN);  Serial.println("");  Serial.println("Hexidecimal:\t\t3 2 1 0");  Serial.print("Expected value :\t");  Serial.println(expectedValue, HEX);  Serial.print("Calculated value :\t");  Serial.println(calculatedvalue, HEX);}void loop() {}`

#### holmes4

#1
##### Sep 24, 2018, 05:11 pm

Quote
Am I doing something wrong? It ain't a bug?
Yes you are doing something wrong and it is a bug in your code!

Mark

#### ffokke

#2
##### Sep 24, 2018, 05:54 pm
Where is the error?

#### PaulS

#3
##### Sep 24, 2018, 07:24 pm
Code: [Select]
`int multiplierB2=0x10000;   //Multiplier 2nd most significant byteint multiplierB3=0x1000000; //Multiplier most significant byte`
Will those values actually fit in an int?

#### Whandall

#4
##### Sep 24, 2018, 07:26 pm

Code: [Select]
`Somewhere\Badhexbin\Badhexbin.ino:6:44: warning: integer overflow in expression [-Woverflow] unsigned long calculatedvalue = (B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong                                            ^Somewhere\Badhexbin\Badhexbin.ino:6:91: warning: integer overflow in expression [-Woverflow] unsigned long calculatedvalue = (B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong                                                                                           ^Somewhere\Badhexbin\Badhexbin.ino:26:20: warning: overflow in implicit constant conversion [-Woverflow] int multiplierB2 = 0x10000; //Multiplier 2nd most significant byte                    ^Somewhere\Badhexbin\Badhexbin.ino:27:20: warning: overflow in implicit constant conversion [-Woverflow] int multiplierB3 = 0x1000000; //Multiplier most significant byte                    ^`
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

#### septillion

#5
##### Sep 24, 2018, 07:36 pm
If you want to store bools in EEPROM why don't you just do that?

Or do you want to pack 8 bools into a single byte? If so do simple bitwise operators or use bitWrite() and bitRead().
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

#### ffokke

#6
##### Sep 24, 2018, 07:48 pm
Code: [Select]
`int multiplierB2=0x10000;   //Multiplier 2nd most significant byteint multiplierB3=0x1000000; //Multiplier most significant byte`
Will those values actually fit in an int?
Code: [Select]
`int multiplierB2=0x10000;   //Multiplier 2nd most significant byteint multiplierB3=0x1000000; //Multiplier most significant byte`
Will those values actually fit in an int?
Right! Of course! Thanks!

#### ffokke

#7
##### Sep 24, 2018, 07:53 pm
I'll do. Didn't know that option.
Thanks a lot for helping this newbie.

#### Whandall

#8
##### Sep 24, 2018, 07:55 pm
I think having warnings disabled as a default is a bad decision of the arduino team.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

#### ffokke

#9
##### Sep 24, 2018, 08:12 pm
If you want to store bools in EEPROM why don't you just do that?

Or do you want to pack 8 bools into a single byte? If so do simple bitwise operators or use bitWrite() and bitRead().
8, 16, 32... don't know yet.
Was just playing around.
16 went ok, but 32 turned out a bit more difficult.
I did find bitshifting and bitWrite etc. Thanks
I may end up using that.

#### PaulRB

#10
##### Sep 24, 2018, 08:30 pm
32 bit should have worked fine. Its 64 bits where bitRead()/bitWrite() don't work. Post your 32 bit code.

#### GolamMostafa

#11
##### Sep 24, 2018, 08:47 pmLast Edit: Sep 25, 2018, 04:46 am by GolamMostafa
32 bit should have worked fine. Its 64 bits where bitRead()/bitWrite() don't work. Post your 32 bit code.
The execution of the following codes does not support your opinion?
Code: [Select]
`void setup() {  Serial.begin(9600);  pinMode(13, OUTPUT);  digitalWrite(13, LOW);  //L is OFF  uint64_t x = 0x8234567812345678;//1000 0010 0011 0100 0101 0110 0111 1000, ..., 1000.  bool n = bitRead(x,63);  Serial.print(n, BIN); //shows 1  bitWrite(PORTB, 5, bitRead(x, 63)); //L is ON}void loop() {}`

#### oqibidipo

#12
##### Sep 25, 2018, 01:21 am
bitRead() works with 64-bit values, but bitSet(), bitClear() and bitWrite() are limited to 32 bits because of that 1UL in the macros:

Code: [Select]
`#define bitRead(value, bit) (((value) >> (bit)) & 0x01)#define bitSet(value, bit) ((value) |= (1UL << (bit)))#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))`

#### GolamMostafa

#13
##### Sep 25, 2018, 07:12 am
bitRead() works with 64-bit values, but bitSet(), bitClear() and bitWrite() are limited to 32 bits because of that 1UL in the macros:

Code: [Select]
`#define bitRead(value, bit) (((value) >> (bit)) & 0x01)#define bitSet(value, bit) ((value) |= (1UL << (bit)))#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))`

Thanks with for the valuable information.

#### septillion

#14
##### Sep 25, 2018, 09:43 am
8, 16, 32... don't know yet.
Was just playing around.
My point was, each EEPROM address can only hold a single byte aka 8-bit. Yeas, with .put() you can place a 16 or 32-bit value in EEPROM but it's then split into 2/4 bytes again. Aka, going beyond 8-bits is a bit pointless. Otherwise you do stuff to pack it and the first thing .put() does is splitting it again.
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