Array of hex values to a long string?

I have a device that sends its data in what I am thinking are hex values… For example, I will have it send “12345678901230AB” on the bus and it ends up in my read buffer as (I see this using Serial.print() with HEX modifier) -

buff[0]=‘12’;
buff[1]=‘34’;
buff[2]=‘56’;
buff[3]=‘78’;
buff[4]=‘90’;
buff[5]=‘12’;
buff[6]=‘30’;
buff[7]=‘AB’;
buff[8]=‘0x00’; // I add this terminator

How do I make it into something more workable? Like a string array? For example, maybe someday I want to store this as an ID number in a database. Or, instead of making a loop to cycle through each element of buff, Serial.println(buff); …

I am making sample code to make the problem, simpler, …

static char buff[10] = { "" };

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

  //  Initalize the array
  buff[0] = '12';
  buff[1] = '34';
  buff[2] = '56';
  buff[3] = '78';
  buff[4] = '90';
  buff[5] = '12';
  buff[6] = '30';
  buff[7] = 'AB';
  buff[8] = '00';

  //for (int b = 0; b < 10; b++) Serial.println(buff[b], HEX);
  Serial.println(buff);
}

void loop() {
}

The output of this code is -
2468020B0

I want
“123456789012AB”

It seems I need to shift the high bit by a mask of some sort and again with the low bit and put those into a string?

Thanks.

  buff[7] = 'AB';

single quotes are for single characters.

buff is of type char, so in each element you can only store one character, not two.

This would be legal:

  buff[7] = 0xAB;

But when you print it, since it is of type char, it will be treated as ascii and it won't print AB but whatever character that is the ascii code for.

You are assigning two characters to each array element, but each array element can only fit one.

Actually, I’m not even sure how the compiler interprets ‘12’! not the way you think - something enclosed in single quotes is supposed to be a single char, but you’re putting two between the single quotes. It looks to me like it’s just discarding the first one of those - or maybe converting them to a 16-bit value and then truncating it to fit in one byte.

static char buff[10] = { "" };

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

  //  Initalize the array
  buff[0] = 0x12;
  buff[1] = 0x34;
  buff[2] = 0x56;
  buff[3] = 0x78;
  buff[4] = 0x90;
  buff[5] = 0x12;
  buff[6] = 0x30;
  buff[7] = 0xAB;
  buff[8] = 0;

  for (int b = 0; b < 10; b++) Serial.print(buff[b], HEX);
  Serial.println();
}

void loop() {
}

Single quotes are used to delimit character constants. Character constants just evaluate to numbers using the ASCII encoding for characters. For instance, 'O' is the same thing as the number 79.

These are all different ways of saying the same thing:

char a = 'O'; // character costant
char b = 79; // decimal constant
char c = 0x4F; // hexadecimal constant
char d = 0b01001111; // binary constant
char e = 0117; // octal constant

C also supports escape codes in character constants

char f = '\x4F'; 
char g = '\0117';

Although this is more useful for strings: "This is\nsome text\nwith line-breaks."

In some languages, something like this '12' will be interpreted as a unicode character constant. I'm not sure that it's part of the C++ language.

The point being that these are all different ways of writing numbers, of writing numeric constants.

Ahhhh of course! It is the assignment of the value to the element of the array. Thank you.
I changed to unsigned char instead of char, removed the single quote because I am assigning a value, not a string constant, and changed serial.println() to serial.print(), so everything prints on one line…

New code -

static unsigned char buff[10] = { "" };

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

  //  Initalize the array
  buff[0] = 0x12;
  buff[1] = 0x34;
  buff[2] = 0x56;
  buff[3] = 0x78;
  buff[4] = 0x90;
  buff[5] = 0x12;
  buff[6] = 0x30;
  buff[7] = 0xab;
  buff[8] = 0x00;

  for (int b = 0; b < 9; b++) Serial.println(buff[b], HEX);
}

void loop() {
}

New output -
12345678901230AB0

This is exactly what I want my pseudo code to do. Now, on to the real question:

Assuming only values 0 - 9, not using A - F… How do I treat this as a customer “number”?

For example,

if (customerNumber = "12345678901230")  Serial.println("We have a match!");

or

if (customerNumber = 12345678901230)  Serial.println("We have a match!");

What datatype would customerNumber be and how do I append each element of buff of customerNumber to make the long string/number to compare against?

12,345,678,901,230 is too big for a long.

single quotes are for single characters.

Corollary: double quotes are for double/multiple characters? :)

Serial.print("ABCD12");  //prints: ABCD12

Sometimes, double quotes also make single character --

Serial.println('A');  //prints: A
Serial.print("B");            //prints: B

My approach would be the following:

[color=#00979c]inline[/color] [color=#00979c]char[/color] [color=#000000]nibbleToHex[/color][color=#000000]([/color][color=#00979c]uint8_t[/color] [color=#000000]nibble[/color][color=#000000])[/color][color=#000000];[/color]  [color=#434f54]// convert a 4-bit nibble to a hexadecimal character[/color]

[color=#00979c]class[/color] [color=#000000]Customer[/color] [color=#434f54]:[/color] [color=#00979c]public[/color] [color=#000000]Printable[/color] [color=#000000]{[/color]
  [color=#00979c]public[/color][color=#434f54]:[/color]
    [color=#000000]Customer[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]id[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]9[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
      [color=#d35400]memcpy[/color][color=#000000]([/color][color=#5e6d03]this[/color][color=#434f54]-[/color][color=#434f54]>[/color][color=#000000]id[/color][color=#434f54],[/color] [color=#000000]id[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]id[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#000000]}[/color]
    [b][color=#d35400]size_t[/color][/b] [color=#000000]printTo[/color][color=#000000]([/color][color=#000000]Print[/color][color=#434f54]&[/color] [color=#000000]printer[/color][color=#000000])[/color] [color=#00979c]const[/color] [color=#000000]{[/color]
      [color=#000000]printer[/color][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]F[/color][color=#000000]([/color][color=#005c5f]"Customer #"[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
      [color=#5e6d03]for[/color] [color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]&[/color][color=#000000]currByte[/color] [color=#434f54]:[/color] [color=#000000]id[/color][color=#000000])[/color] [color=#000000]{[/color]
        [color=#000000]printer[/color][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]nibbleToHex[/color][color=#000000]([/color][color=#000000]currByte[/color] [color=#434f54]>>[/color] [color=#000000]4[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
        [color=#000000]printer[/color][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]nibbleToHex[/color][color=#000000]([/color][color=#000000]currByte[/color] [color=#434f54]>>[/color] [color=#000000]0[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
      [color=#000000]}[/color]
    [color=#000000]}[/color]
    [color=#00979c]bool[/color] [color=#00979c]operator[/color][color=#434f54]==[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#000000]Customer[/color] [color=#000000]&other[/color][color=#000000])[/color] [color=#00979c]const[/color] [color=#000000]{[/color]
      [color=#5e6d03]for[/color] [color=#000000]([/color][color=#00979c]uint8_t[/color] [color=#000000]i[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000];[/color] [color=#000000]i[/color] [color=#434f54]<[/color] [color=#000000]9[/color][color=#000000];[/color] [color=#000000]i[/color][color=#434f54]++[/color][color=#000000])[/color]
        [color=#5e6d03]if[/color] [color=#000000]([/color][color=#5e6d03]this[/color][color=#434f54]-[/color][color=#434f54]>[/color][color=#000000]id[/color][color=#000000][[/color][color=#000000]i[/color][color=#000000]][/color] [color=#434f54]!=[/color] [color=#000000]other[/color][color=#434f54].[/color][color=#000000]id[/color][color=#000000][[/color][color=#000000]i[/color][color=#000000]][/color][color=#000000])[/color]
          [color=#5e6d03]return[/color] [color=#00979c]false[/color][color=#000000];[/color]
      [color=#5e6d03]return[/color] [color=#00979c]true[/color][color=#000000];[/color]
    [color=#000000]}[/color]
    [color=#00979c]bool[/color] [color=#00979c]operator[/color][color=#434f54]!=[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#000000]Customer[/color] [color=#000000]&other[/color][color=#000000])[/color] [color=#00979c]const[/color] [color=#000000]{[/color]
      [color=#5e6d03]return[/color] [color=#434f54]![/color][color=#000000]([/color][color=#434f54]*[/color][color=#5e6d03]this[/color] [color=#434f54]==[/color] [color=#000000]other[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#000000]}[/color]
  [color=#00979c]private[/color][color=#434f54]:[/color]
    [color=#00979c]uint8_t[/color] [color=#000000]id[/color][color=#000000][[/color][color=#000000]9[/color][color=#000000]][/color][color=#000000];[/color]
[color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#5e6d03]while[/color][color=#000000]([/color][color=#434f54]![/color][b][color=#d35400]Serial[/color][/b][color=#000000])[/color][color=#000000];[/color]

  [color=#000000]Customer[/color] [color=#000000]a[/color][color=#000000]([/color] [color=#000000]{0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x30, 0xAB, 0x01}[/color] [color=#000000])[/color][color=#000000];[/color]
  [color=#000000]Customer[/color] [color=#000000]b[/color][color=#000000]([/color] [color=#000000]{0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x30, 0xAB, 0x01}[/color] [color=#000000])[/color][color=#000000];[/color]
  [color=#000000]Customer[/color] [color=#000000]c[/color][color=#000000]([/color] [color=#000000]{0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x30, 0xAB, 0x00}[/color] [color=#000000])[/color][color=#000000];[/color]

  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color] [color=#000000]a[/color] [color=#434f54]==[/color] [color=#000000]b[/color] [color=#434f54]?[/color] [color=#005c5f]"a is equal to b"[/color] [color=#434f54]:[/color] [color=#005c5f]"a is not equal to b"[/color] [color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color] [color=#000000]b[/color] [color=#434f54]!=[/color] [color=#000000]c[/color] [color=#434f54]?[/color] [color=#005c5f]"b is not equal to c"[/color] [color=#434f54]:[/color] [color=#005c5f]"b is equal to c"[/color] [color=#000000])[/color][color=#000000];[/color]
  
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color] [color=#000000]c[/color] [color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color] [color=#000000]}[/color]

[color=#00979c]inline[/color] [color=#00979c]char[/color] [color=#000000]nibbleToHex[/color][color=#000000]([/color][color=#00979c]uint8_t[/color] [color=#000000]nibble[/color][color=#000000])[/color] [color=#000000]{[/color]  [color=#434f54]// convert a 4-bit nibble to a hexadecimal character[/color]
  [color=#000000]nibble[/color] [color=#434f54]&=[/color] [color=#000000]0xF[/color][color=#000000];[/color]
  [color=#5e6d03]return[/color] [color=#000000]nibble[/color] [color=#434f54]>[/color] [color=#000000]9[/color] [color=#434f54]?[/color] [color=#000000]nibble[/color] [color=#434f54]-[/color] [color=#000000]10[/color] [color=#434f54]+[/color] [color=#00979c]'A'[/color] [color=#434f54]:[/color] [color=#000000]nibble[/color] [color=#434f54]+[/color] [color=#00979c]'0'[/color][color=#000000];[/color]
[color=#000000]}[/color]

Output:

a is equal to b
b is not equal to c
Customer #12345678901230AB00

Pieter

Edit: Use references in operator== en operator!= methods, so it doesn’t have to copy the customer.

My approach would be the following:

byte buff[8];
char myArray[sizeof(buff)*2];
byte x;

void setup()
{
  Serial.begin(9600);
  buff[0] = 0x12;
  buff[1] = 0x34;
  buff[2] = 0x56;
  buff[3] = 0x78;
  buff[4] = 0x90;
  buff[5] = 0x12;
  buff[6] = 0x30;
  buff[7] = 0xAB;
  //----------------
  hexToAscii();
  myArray[sizeof(buff)*2] = 0x00;  //null-byte
  Serial.print(myArray);      //output: 12345678901230AB
}

void loop()
{

}

void hexToAscii()
{
  for (int i = 0, j = 0; i < 8, j < 16; i++, j++)
  {
    x = buff[i];  //x = 12
    x = x >> 4;   // x= 01
    if ((x >= 0) && (x <= 9))
    {
      myArray[j] = x + 0x30;    //0x30 - 0x39 = 0 - 9
      j = j + 1;
    }
    else
    {
      myArray[j] = x + 0x37;    //0x41 - 0x46 = A - F
      j = j + 1;
    }
    //-------------------------------------
    x = buff[i];  //x = 12
    x = x & 0x0F;   // x= 02
    if ((x >= 0) && (x <= 9))
    {
      myArray[j] = x + 0x30;    //0x30 - 0x39 = 0 - 9
      //j = j+1;
    }
    else
    {
      myArray[j] = x + 0x37;    //0x41 - 0x46 = A - F
      //j = j+1;
    }
  }
}

Thank you both for the time typing up the solution for me.

@PieterP The code you wrote looks cool. However, I cannot follow it. I have saved it off for later review and someday I hope to look at it and say ah, yes, of course....

@GolamMostafa Your code, to me, seems easier to follow and have modified it to work with my code.

On the first pass through, the first two numbers are incorrect. All other passes are fine. Not sure why this is.

Again, thank you both for your time helping me with through this problem.

I’ll try to explain how it works:

The first line is just a function prototype for a function that converts a 4-bit number to its hexadecimal representation. E.g. if you enter 15, it’ll return ‘F’, if you enter 5, it’ll return ‘5’. The actual implementation of the function is at the bottom of the sketch.

The next thing is the definition of a class Customer. A class is just a collection of data (a customer id of 9 bytes long, in this case) and some functions to manipulate this data (e.g. a function to print the customer’s id, a function to check the (in)equality of customers). These functions are called ‘methods’.

The data is an array of 9 bytes (uint8_t == byte), it is declared at the bottom of the class, and it’s private, so you can’t read/write to it from outside of the class.

The first function in the class is a special one, it’s a constructor. It’s used to create a Customer object. It takes an array of 9 bytes as a parameter (id), and it just copies this array into its own internal array (this->id).
To create a Customer object, you just use the name ‘Customer’, then a variable name, and then, between parentheses, the id (as an array). For example:

Customer myCustomer({0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x30, 0xAB, 0x01});

Now you have a Customer object called ‘myCustomer’ that has an id equal to the array above.

Then I defined the printTo function. It’s a function that’s declared by the Arduino Core that allows you to print your own objects to a Print (e.g. Serial is a ‘Print’). By implementing this function, we can do

Serial.println(myCustomer);

The way it works, is it just loops over the entire array, printing each byte as a hexadecimal number. Each byte has 8 bits, and each hex character only represents 4 bits, so we have to use the nibbleToHex function twice for each byte, first for the highest 4 bits (currByte >> 4) and then for the lowest for bits (currByte >> 0) or (currByte). ‘>>’ is the bitshift operator: if currByte is 0b10101111, then currByte >> 4 is 0b00001010.

The next function implements the “==” operator for Customer objects. All it does is looping over the ids of the two operands, and as soon as it finds a byte that’s different between the two, it returns false (i.e. not equal). If the loop finishes, and all bytes are the same, then the Customers are the same, so it returns true (equal).
The const between parentheses means that the ‘other’ Customer is not altered by the function (read only), and the const after the parentheses means that the first Customer of the comparison is not altered by the function. The ampersand before ‘other’ means: use a reference to the existing version of ‘other’, instead of making a copy.

Operator!= is pretty simple: there’s inequality between two Customers if they’re not equal, so we can use the equal function and invert its result. (‘this’ points to a Customer, so we have to follow the pointer first, to get to the actual Customer, that’s what the asterisk is doing, it’s called dereferencing)

Finally, I just start the Serial connection, create some Customer objects, check their equality, and print the results.

If you have any further questions, feel free to ask them.