Converting DEC to HEX

Hello,

I am having trouble with converting a decimal number to HEX.
I am using a library for a satellite modem called SWARM M138.
I have integer values which I want to transmit with the "transmitBinary" function of the library.

It expects the data in the following form:
uint8_t message[] = { 0x05, 0xA9, 0xFE, 0x20 };

My integer values have the following form:
int value1 = 1449;
int value2 = -480;

I am having surprisingly big troubles to convert the integer values to HEX
1449 --> 05 A9
-480 --> FE 20
and to get them in an unit8_t array.

I hope my question is comprehensible, if not I am happy to clarify.
Can anybody help me?

Welcome to the forum

Hexadecimal is only a way of representing a number but behind the scenes everything is binary

So, 0xF5 is the same as 0b11110101 in binary and 245 in decimal so why do you need to convert anything ?

Thanks for the warm welcome!

I know that Hex is only a way of representing the number so maybe I did not understand something else.
I have an example for sending a binary message:

// Send a simple binary message
uint64_t id;
const uint8_t myMessage[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
size_t len = 8;
err = mySwarm.transmitBinary(myMessage, len, &id);

and I also looked in the sources of the library (can also post it). That is why It seems to me that it needs the values in Hex.
Maybe there is a simple solution to this, at least I hope that. :wink:

do you want to try that?

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

  int value1 = 1449;
  int value2 = -480;

  uint8_t message[4];

  message[0] = value1 >> 8;   // shift the value by 8 bits 
  message[1] = value1 & 0xFF; // take the lower 8 bits
  message[2] = value2 >> 8;
  message[3] = value2 & 0xFF;
  Serial.println(F("input was "));
  Serial.println(value1, HEX);
  Serial.println(value2, HEX);

  Serial.println(F("output is "));
  for (int i = 0; i < 4; i++) {
    Serial.println(message[i], HEX);  // hex just make it appear for you to make it "hex" like ... its binary/dec/hex ... whatever you want ...
  }

}

void loop() {
  // put your main code here, to run repeatedly:

}
1 Like

Firstly, your example may be incorrect. Your first int is positive, will be stored as 0x05A9; your second is negative, will be stored as 0xFE20.
So please explain.

1 Like
// Send a simple binary message

The comment say binary

const uint8_t myMessage[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

The code uses a hex representation of the values

It would work just as well if you used

const uint8_t myMessage[] = { 0, 1, 2, 3, 4, 5, 6, 7 };

The library functions may well be declared in terms of hex values, but that is just to make it easier for us humans to read the values

By all means post the relevant library function

1 Like

You are totally right, sorry for that:
1449 --> 05 A9

thanks a lot for the answer I will test it asap and come back

Thanks a lot for your answer.
It is now a bit clearer for me.

The library function is at follows:

/**************************************************************************/
/*!
    @brief  Queue a binary message for transmission
    @param  data
            The binary message
    @param  len
            The length of the binary message in bytes
    @param  msg_id
            A pointer to a uint64_t which will hold the assigned message ID
    @return SWARM_M138_ERROR_SUCCESS if successful
            SWARM_M138_ERROR_MEM_ALLOC if the memory allocation fails
            SWARM_M138_ERROR_ERR if a command ERR is received - error is returned in commandError
            SWARM_M138_ERROR_ERROR if unsuccessful
*/
/**************************************************************************/
Swarm_M138_Error_e SWARM_M138::transmitBinary(const uint8_t *data, size_t len, uint64_t *msg_id)
{
  return (transmitBinary(data, len, msg_id, false, 0, false, 0, false, 0));
}

and

// Queue a binary message for transmission
// Return the allocated message ID in msg_id
Swarm_M138_Error_e SWARM_M138::transmitBinary(const uint8_t *data, size_t len, uint64_t *msg_id, bool useAppID, uint16_t appID,
                                            bool useHold, uint32_t hold, bool useEpoch, uint32_t epoch)
{
  char *command;
  char *response;
  char *scratchpad;
  Swarm_M138_Error_e err;

  // Calculate the possible message length
  size_t msgLen = strlen(SWARM_M138_COMMAND_TX_DATA); // $TD
  msgLen += 1; // Space
  if (useAppID) msgLen += 3 + 5 + 1; // AI=65535,
  if (useHold) msgLen += 3 + 8 + 1; // HD=34819200,
  if (useEpoch) msgLen += 3 + 10 + 1; // ET=2147483647,
  msgLen += 2 * len; // The message length in ASCII Hex
  msgLen += 5; // asterix, checksum chars, line feed, null

  // Allocate memory for the command, message, asterix, checksum bytes, \n and \0
  command = swarm_m138_alloc_char(msgLen);
  if (command == NULL)
    return (SWARM_M138_ERROR_MEM_ALLOC);
  memset(command, 0, msgLen); // Clear it

  // Allocate memory for the scratchpad
  scratchpad = swarm_m138_alloc_char(16);
  if (scratchpad == NULL)
  {
    swarm_m138_free_char(command);
    return (SWARM_M138_ERROR_MEM_ALLOC);
  }
  memset(scratchpad, 0, 16); // Clear it

  sprintf(command, "%s ", SWARM_M138_COMMAND_TX_DATA); // Copy the command. Append the space
  if (useAppID)
  {
    strcat(command, "AI=");
    sprintf(scratchpad, "%d", appID);
    strcat(command, scratchpad);
    strcat(command, ",");
  }
  if (useHold)
  {
    strcat(command, "HD=");
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
    sprintf(scratchpad, "%d", hold);
#else
    sprintf(scratchpad, "%ld", hold);
#endif
    strcat(command, scratchpad);
    strcat(command, ",");
  }
  if (useEpoch)
  {
    strcat(command, "ET=");
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
    sprintf(scratchpad, "%d", epoch);
#else
    sprintf(scratchpad, "%ld", epoch);
#endif
    strcat(command, scratchpad);
    strcat(command, ",");
  }
  for (size_t i = 0; i < len; i++)
  {
    char c1 = (data[i] >> 4) + '0'; // Convert the MS nibble to ASCII
    if (c1 >= ':') c1 = c1 + 'A' - ':';
    char c2 = (data[i] & 0x0F) + '0'; // Convert the LS nibble to ASCII
    if (c2 >= ':') c2 = c2 + 'A' - ':';
    sprintf(scratchpad, "%c%c", c1, c2);
    strcat(command, scratchpad); // Append each data byte as an ASCII Hex char pair
  }
  strcat(command, "*"); // Append the asterix
  addChecksumLF(command); // Add the checksum bytes and line feed

  response = swarm_m138_alloc_char(_RxBuffSize); // Allocate memory for the response
  if (response == NULL)
  {
    swarm_m138_free_char(command);
    swarm_m138_free_char(scratchpad);
    return(SWARM_M138_ERROR_MEM_ALLOC);
  }
  memset(response, 0, _RxBuffSize); // Clear it

  err = sendCommandWithResponse(command, "$TD OK,", "$TD ERR", response, _RxBuffSize, SWARM_M138_MESSAGE_TRANSMIT_TIMEOUT);

  if (err == SWARM_M138_ERROR_SUCCESS) // Check if we got $TD OK
  {
    char *idStart = strstr(response, "$TD OK,");
    if (idStart != NULL)
    {
      char *idEnd = strchr(idStart, '*'); // Look for the asterix
      if (idEnd != NULL)
      {
        uint64_t theID = 0;

        idStart += 7; // Point at the first digit of the ID

        while (idStart < idEnd)
        {
          theID *= 10;
          theID += (uint64_t)((*idStart) - '0'); // Add each digit to theID
          idStart++;
        }

        *msg_id = theID;
      }
    }
  }

  swarm_m138_free_char(command);
  swarm_m138_free_char(scratchpad);
  swarm_m138_free_char(response);
  return (err);
}

It is quite long, sorry for that but I was afraid of missing something important...

while 1449 is 0x05a9, it's not clear why you say it is 0xF5A9. the most significant bit often indicates the sign

since 0xFE20 is how -480 would be represented in 2 bytes, i believe the 0xF5 above is incorrect

1 Like

another question is the ordering of the bytes

output from code below

 0xa9 0x05 0x20 0xfe 0x00 0x00 0x00 0x00 0x00 0x00
byte msg [10];

char s [80];

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

    *(int16_t*) & msg [0] = 1449;
    *(int16_t*) & msg [2] = -480;

    for (unsigned n = 0; n < sizeof(msg); n++) {
        sprintf (s, " 0x%02x", msg [n]);
        Serial.print (s);
    }
    Serial.println ();
}

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

1449 is the same as 0x05A0, if that helps :slight_smile:

There is no mention of requiring a hex value in the code that you posted. In fact the notes about the parameters say

    @brief  Queue a binary message for transmission
    @param  data
            The binary message
    @param  len
            The length of the binary message in bytes

calc

Thanks for pointing that out, I made a mistake.
right is: 1449 --> 05 A9
(see post #7)

the byte ordering is definitely
0x05 0xa9
and
0xfe 0x20
thank you!

Arduinos and many other computers store multibyte values the little-endian way.
If transmission defines / requires it, big-endian is often seen.

might be a problem, then.

If you have control of both sides of the protocol, your way of storing big values in a byte array is fine, if you have to do it the other way, well then you have to shift every byte into the right location.

Thank you for your input!
I am in control of both sides, so I'll stick to "my" way of storing.

where in the your code do you format the msg bytes?

Dear all!
Thank you all for your help!
It might not have been a big thing for you but you saved my sunday for me! :slight_smile:
I tested post #4 from noiasca and adapted it for automation and it works very well.
To all you others, thanks a lot for being polite and helping me with so much patience.
Also, I learned a lot today!