How to convert decimal to binary to hexadecimal ?

Hi all,

I use an RF chip that send only data in hex format.
So I want to make a tram like this: "Id value1 value2 value3" etc.
--> So Id and valuexxx must be in hex format.

On the other side I will decode the tram like this: First byte is the id -> convert this byte from hex to decimal, two next byte are for the value one (convert to decimal), next byte for value3 (convert again), next 4 byte for value4 (convert again) etc.

--> So the size of each value must NOT change, because if it's change, my décoding will not work...
ie. If value1 is two byte, even if the value in decimal is 10, value1 must be "000A" and not just "A"

I don't know, with Arduino, how I can convert a number from decimal, to Hex with a "fixed" size:
For my project I need value size of: 4bit, 8bit, 16bit, 20bit, 32bit

Have you got a solution please ?

Thanks for all !

Hexor:
So I want to make a tram like this: "Id value1 value2 value3" etc.

We have trams in Melbourne, but they look more like this:

(Image credit: ninad katyare) GFDL

On the other side I will decode the tram like this: First byte is the id -> convert this byte from hex to decimal ...

Still don't understand.

Maybe: sprintf?

All variables in the arduino are a fixed size. All variables are stored as binary bit patterns.

It is only when YOU come to write them down or get the computer to print them out do things like hex and decimal conversion takes place.

There is no conversion needed. What you do need to do is to handle those numbers correctly for what you are doing. You have not told us what you are doing so we can't help.

Please post your code of what you are attempting.

We have trams in Melbourne, but they look more like this:

Sorry, error of translation :-[ , in French the word is "trame", but I don't remember the english translation... packet ? datagram ?

On the other side I will decode the tram like this: First byte is the id -> convert this byte from hex to decimal ...

The "other side" is the server side.
My arduino will send data, in hex format, to an RF chip, and the chip will transfer this data to a server. On this server I must decode this data.
For example, the first byte is for the ID, two next byte for the first sensor, next byte for the second sensor etc etc.
(the server side is not the subject of this topic, it's just for understanding the problem)

I can't post all my code, because at this time it not exist because I don"t know how to convert my data.

That I want: send data from several sensor to a server.
For acquire the data I use an Arduino and for send the data I use an RF chip, with AT command, and I must send the data in hex format:

AT$1=AABBCCDDEEFF //Data in hex format

And the problem is that each value (in hex format) must have the same lenght over the time, because for decode I will use this:

Fisrt byte = ID
Next two byte = sensor1
Next byte = sensor2
Next four byte = sensor3
Next three byte = sensor4

So if the lenght of a value change (ie. The zero at the left are deleted), all my decoding function will not work.


For example the ensor1 is the DHT22's temperature, and sensor 2 is the humidity.
For the temperature (That can be negative, so I must use signed number):

(for simplify the example, I use unsigned)
Step 1 - I read 27.58°C
Step 2 - I will multiply by 100 to avoiding the comma: 2758
Step 3 - Converting to binary - two byte: 0000 1010 1100 0110
Step 4 - To Hex: 0AC6
Send the data to the server
Decode the data on the server: convert to decimal and divide by 100

No problem for step 1 and 2, but I don't know how I must do for the step 3
Several problem:

  • A byte (data type on Arduino) are 8 bit, in this case they have 16 bit, how I can store this in Arduino (Word datatype can contain 16 bit, ok, But when I have a sensor which use 4 byte, how I can do ?)
  • I must send the value on two byte, How I can keep the four zero at the left ?

Thanks for your help.

The English is "packet", not "tram". We do speak of a "train", but only of pulses, not
data.

For outputing every hex character including leading zeroes I'd normally
use recursive set of functions:

void print_hex_byte (byte b)
{
  Serial.print (b >> 4, HEX) ;   // assuming sending to serial stream...
  Serial.print (b & 15, HEX) ;
}

void print_hex_int (int i)
{
  print_hex_byte (i >> 8) ;
  print_hex_byte (i & 0xFF) ;
}

print_hex_long is left as an exercise!

All the data inside the computer is binary numbers.

It is nonsensical to talk of a chip that sends "hex format"

The most important thing you need to know, is whether you are dealing with binary numbers that represent numbers, or binary numbers that represent text/char in some kind of encoding ( usually ascii ).

(for simplify the example, I use unsigned)
Step 1 - I read 27.58°C
Step 2 - I will multiply by 100 to avoiding the comma: 2758
Step 3 - Converting to binary - two byte: 0000 1010 1100 0110
Step 4 - To Hex: 0AC6
Send the data to the server
Decode the data on the server: convert to decimal and divide by 100

No problem for step 1 and 2, but I don't know how I must do for the step 3

Nonsensical. The number 2758 which you have in the computer - if it is an integer and not a floating point number - is ALREADY 0000101011000110.

So for step 3, you don't need to do anything.

As for your un-numbered Step 5, "Send the data to the server" what do you actually want to do ?

If you want to send the number 2758, then you send 0000101011000110 which you already had in Step 2. Steps 3,4 and 5 are not required.

If you want to send the character '0', the character 'A', the character 'C', and the character '6', then send those. You already determined those in Step 4, whatever that actually was.

Hi,

As for your un-numbered Step 5, "Send the data to the server" what do you actually want to do ?

I want to send the data to the server via my RF chip.
So for sending datas, arduino must send, over software serial, this AT command:

AT$1=hex_packet

Where "hex_packet" is a packet in hexadeciaml (obligatory in hex format, this RF module work as this).
Example:

AT$1=00AABBCCDDEEFF9988

I have made a test, but Arduino delete the zero on the left for the temperature...

This piece of code acquire the temp and humidity of a DHT22 and format them:

float temperature = 0.0;
byte humidity = 0;

[...] 

void acquisition_dht22() {
  errorCode = myDHT22.readData();

  if (errorCode == DHT_ERROR_NONE)
  {
    temperature = myDHT22.getTemperatureC();
    humidity = myDHT22.getHumidity();
    
    //Format
    String thisString1 = String(humidity, HEX);
    Serial.println(thisString1);
    
    word temperature2 = temperature * 100;
    thisString2 = String(temperature2 , HEX);
    Serial.println(thisString2);  

  } 
}

On the serial I see this:

27
85c

27 is ok : 27(16) = 39(10) = 39%RH

85c is only on 12 bit and not 16 as expected.
--> 85c(16) = 2140(10)
2140 / 100 = 21.40°C

I don't unserstand, I'm using "word type" to store the temp but it's seem to store on 12bit only and not 16, as expected.
Where is my problem ?

Thanks a lot for your help and answer ! :wink:

I use an RF chip that send only data in hex format.

The RF chip sends only binary information (only 1s and 0s). You are confused about the data format required by the software (library) that controls the chip.

AT$1=00AABBCCDDEEFF9988

In most programming languages, this would not be a valid expression.
Post a quote or example from the chip data sheet or software library instructions, explaining how to set and then send the value of interest.

The RF chip sends only binary information (only 1s and 0s).

Yes, you are right !
I know this, but I don't speak english every day, so sometimes I don't use the best words to explain me... It's the AT command which require hexadecimal.

This an extract of the datasheet. (see attachment)
Only this command is necessary to send the data.

The extract is meaningless to me. Post a link to the device data sheet.

Hello,

The RF chip is not the problem, the only needed command is "AT$SS=hex_packet" and it's works very well. :wink:
Arduino have send succefully several packet.
But I have manually write the command such as "AT$ss=00AABBCCDDEEFF9988" in the arduino's code.
So now, I try to replace the hex_packet with a variable. :smiley:

@Hexor - This has nothing to do with how numbers are STORED, it has everything to do with how they're DISPLAYED by Serial.print.

You need the values converted to strings with HEX representation with leading zeros, Serial.print offers the HEX display feature but doesn't offer the leading zeros feature so you have to use another method to format the string yourself. Once you have the string, you can do what you like with it i.e. send it to your module or whatever. There are many and varied ways to do this. One way is to use sprintf (google it for full details). Play with the following:

void setup()
{
  Serial.begin(9600);
  
  char buffer[20]; //at least string length + 1
  byte id1 = 5; //0x5
  byte id2 = 77;//0x4D
  unsigned sensor1 = 2140; //0x85C
  unsigned sensor2 = 1234; //0x4D2
  
  //google sprintf for formatting data as strings
  sprintf(buffer, "AT$1=%02X%04X%02X%04X", id1, sensor1, id2, sensor2); //etc...
  Serial.println(buffer);
}

void loop(){}

A big thanks to Nick Gammon and yaafm !! :grinning: :grinning:
sprintf works like a charm !!!

For my test I have use sensor's values coded on 1 byte = 8 bit and 2 byte = 16 octets --> byte type and int type.
But another value must be coded on 3 byte = 24 bit but, if I'm not wrong they don't have data type of 3 byte lenght.
How I can do ? Use a 4 byte data type and with sprintf ask to display only 3 byte ?
Normaly it's work, but maybe they are a best solution to do this.

Thanks !

Hexor:
For my test I have use sensor's values coded on 1 byte = 8 bit and 2 byte = 16 octets --> byte type and int type.
But another value must be coded on 3 byte = 24 bit but, if I'm not wrong they don't have data type of 3 byte lenght.
How I can do ? Use a 4 byte data type and with sprintf ask to display only 3 byte ?
Normaly it's work, but maybe they are a best solution to do this.

No - you're still misunderstanding the difference between the number of bytes needed to STORE a number and the number of bytes needed to REPRESENT that number in a string for display or for sending to your module.

Hmm...
For example if I need to store a max value of 16777215(10) = need 3 byte to store them.
Which data type I must use, on Arduino to store them ? a long ? (which can store up to 4 byte)

Certainly a long is a convenient storage type for that size number - but that is a different question to what you asked re: sprintf in your last post.

I think I was not speak (write !) clearly in my last post (English was not my "every day" langage)

My question was:
For a number which can be stored on 3 byte, which Arduino's data type I must use ?
--> If I must use a long (4 byte) I will use sprintf to display 3 byte of data. (to have the leading zero to fill 3 byte max, not 4 byte)

But with your answer I have found the solution !
--> Use a long, and use sprintf to have the leading zero on 3 byte only.
:wink: