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.
Thanks for the quick reply! 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!