Merging an array of Char with an array of Bytes

Hi all,
I have recently faced a challenge with merging two arrays of different types. I know this is a repetitive question but I searched for a long time in other forums with the same problem but didn't get the answer.
So, I have an array for the microcontroller's Unique ID containing 9 bytes of numbers in it which needs to be printed in HEX format. And on the other side, I have an array of ASCII characters of type BYTE that I need to merge together. I tried SPRINTF, SPRINTNF and STRCAT codes but it returns messed up numbers only!!!

I downloaded the uniqueID library from Github :
https://github.com/ricaun/ArduinoUniqueID

The array that I want to merge it with is:
byte buff[]={"Unique ID="};

I just don't want to print the buff array next to the Unique ID, I want them to be merged under one array. I know the code will print UniqueID size which is only 9 bytes, but even when I increase it to 30 bytes in the for loop, it prints zeros after the Unique ID serial number.

#include "ArduinoUniqueID.h"
void setup()
{
 delay(1000);
 byte buffer[25]={"Unique ID= "};
Serial.begin(115200);
 snprintf(buffer, "%s%s", UniqueID);
 for (size_t i = 0; i < UniqueIDsize; i++)
  {
    if (UniqueID[i] < 0x10)
   delay(100);  
    Serial.print(buffer[i],HEX); 
  }
}

void loop()
{
}

Why do you want to merge them? Aka, what do you think to achieve with it in contract to separate array's? If all you want to do is print them, don't. Just print them right after eachother.

Also, you don't try to merge them, you try to write the ascii hex representation to a string.

septillion:
Why do you want to merge them? Aka, what do you think to achieve with it in contract to separate array's? If all you want to do is print them, don't. Just print them right after eachother.

Also, you don't try to merge them, you try to write the ascii hex representation to a string.

Thanks for the reply.
I'm trying to transmit data (Over RF) from 4 slave boards to a master board. I have been successful in sending the Unique ID and the arrays separately, but I don't want to send data twice since the slaves are battery powered and every transmission almost costs 50mA. If I can merge the message with ID, I can easily determine which slave board is transmitting data. I have been trying for days to merge these two arrays but no success.

there are better ways to handle the id

outputu

text:  01 02 03 04 05 06 07 08 09
const char text [] = "text:";
byte       id   [] =  { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

char s [40];

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

    sprintf (s, "%s  %02x %02x %02x %02x %02x %02x %02x %02x %02x",
        text, id [0], id [1], id [2], id [3], id [4], id [5],
        id [6], id [7], id [8]);
    Serial.println (s);
}


void loop (void)
{
}

gcjr:
there are better ways to handle the id

outputu

text:  01 02 03 04 05 06 07 08 09
const char text [] = "text:";

byte       id   [] =  { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

char s [40];

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

sprintf (s, "%s  %02x %02x %02x %02x %02x %02x %02x %02x %02x",
       text, id [0], id [1], id [2], id [3], id [4], id [5],
       id [6], id [7], id [8]);
   Serial.println (s);
}

void loop (void)
{
}

Thanks for the reply. There are still a few issues with this. First, the result array has to be type BYTE in order to correspond to my other code. So, I tried doing the following (I changed the s array to BYTE) :

#include "ArduinoUniqueID.h"

const char text[]={"Unique Id="};
byte s[40];


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

sprintf (s, "%s  %02x %02x %02x %02x %02x %02x %02x %02x %02x",
        text, UniqueID8 [0], UniqueID8 [1], UniqueID8 [2], UniqueID8 [3], UniqueID8 [4], UniqueID8 [5],
        UniqueID8 [6], UniqueID8 [7], UniqueID8 [8]);
    Serial.println (s[40]);
}

void loop()
{
}

The output is 2 only !! If I put char as type of array s, it will print one square only !!

    Serial.println (s[40]);

this attempts to print a single byte in the "s" array.

shouldn't this be

    Serial.println (s);

Alright, for a wireless transmit you indeed need it as a single string. But use the property of to array :slight_smile:

Although you can probably write a string to itself with sprintf() if you start with it, it's extra work. Also, you could sprintf() to the correct location in a string but think using an intermediate variable makes it more readable.

const char text[] = "text:";
byte ids[] =  {1, 2, 3, 4, 5, 6, 7, 8, 9};

char output[40]; //need at least 5 (text)+ 9 x 3 (id's + space) + 1 (null termination)

void setup(){
  Serial.begin (115200);
  
  strcpy(output, text);
  
  for(byte i = 0; i < sizeof(ids); i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, " %02x", ids[i]);
    strcat(output, idStr);
  }
  
  Serial.println(output);
}

void loop (void){
  
}

If the thing you want to plug it into really does not support strings (which seems weird in the application), just cast the char array as byte array

(byte *) output

gcjr:

    Serial.println (s[40]);

this attempts to print a single byte in the "s" array.

shouldn't this be

    Serial.println (s);

I tried it like that but it gives and error :
no matching function for call to 'println(byte [40])'

no matching function for call to 'println(byte [40])

are you sure that's what you compiled because "byte [40]" is not Serial.println (s);

How about just combining the data into a single array just by copying each element one-by-one

char names[] = "Dizzy coder";
uint8_t numbers[10] = {1,2,3,4,5,6,7,8,9,0};

byte buffer[30];

uint8_t count;

for(count = 0; count < (10 + sizeof(names)); count++)
{
	if(count < 10) {
		buffer[count] = numbers[count];
	}
	else {
		buffer[count] = names[count - 10];
	}
}

buffer[count] = 0;

septillion:
Alright, for a wireless transmit you indeed need it as a single string. But use the property of to array :slight_smile:

Although you can probably write a string to itself with sprintf() if you start with it, it's extra work. Also, you could sprintf() to the correct location in a string but think using an intermediate variable makes it more readable.

const char text[] = "text:";

byte ids[] =  {1, 2, 3, 4, 5, 6, 7, 8, 9};

char output[40]; //need at least 5 (text)+ 9 x 3 (id's + space) + 1 (null termination)

void setup(){
 Serial.begin (115200);
 
 strcpy(output, text);
 
 for(byte i = 0; i < sizeof(ids); i++){
   char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
   sprintf(idStr, " %02x", ids[i]);
   strcat(output, idStr);
 }
 
 Serial.println(output);
}

void loop (void){
 
}




If the thing you want to plug it into really does not support strings (which seems weird in the application), just cast the char array as byte array


(byte *) output

Thank you very much, This really combines the two arrays, However, it prints incorrect values for the Unique ID.
The output on COM port is now: Unique Id=QPQP

@hzrnbgy And end up with an array that contains ASCII and non-ASCII. Does not seem very useful to me...

@dizzycoder Please post all the code. My code had no "Unique Id" in it so it must be in the changes you made :slight_smile:

Hi Septillion,

Here is the full code.

the full code.zip (3.04 KB)

Because of macro trickery in the UniqueID library you can't do a sizeof() on it. Now it return the pointer size (2 bytes). But your mistake is sprint()'ing it into 'UniqueID8' instead of the temporary string 'idStr'. And because 'idStr' isn't initialized it seems to contain "QP" by "sheer luck".

So try:

//
// ArduinoUniqueID.ino
//
// Example shows the UniqueID on the Serial Monitor.
//

#include "ArduinoUniqueID.h"

const char text[]= "Unique Id=";
char output[40];

void setup(){
  delay(1000);

  strcpy(output,text);
  Serial.begin(115200);

  for(byte i = 0; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, " %02x", UniqueID8[i]);
    strcat(output, idStr);
  }
 
  Serial.println(output);
}


void loop(){
  
}

Also fixed the indentation. And please post the code in code tags next time instead of a zip as stated in the forum rules.

septillion:
Because of macro trickery in the UniqueID library you can't do a sizeof() on it. Now it return the pointer size (2 bytes). But your mistake is sprint()'ing it into 'UniqueID8' instead of the temporary string 'idStr'. And because 'idStr' isn't initialized it seems to contain "QP" by "sheer luck".

So try:

//

// ArduinoUniqueID.ino
//
// Example shows the UniqueID on the Serial Monitor.
//

#include "ArduinoUniqueID.h"

const char text[]= "Unique Id=";
char output[40];

void setup(){
 delay(1000);

strcpy(output,text);
 Serial.begin(115200);

for(byte i = 0; i < 8; i++){
   char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
   sprintf(idStr, " %02x", UniqueID8[i]);
   strcat(output, idStr);
 }

Serial.println(output);
}

void loop(){
 
}



Also fixed the indentation. And please post the code in code tags next time instead of a zip as stated in the forum rules.

This is the absolute answer, thank you very much!!!