String to byte (ex. String b = "0xc7"; to byte b = 0xc7;)

I am trying to convert strings that are formatted like this String byte1 = "0xc7"; to bytes so that I can use serial write to send them to a gas sensor I am using as a project for the calibration process. I've been searching the web and have been unable to come across a solution that works for me.

Any help would be much appreciated!

//Convert user inputted calibration offset to IEEE 754
  String hexOffset = decimalToFloatingHex(offset);  //returns a string like "42c70000"
  String byte1 = "0x" + hexOffset.substring(hexOffset.length() - 2, hexOffset.length());
  String byte2 = "0x" + hexOffset.substring(hexOffset.length() - 4, hexOffset.length() - 2);
  String byte3 = "0x" + hexOffset.substring(hexOffset.length() - 6, hexOffset.length() - 4);
  String byte4 = "0x" + hexOffset.substring(hexOffset.length() - 8, hexOffset.length() - 6);

  
  byte spanMethane2[13] = {0x10, 0x1A, 0x06, byte1, byte2, byte3, byte4, 0x01, 0x00, 0x10, 0x1F, 0x01, 0x69};
  Serial1.write(spanMethane2, sizeof(spanMethane2)); //Sends the readCommand array to the sensor.

Just don't store them as 0xc7 and just don't store them in a String :slight_smile:

Where are the variables coming from?

Thanks for the quick reply! :slight_smile: I'm converting a float value to IEEE-754 Floating-Point using the code below. Not returning them as a string may be a viable option, I'll play around with it a bit!

String decimalToFloatingHex(float decimalNumber) {
  int signBit;
  String mantissa;
  String floatingPointNumber;
  int integerLength;
  int fractionLength;

  //determine the length of integer and fraction parts
  if (decimalNumber < 4) {
    integerLength = 2;
  }

  if (decimalNumber >= 4 && decimalNumber < 8) {
    integerLength = 3;
  }

  if (decimalNumber >= 8 && decimalNumber < 16) {
    integerLength = 4;
  }
  if (decimalNumber >= 16 && decimalNumber < 32) {
    integerLength = 5;
  }
  if (decimalNumber >= 32 && decimalNumber < 64) {
    integerLength = 6;
  }
  if (decimalNumber >= 64 && decimalNumber < 128) {
    integerLength = 7;
  }
  if (decimalNumber >= 128 && decimalNumber < 256) {
    integerLength = 8;
  }

  fractionLength = 23 - integerLength;

  //Find the sign bit (1 bit)
  if (decimalNumber < 0 ) {
    signBit = 1;
    decimalNumber = decimalNumber * -1;
  } else {
    signBit = 0;
  }

  //Calculate the mantisse (23 bits)
  //Extract integer and fractional parts
  int integerPart = (int) decimalNumber;
  double fractionPart = (decimalNumber - integerPart);
  Serial.print("Integer Part: ");    Serial.println(integerPart);
  Serial.print("Fraction Part: ");    Serial.println(fractionPart);

  //Convert the integer part of the decimal number to binary
  String integerBin = decimalToBinary(integerPart, integerLength, fractionLength);
  Serial.print("Integer Binary: ");    Serial.println(integerBin);

  //Convert the fraction part of the decimal number using specified method
  String fractionBin = decimalToBinary(fractionPart, integerLength, fractionLength);
  Serial.print("Fraction Binary: ");    Serial.println(fractionBin);

  //Add required zeros so that mantisse bit size = 23
  mantissa =  integerBin + fractionBin;
  Serial.print("Index of 1st 1: ");   Serial.println(mantissa.indexOf('1'));
  mantissa = mantissa.substring(mantissa.indexOf('1') + 1, mantissa.length());
  while (mantissa.length() < 23) {
    mantissa += 0;
  }
  Serial.print("Mantissa: ");   Serial.println(mantissa);

  //Calculate exponent (8 bits)
  int exponent;
  if (integerBin.length() > 1) {
    exponent = integerBin.length() - 1;
  } else {
    exponent = 1;
  }

  exponent = exponent + 127;
  String exponentBin = decimalToBinary(exponent, 8, 8);
  Serial.print("Exponent Binary: ");    Serial.println(exponentBin);

  //Make sure total bits = 32
  floatingPointNumber = signBit + exponentBin + mantissa;

  if (floatingPointNumber.length() == 32) {
    Serial.print("Floating Point Number (bin): ");  Serial.println(floatingPointNumber);

    Serial.print("Floating Point Number (HEX): ");  Serial.println(floatingPointNumber);
  } else {
    Serial.println("Error: Result < 32 bits");
  }

  //Convert the floating point binary rep to hex
  String hexResult = String(binaryToHex(floatingPointNumber), HEX);

  //Return hex result string
  Serial.print("FINAL RESULT (HEX): ");   Serial.println(hexResult);
  return hexResult;  
}

uint32_t binaryToHex(String bitString) {
  uint32_t result = 0;
  for (unsigned int i = 0; i < bitString.length(); ++i)
  {
    result = result << 1;
    result = result | (bitString[i] & 1);
  }
  return result;
}


String decimalToBinary(float dec, int integerLength, int fractionLength) {      //IMPORTANT: Only feed this function posative numbers less than 255!!

  String binary = "";
  int binSize = 0;
  int bitArray[32];

  if (dec >= 1 || dec == 0) {       //This is for the ints
    int decInt = (int) dec;
    int loopCounter = 0;
    while (decInt != 0 ) {
      if (decInt == 0) {
        binary = "0";

      } else {
        int b = decInt % 2;

        bitArray[binSize] = b;
        decInt = (decInt / 2);
        binSize++;
      }
      loopCounter++;
      if (loopCounter == integerLength) {
        break;
      }
    }
    for (int i = 0; i < binSize; i++) {
      binary += bitArray[(binSize - 1) - i];
    }

  } else {    //This is for fractional numbers
    int loopCounter = 0;
    while (dec != 1) {
      if (dec < 1) {
        bitArray[binSize] = 0;
        dec = dec * 2;
      }

      if (dec > 1)  {
        bitArray[binSize] = 1;
        dec = dec - 1;
      }

      if (dec == 1) {
        bitArray[binSize] = 1;
      }

      binSize++;
      loopCounter++;
      if (loopCounter == fractionLength) {
        break;
      }
    }
    for (int i = 0; i < binSize; i++) {
      binary += bitArray[i];
    }
  }
  return binary;
}

Just send the 4 bytes of the float variable. Arduino float variables are already in IEEE 754 format:

  float    offset = 12.345; // or whatever
  uint8_t *bytes  = (uint8_t *) &offset; // a byte pointer into the float variable

  for (uint8_t i=0; i < sizeof(f); i++) {
    uint8_t c = bytes[i]; // one of the float's bytes
    if (c < 0x10)
      Serial.print('0'); // leading zero for a byte < 16...
    Serial.print( c, HEX );  // ... because this doesn't print leading zeros
  }

And don't use String. It's very wasteful, and it can cause you program to act weird or crash at random times.

wow. Thanks -dev. That makes sense and is insanely more simple that my previous code. I'll heed your warning about the use of String. Very very much appreciated!