Is it possible to convert a byte* to char[]?
I am trying this code and it prints ascii values to me
char arr[16];
byte *buffer; // it has a value like "0472AB12CBAC"
strncpy(arr, (char*)buffer,sizeof(arr));
Serial.println(arr);
Is it possible to convert a byte* to char[]?
I am trying this code and it prints ascii values to me
char arr[16];
byte *buffer; // it has a value like "0472AB12CBAC"
strncpy(arr, (char*)buffer,sizeof(arr));
Serial.println(arr);
Can you post a complete example so we don't have to guess if your buffer contains 0x04, 0x72 etc or that it contains the (null terminated) string "0472..." (as you describe).
And what do you expect as output.
Also, whether the sizeof(array) returns what you expect - if it is buried in a function it might be returning the size of the pointer, not the array.
I am trying to read the RFID buffer, which is a byte* and would like to save it to a char array. I have to work without the serial library as a requirement. This is my loop
char *temp;
char arr[16];
void loop
{
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
temp= (char*)(mfrc522.uid.uidByte);
strncpy(arr, temp, sizeof(arr));
arr[sizeof(temp)-1]=NULL;
send(arr);
delay(2000);
}
NULL is not what you want. You want NUL which is '\0'
temp is a pointer. It points to a memory location and so it is not possible for temp to have a value like:
"0472AB12CBAC"
It can point to memory location where information like that is stored, but the actual variable temp itself is just a memory location.
sizeof(temp) will return the size of the temp variable which is 2 since temp is a pointer which is an address.
And memory addresses on the AVR are 16 bits which are 2 bytes in size.
If you want the size of arr then you need to use sizeof(arr) and not sizeof(temp).
If you want the size of what temp points to then you use strlen() and not sizeof(), but only if the data at the memory location is an actual C string.
strncpy() already will contain the needed NUL if the string length of uidByte[] is less than what you told strncpy() which was sizeof(aar)
If you are concerned that strlen(uidByte) is greater than sizeof(aar) -1, and want to add a NUL to the last position of aar[], then you need to be using sizeof(aar) and not strlen(temp).
note: strlen(temp) would never be useful.
Note that temp is not really needed:
i.e
strncpy(arr, (char*)mfrc522.uid.uidByte, sizeof(arr));
arr[sizeof(arr)-1]=NUL;
The first line will copy up sizeof(arr) bytes from uidByte[] to arr
The 2nd line will add a NUL to the last location if the string length of uidByte[] happens to be larger than arr.
BUT......
All this assumes that the uidByte[] array is holding an actual C string. (NUL terminated characters)
If it is just data bytes, then you cannot use C string functions like strncpy() and strlen()
The Uid structure also has a length field:
mfrc522.uid.size
which holds the length of the uid data stored in uidByte[] array
So if the uidByte[] array is really an array of bytes and not a C string, then you will have to use that size to know the actual length of the data in the array to know how much to copy and you will not be able to use string functions like strncpy() and strlen()
--- bill
Is this what you are looking for?
// Dump UID
Serial.print(F("Card UID:"));
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Taken from ChangeUID example that comes with the library.
Thanks Bill! for a very helpful explanation.
You are right, the data is byte array and I want it to copy it to a char array. Iam trying this, but won't work
arr = reinterpret_cast<char>(mfrc522.uid.uidByte);
throws an error: cast from 'byte* {aka unsigned char*}' to 'char' loses precision [-fpermissive]
This gives me an ascii value as it is getting converted from byte to char without a cast
for(int i = 0; i<=(mfrc522.uid.size); i++)
{
arr[i] = mfrc522.uid.uidByte[i];
}
Can you help me with the conversion. Sorry stuck at basic.
@sterretje: I cannot use the serial library as a requirement but i have already tested the code to test the RFID reader when I bought it. /Thanks.
muzab:
@sterretje: I cannot use the serial library as a requirement but i have already tested the code to test the RFID reader when I bought it. /Thanks.
The given code simply shows how to convert. It does not matter that it prints, you can just as well assign it to a char array.
Think outside the box ![]()
muzab, you have wandered down the XY problem path taking us with you.
In case you are not familiar with the XY problem: http://xyproblem.info/
As evidence, your initial post was asking about issues with respect to grabbing data from a byte array and then printing it out using the Serial.println() function.
A bit more information dribbles out that indicates that there is more to the problem than was disclosed in post #0
And when sterretje offered you a solution for that in post #8 based on the information about the problem provided so far, you came back and said you could not use the Serial library.
So obviously the actual problem is different than what were lead to believe.
I provided some additional information that may help, but in order to get assistance, you need to disclose what the real problem is and any particular limitations/restrictions on the solution.
--- bill
Pay close attention to indexes. Your for loop is copying one too many bytes.
for(int i = 0; i<=(mfrc522.uid.size); i++)
lets dip down in to the weeds for a moment:
Keep in mind that byte and char types are not the same.
While in gcc on the AVR and ARM, both fit in 8 bits, a byte is a Arduino proprietary typedef for unsigned char and a char is well a char.
Technically according to the C standard, there are actually three "byte"/"char" types: char, signed char, and unsigned char.
They are treated differently by the compiler.
So while a compiler may treat a char as signed or unsigned by default it is not treated exactly the same as signed char or unsigned char.
(For historical reasons there are 3 types, and even if a char is signed by default it is not treated the same as a signed char in all cases)
The gcc AVR compiler treats type char as signed by default.
type char is intended for characters and not for generic 8 bit data.
If using 8 bit data, signed char or unsigned char should be used.
The C standard also includes some standard types to aid with this.
uint8_t and int8_t are the official 8 bit data types.
Arduino decided to create their own proprietary type for unsigned 8 bit values and provides a typedef called byte.
Now back to your situation.
I am not familiar with your rfid library and how it stores its information in the Uid structure.
However, since it declared the data array as a byte array, AND provided a length field, I'd assumed that the data is not printable characters but actual 8 bit values that could be any value from 0x00 to 0xff.
(This could be wrong since I see many programmers to odd things).
Depending on what type of data format the original data is in, and how you intend to use the data will determine what you have to do and how you treat the data.
For example if it is 8 bit data and you need it to be converted to printable ASCII characters, then you will have to convert the value of each 8 bit data byte into the printable characters for that value.
And you would have to know what base the printable value needs to be in.
i.e. if a byte value is 222 (decimal) 0xDE (hex) then that single 8 bit data value would turn into multiple ASCII characters. The exact characters would be determined by the base. (2(binary), 10(decimal), 16(hex))
In decimal the value is 222 so the printable characters are '2', '2,', '2', or 0x32, 0x32, 0x32
In Hex, the value 0x 0xDE so the printable characters are 'D', 'E', or 0x44, 0x45
If you don't need to do any translation on the data but merely grab it and send it somewhere else,
then all you do is copy the correct number of bytes and send it.
But if there is no translation, then there would be no need to copy the bytes from the orignal location to another before sending them.
--- bill
Sorry Bill and sterretje for creating the XY-Problem. A bit stressed here and confused but i genuinely appreciate your help and suggestions.
The actual RFID is in this format "04 73 BA 12 B6 2B 80", when printed with serial library. I want to send the exact ID, But I dont want to do it with serial so, this is what I have tried so far:
char arr[16];
int arr2[16];
byte *buffer;
buffer = (mfrc522.uid.uidByte);
bytesize = (mfrc522.uid.size);
try-1
strcpy(arr, (char*)buffer ); // gives me an ascii value
try-2 // gives me a value "4i
×0"
for (int i = 0; i <= bytesize; i++)
{
arr2[i] = buffer[i];
if(arr2[i]<10){arr[i] = arr2[i]+'0';}
else{arr[i] = (arr2[i]-10)+'a';}
}
try-3 // gives me: invalid conversion from 'const char*' to 'char' [-fpermissive]
for (int i = 0; i <= bytesize; i++)
{
arr2[i] = buffer[i];
if(arr2[i]<10){arr[i] = arr2[i]+"0";}
else{arr[i] = arr2[i]-10)+"a";}
}
try-4 // gives me: invalid conversion from 'const char*' to 'char' [-fpermissive]
for (byte i = 0; i < bytesize; i++)
{
arr[i]=buffer[i] < 0x10 ? " 0" : " ";
arr[i]=(arr[i], HEX);
}
try-5 // gives NOTHING
for (byte i = 0; i < bytesize; i++)
{
arr2[i] = buffer[i];
arr[i] = (arr2[i]+'0');
arr[i] = (buffer[i], HEX);
}
try-6 // make a function that takes the buffer and converts the ASCII to HEX chars
// Throws garbage values
char *atohx(char * dst, byte *src)
{
char *ret = dst;
for(int lsb, msb; *src; src += 2)
{
msb = tolower(*src);
lsb = tolower(*(src + 1));
msb -= isdigit(msb) ? 0x30 : 0x57;
lsb -= isdigit(lsb) ? 0x30 : 0x57;
if((msb < 0x0 || msb > 0xf) || (lsb < 0x0 || lsb > 0xf))
{
*ret = 0;
return NULL;
}
*dst++ = (char)(lsb | (msb << 4));
}
*dst = 0;
return ret;
}
Type casting or conversion seems to be tedious in Arduino without serial, as I cannot do something like this
for(byte i = 0; i<bytesize; i++)
{
arr_= Serial.println(buffer*,HEX);_
_}*_
without using serial.
Not going to dig through all your attempts ![]()
I guess you want to store an ascii representation of hexadecimal values. Below code simulates your mrfc522 data, converts it to an ascci representation in a character array 'dest' and prints the result to show that it works ![]()
void setup()
{
Serial.begin(9600);
// simulation of data
byte uidByte[] = {0x04, 0x73, 0xBA, 0x12, 0xB6, 0x2B, 0x80};
byte uidSize = sizeof(uidByte);
// destination array; space for 14 representations of a nibble plus terminating '\0'
char dest[15];
// initialise character array
memset(dest, 0, sizeof(dest));
// test the size of the character array
if((sizeof(dest) - 1) / 2 < uidSize)
{
// display error message
Serial.println("Character buffer too small");
// never continue
for(;;);
}
for (int cnt = 0; cnt < uidSize; cnt++)
{
// convert byte to its ascii representation
sprintf(&dest[cnt * 2], "%02X", uidByte[cnt]);
}
// display
Serial.println(dest);
}
Note that the character array needs to be one larger than the number of nibbles that you have stored in uidByte (to cater for a terminating '\0'); if you don't know in advance, make it big enough. The code will print an error message and stop forever if the size if too small.
The code uses sprintf to do the conversion. It will convert every byte in uidByte in succession and place it in the character array. The representation of the first byte takes 2 locations in the array (positions 0 and 1), the representation of the next byte takes again 2 locations in the array (positions 2 and 3) and so on.
Note:
for demo purpose, the code is implemented in setup().
Great!
That solves it (Thanks! sterretje :)). Did not know that you can use sprintf in arduino.
Can you explain the rationale behind [cnt * 2]?
Each byte equals two nibbles. So you 'sprintf' two chars for every byte.
Thanks again! ![]()
sterretje:
Each byte equals two nibbles. So you 'sprintf' two chars for every byte.
But muzab said the format was: "XX YY ZZ"
Which stated that data consisted of a string where there is a between the ascii characters for the hex values.
While we can assume that the space was just for readability that isn't what muzab said the format was.
Also, it wasn't clear if the data is really a byte array or an array of characters representing the hex values.
muzab, details really matter.
Like I said, how you handle the data will depend on its format and how you wanted it re-formatted before you send it on.
We still are unclear about the format of the original data and what format you want it in before you send it on.
Is the data really a C string or is it just a block of bytes?
The two are VERY different.
Your post #10 seems to treating it as both and confusing them at various points.
i.e.
You said the data format was: "04 73 BA 12 B6 2B 80"
Which shows the data format as being a string of characters representing hex byte values separated by a space between each.
This code is treating the rfid data as a C string.
strcpy(arr, (char*)buffer ); // gives me an ascii value
Is treating the data as ascii characters.
While
for(byte i = 0; i<bytesize; i++)
{
arr= Serial.println(buffer,HEX);
}
Is treating the data as bytes.
Again, the two are VERY different formats, and you can't simply do any sort of cast to get between the two different data formats.
One is an array of data values and the other is an array of characters that represents the data values.
Casting does not do data conversion. It merely treats the existing data slightly differently when doing operations on it or modifications to it.
Consider the 3 different ways the data above was treated and the value of uid.size for each:
So what format is the original data in and what format do you need it be?
--- bill
If you just want to copy from one 8-bit array to another without regard for type then look into
void * memcpy (void *, const void *, size_t)
void * memcpy ( void * dest,
const void * src,
size_t len
)Copy a memory area.
The memcpy() function copies len bytes from memory area src to memory area dest. The memory areas may not overlap. Use memmove() if the memory areas do overlap.
Returns
The memcpy() function returns a pointer to dest.
I know, void pointers?
You can check out a command easier with a test sketch than by inserting it into larger code and trying trying to figure out the bugs after getting the syntax right.
Not a complete answer to the problem, just a demonstration to edit and play around with:
char myChars[] = { "hello" };
byte buffer[ 8 ]; // defaults to all 0's
void setup()
{
Serial.begin( 115200 );
memcpy( (void *)( buffer ), (void *) myChars, 5 );
Serial.println( );
for ( byte i = 0; i < 5; i++ )
{
Serial.print( myChars[ i ] );
Serial.print( F( " converts to " ));
Serial.println( buffer[ i ] );
}
Serial.println( );
}
void loop() {
// put your main code here, to run repeatedly:
}
Reply #11 seems to have solved the problem.
sterretje:
Reply #11 seems to have solved the problem.
So that means that the data is not in the form that you told us.
The original data is not a character array and it is not a character string like this at all: "04 73 BA 12 B6 2B 80"
It sounds like the data is a simple byte array as I suspected in post #9 and what you really wanted to do was to convert the bytes into a character array representing each byte's value with no spaces between each converted value.
That is a very different problem than you had stated and data conversion is not solved through casting.
--- bill
sterretje:
Reply #11 seems to have solved the problem.
All I was trying to do is show another approach to these kind of things.
Forum threads are for all members to be able to get understanding from and my post is pertinent to the OP's issues isn't it?