Cannot understand the code

Hello,

I am quite new to Arduino and trying to play with RFID. I copied/pasted and amended a code that I found with one of the project and cannot understand two items in the output:
1 - Why “John” is shown in a new line?
2 - Why there are question marks at the end of the second dump?

I spent quite a few hours trying to understand that but with no avail. Please help me as this is driving me crazy
Thank you in advance to anyone who is willing to sacrifice som time to it.

Write personal data on a MIFARE PICC
Card UID:7C9BDAC3 PICC type: MIFARE 1KB
Type Family name, ending with #
PCD_Authenticate() success:
Alphanumeric representation1: Smith
Smith
MIFARE_Write() success:
Data in block 1:
53 6D 69 74 68 0A 53 6D 69 74 68 20 20 20 20 20

Type First name, ending with #
PCD_Authenticate() success:
Alphanumeric representation2:
John
MIFARE_Write() success:
Data in block 4:
0A 4A 6F 68 6E 20 20 20 20 20 20 20 20 20 20 20⸮⸮⸮⸮
⸮⸮⸮⸮

Here is the full code:

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
void setup() {
  Serial.begin(9600);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card
  Serial.println(F("Write personal data on a MIFARE PICC "));
}

void loop() {

  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) return;

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) return;

  Serial.print(F("Card UID:"));    //Dump UID
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    Serial.print(mfrc522.uid.uidByte[i], HEX);
  }
  Serial.print(F(" PICC type: "));   // Dump PICC type
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));

  byte buffer[34];
  byte block;
  MFRC522::StatusCode status;
  byte size = sizeof(buffer);

  byte len;
  Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
  // Ask personal data: Family name
  Serial.println(F("Type Family name, ending with #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
  for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces
  

  block = 1;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("PCD_Authenticate() success: "));

  // Write block
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  Serial.print(F("Alphanumeric representation1: "));                 //Alphanumeric Translation
  for (byte i = 0; i < 30; i++) Serial.write(lowByte(buffer[i]));   //Alphanumeric Translation
  Serial.println();                                                 //Alphanumeric Translation
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));


  Serial.print(F("Data in block ")); Serial.print(block); Serial.println(F(":"));
  dump_byte_array(buffer, 16); 


  // Ask personal data: First name
  Serial.println(F("Type First name, ending with #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read first name from serial
  for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces

  block = 4;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("PCD_Authenticate() success: "));
  
  // Write block
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  Serial.print(F("Alphanumeric representation2: "));                  //Alphanumeric Translation
  for (byte i = 0; i < 30; i++) Serial.write(lowByte(buffer[i]));     //Alphanumeric Translation
  Serial.println();                                                   //Alphanumeric Translation
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
    else Serial.println(F("MIFARE_Write() success: "));
    
  Serial.print(F("Data in block ")); Serial.print(block); Serial.println(F(":"));
  dump_byte_array(buffer, 16);

  mfrc522.PICC_HaltA(); // Halt PICC
  mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD

}
void dump_byte_array(byte *buffer, byte bufferSize) 
{
  int i,j;
  char bytearray[bufferSize];
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
  
 strcpy((char*)bytearray , *buffer);
String myString[bufferSize] = String((char *)bytearray);

for(j=0;j<=1;j++)
{
Serial.println(myString[i]);
if(myString[i]==16)
break;
}
}
  byte buffer[34];

  for (byte i = 0; i < 30; i++) Serial.write(lowByte(buffer[i]));

It is hardly necessary to extract the low order byte from a variable that is a single byte wide.

1 - Why "John" is shown in a new line?

You are sending serial data to the Arduino. If you are using the Serial Monitor application to do that, you have some line ending setting that you did not disclose.

I’m going to guess, though, that it is set to line feed/carriage return. You stop reading the last name when the # in the string arrives, leaving the line feed and carriage return in serial buffer. Then, when you read the first name you get the line feed, carriage return, and the user input. So, when you print the first name, the first character of the first name is a line feed. The second is a carriage return. The third character is the ‘J’. You see it appear where it does because of the non-printable characters in the array that holds the first name.

 strcpy((char*)bytearray , *buffer);

Rubbish. The second argument is the address of the array to copy from. That address is buffer, NOT *buffer.

2 - Why there are question marks at the end of the second dump?

That crap code above is one possibility. Another is that you don’t bother printing anything after the array dump, so you have no real idea what print()/write() call produced that output, so it is quite likely that it is NOT part of the second dump.

Hello PaulS,
Thank you for the reply.

I tried the code applying your insights and this is what I got:
re 1. I did not notice any difference with or without low order byte - got rid of it
re 2. "John" in a new line - It is a tricky one because exactly the same code was used previously with "Smith" and "Smith" was printed in the same line. So line editing setting should affect both of them and they not. Still trying to figure that out.
re 3. I am not quite sure what I am saying here but would '' before buffer indicate the pointer? I tried to run it without the '' and there were two outcomes: 1 the code would run continuously and the datadump would not produce data from the block. I would appreciate any pointers on this one.
re 4. I managed to found out the source of question marks. It was the variable 'myString' that was printed at the end of the "dump_byte_array". The issue is that I am not sure what these lines producing value in 'myString' were supposed to accomplish. Any ideas would be greatly appreciated.

Thank you for all your help,
Robert

re 2. “John” in a new line - It is a tricky one because exactly the same code was used previously with “Smith” and “Smith” was printed in the same line. So line editing setting should affect both of them and they not. Still trying to figure that out.

You print two prompts. You enter “Smith#” and press send. If the line ending is set to cr/lf, you actually send “Smith#”.

You read up to the ‘#’, leaving “” in the buffer.

Then, you enter “John#” and the Serial Monitor sends “John#”, resulting in the buffer containing “John#”. You read up to the ‘#’, making the first name “John”.

The solution is to set the line ending to none, in the Serial Monitor app.

re 3. I am not quite sure what I am saying here but would ‘*’ before buffer indicate the pointer?

*buffer means to treat the value as a pointer. It means that buffer CONTAINS an address, not IS an address. The strcpy() function wants an address, not the address of an address.

strcpy(bytearray , buffer);

is the proper way to use strcpy() to copy the data in the array called buffer to the array called (uselessly) bytearray.

You don’t tag “scalarvariable” onto the end of scalar variables, so tagging “array” onto the end of arrays is unnecessary.

bytearray is also a dumb name because the type of the array is NOT byte. it is char (array), so the cast was unnecessary.

re 4. I managed to found out the source of question marks. It was the variable ‘myString’ that was printed at the end of the “dump_byte_array”. The issue is that I am not sure what these lines producing value in ‘myString’ were supposed to accomplish.

myString is actually an array of resource-wasting String objects. The array can hold 16 elements, but only actually holds one.

The loop to iterate once was useless. Comparing a String to 16 makes no sense. Constructing a String of an address (what the cast produces) is pointless.

Creating a local String object (or array) to hold a string is pointless, since the local object (or array) goes out of scope after being printed. Just print the string.