Convert Hex-String like "00008BFC" to double/integer

In my project, my Arduino Micro receives signals from a rotation mount where the position is described by a hex-8 digit string like “00008BFC” which corresponds to 35836 in decimal basis. Only the last 4 digits are used. However, for negative values I get something like “FFFFB9F8”. After literally hours of reading and testing, I couldn’t find a solution to convert this into an integer or other variable type. I hope you can help me. I tried different functions like sscanf but didn’t succeed. My current approach is very basic but still produces errors.

int hex2int(char ch)
{
    if (ch >= '0' && ch <= '9')
        return ch - '0';
    if (ch >= 'A' && ch <= 'F')
        return ch - 'A' + 10;
    if (ch >= 'a' && ch <= 'f')
        return ch - 'a' + 10;
    return -1;
}

double convert(char* position){
  Serial.print("Convert: ");
  Serial.println(position);
  Serial.print("pos[3]*16^4=65536*");
  Serial.print(hex2int(position[3]));
  Serial.print("=");

  double val1=hex2int(position[3])*65536;

  Serial.println(val1);
  Serial.print("pos[4]*16^3=4096*");
  Serial.print(hex2int(position[4]));
  Serial.print("=");

  double val2=hex2int(position[4])*4096;

  Serial.println(val2);
  Serial.print("pos[5]*16^2=256*");
  Serial.print(hex2int(position[5]));
  Serial.print("=");

  double val3=hex2int(position[5])*256;

  Serial.println(val3);
   Serial.print("pos[6]*16^1=16*");
  Serial.print(hex2int(position[6]));
  Serial.print("=");

  double val4=hex2int(position[6])*16;

  Serial.println(val4);
  Serial.print("pos[7]*16^0=1*");
  Serial.print(hex2int(position[7]));
  Serial.print("=");

  double val5=hex2int(position[7]);

  Serial.println(val5);              
  double val = val1+val2+val3+val4+val5;
  Serial.print("Total: ");
  Serial.println(val);
  return val;
}

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

void loop() {
 convert("00008BFC");
 delay(5000);
}

I get the output:

Convert: 00008BFC
pos[3]*16^4=65536*0=0.00
pos[4]*16^3=4096*8=-32768.00
pos[5]*16^2=256*11=2816.00
pos[6]*16^1=16*15=240.00
pos[7]*16^0=1*12=12.00
Total: -29700.00

Can you tell me why I get -32768.00 instead of 524288. I can understand that I run into errors multiplying by something like 16^6, but in this case?!

Do you have a simple solution for me how to convert these strings? There are also negative values like “FFFFB9F8” that I don’t know how to deal with yet. I also need the other direction creating those strings. I would really appreciate your help.

Edit: Typo in the code changed.

Misuse of the XOR operator ^

Joking.

val1=hex2int(position[3])*65536 Sixteen bit ints, don’t forget

get following result

35836

using

void setup (void)
{
    unsigned int val;
    const char*  s = "008bFC";

    sscanf (s, "%x", &val);

    Serial.begin (9600);
    Serial.println (val);
}

// -----------------------------------------------------------------------------
void loop (void)
{
}

I use the standard function strtoul().

void setup() {
  Serial.begin(9600);
  unsigned long x = strtoul("00008BFC", NULL, 16);
  Serial.println(x); //prints 35836
}

void loop() {
}

TheMemberFormerlyKnownAsAWOL:
Sixteen bit ints, don’t forget

Thanks! I somehow thought I am working on 32 bits :slight_smile:
I tried to simplify the function and found another weird thing

  for(int i=3;i<5;i++){
    Serial.println(pow(16,7-i));
   }

returns:

65535.95
4096.00

While the same function with i<4 returns 65536.00. I can also use doubles for all variables with the same result

double convert(char* position){
  double exponent=7;
  double base=16;
  for(double i=3;i<5;i++){
    Serial.println(pow(base,exponent-i));
   }

What’s going on here?

pow() uses floating point math with logarithm and exponential functions. It is best avoided when calculating integer powers.