Convert Serial.read() hex to ASCII string

  • Short version -
    I need: byte a[] = {0x43, 0xE8, 0xD4, 0x7A};
    to be in format: char b[] = "43E8D47A";

  • Longer version -
    I have incoming serial data via a modbus sensor. a[] above is the meat of the payload as read in bytes. This converts it to float32 per the datasheet, which I have not been able to accomplish directly from a[]. I can accomplish the conversion using b[] and a union, which equals 465.65997. I cannot figure out how convert from a[] to b[].

edit: if there is a more elegant way to convert directly from a[] to the float value, I have looked with no luck and am all ears.

byte a = 0x43;

Each byte is 2 nybbles.

( 0x43 & 0xF0 ) >> 4 + '0' = '4' // 1st char

( 0x43 & 0xF ) + '0' = '3' // 2nd char --- need more is easy?

char b[ 3 ] = ( '4', '3', 0 };

The & is a bit-logical AND.
The >> is the right-shift operator that moves all the bits to the right.
The + '0' lines up numbers starting at zero to start at ASCII '0'.

CosineKitty's Bit Math Tutorial explains all that.
For the 1st char

You don't really need to convert from byte to char, what you need is to reverse the order of the bytes. If you are not concerned with keeping the original data in a, the reordering can be done in-place, or you can create a temporary byte array, then do a memcpy into the float (I'm not sure individually copying the bytes from a into the float would be a legal method of type punning).

byte a[] = {0x43, 0xE8, 0xD4, 0x7A};

void setup(){
  Serial.begin(115200);
  Serial.println("start");
  float f;
  byte temp[4];
  temp[0] = a[3];
  temp[1] = a[2];
  temp[2] = a[1];
  temp[3] = a[0];
  memcpy(&f, &temp, sizeof(float));
  Serial.println(f, 5);
  Serial.println("end");
}

void loop(){
}

Sorry for not going straight here!

Use type unsigned long variables for this

0x43 << 24 + 0xE8 << 16 + 0xD4 << 8 + 0x7A = 0x43E8D47A = 1139332218 (my Linux calculator does HEX and DEC).
Note that once the variable is set to the HEX, it prints DEC by default.
What a 32 bit float will do with that is get the 1st 7 digits right and kludge the other 3 but that's what floats do.

A loop to do that will be cleaner. I leave that up to you.

Some totally untested code!

I assume you could use sscanf() to get your float out of the string.

  strcpy(b, "");               // Make sure string is empty
  for (i = 0; i < 4; i++)
    strcat(b, "%X", a[i]);     // Print each byte into the string

Or do it in a single line:

  sprintf(b, "%X%X%X%X", a[0], a[1], a[2], a[3]);

output

43E8D47A
byte a[] = {0x43, 0xE8, 0xD4, 0x7A};
char s [80];

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

    sprintf (s, "%02X%02X%02X%02X", a[0], a[1], a[2], a[3]);
    Serial.println (s);
}

void loop () {
}
1 Like

Thank you for the quick replies!

sprintf worked.

I tried memcpy before the first post but couldn't get it to work.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.