Arduino Ram/Code Problem

Hi

Im relatively new to programming and arduino. For a summer camp im trying to build a simple time attendance system using the RFID module. Im also using a LCD display, two LED's and a SSD module to save all the data. So far I managed to solve all problems, everything's wired up and workin except that as I wanted to add more RFID cards to my string eventually I ran out of memory. Im hopping to store up to 50 RFID cards with a name attached to it(not on the card itself but theres a list of the UID and the according name. Is there a better way to do it? Maybe using CHAR?

Thanks for your Help!!

Heres my code:

/*
 * Rui Santos 
 * Complete Project Details https://randomnerdtutorials.com
 */

#include <MFRC522.h> // for the RFID
#include <SPI.h> // for the RFID and SD card module
#include <SD.h> // for the SD card
#include <RTClib.h> // for the RTC
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// define pins for RFID
#define CS_RFID 10
#define RST_RFID 9
// define select pin for SD card module
#define CS_SD 4 

// Create a file to store the data
File myFile;

// Instance of the class for RFID
MFRC522 rfid(CS_RFID, RST_RFID); 

// Variable to hold the tag's UID
String uidString;

// Instance of the class for RTC
RTC_DS1307 rtc;

// Define check in time
const int checkInHour = 16;
const int checkInMinute = 5;

//Variable to hold user check in
int userCheckInHour;
int userCheckInMinute;

// Pins for LEDs and buzzer
const int redLED = 6;
const int greenLED = 7;
const int buzzer = 5;

// Rfid definiert Block der gelesen wird


LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display


void setup() {
  
  // Set LEDs and buzzer as outputs
  pinMode(redLED, OUTPUT);  
  pinMode(greenLED, OUTPUT);
  pinMode(buzzer, OUTPUT);
  lcd.init();                      // initialize the lcd 
  lcd.noDisplay();
  
  // Init Serial port
  Serial.begin(9600);
  while(!Serial); // for Leonardo/Micro/Zero
  
  // Init SPI bus
  SPI.begin(); 
  // Init MFRC522 
  rfid.PCD_Init(); 

  // Setup for the SD card
  Serial.print("Initializing SD card...");
  if(!SD.begin(CS_SD)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // Setup for the RTC  
  if(!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while(1);
  }
  if(!rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  }
}


void loop() {
  //look for new cards
  if(rfid.PICC_IsNewCardPresent()) {
    readRFID();
    logCard();
    verifyCheckIn();
  }
  delay(10);
}

void readRFID() {
  rfid.PICC_ReadCardSerial();
  Serial.print("Tag UID: ");
  uidString = String(rfid.uid.uidByte[0]) + " " + String(rfid.uid.uidByte[1]) + " " + 
    String(rfid.uid.uidByte[2]) + " " + String(rfid.uid.uidByte[3]);
  Serial.println(uidString);
 
  // Sound the buzzer when a card is read
  tone(buzzer, 2000); 
  delay(100);        
  noTone(buzzer);
  
  delay(100);
}

void logCard() {
  String names[] =  { "Aaron", "Remy", "Twintzeps", "Armin", "Ilo", "Bolt", "Jamie", "Topo", "Floss"};
  String tagliste[] = { "129 129 135 50", "113 251 237 50",  "113 203 107 50",  "129 180 235 50",  "99 225 157 52",  "99 215 242 52",  "99 180 92 52",  "99 227 167 52",  "83 249 207 52"};
  // Enables SD card chip select pin
  digitalWrite(CS_SD,LOW);
  
  // Open file
  myFile=SD.open("DATA.txt", FILE_WRITE);

  // If the file opened ok, write to it
  if (myFile) {
    Serial.println("File opened ok");
    myFile.print(uidString);
    myFile.print(", "); 
    for(int x = 0; x < 50; x++) {
      if (uidString == tagliste[x]) {
        myFile.print(names[x]);
      }
    }
    myFile.print(", ");   
    
    // Save time on SD card
    DateTime now = rtc.now();
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(',');
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.println(now.minute(), DEC);
    
    // Print time on Serial monitor
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.println(now.minute(), DEC);
    Serial.println("sucessfully written on SD card");
    myFile.close();
    

    // Print time on lcd display
    lcd.backlight();
    lcd.display();
    lcd.print(now.year(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.day(), DEC);
    lcd.print(' ');
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.println(now.minute(), DEC);
    lcd.setCursor(2,1);
    for(int x = 0; x < 50; x++) {
      if (uidString == tagliste[x]) {
        lcd.print(names[x]);
      }
    }
    delay(1000);
    lcd.clear();
    
    // Save check in time;
    userCheckInHour = now.hour();
    userCheckInMinute = now.minute();
  }
  else {
    Serial.println("error opening data.txt");  
  }
  // Disables SD card chip select pin  
  digitalWrite(CS_SD,HIGH);
}

void verifyCheckIn(){
  if((userCheckInHour < checkInHour)||((userCheckInHour==checkInHour) && (userCheckInMinute <= checkInMinute))){
    digitalWrite(greenLED, HIGH);
    Serial.println("Wilkomme am Deck!!!");
    lcd.println("Wilkomme am Deck!!!");
    delay(1000);
    digitalWrite(greenLED,LOW);
    lcd.clear();
    lcd.noDisplay();
    lcd.noBacklight();
  }
  else{
    digitalWrite(redLED, HIGH);
    Serial.println("Du bisch z spat...");
    lcd.println("Du bisch z spat...");
    delay(1000);
    digitalWrite(redLED,LOW);
    lcd.clear();
    lcd.noDisplay();
    lcd.noBacklight();
  }
}

Getting rid of Strings would be good. There are plenty of places to use the F macro too e.g.
this:

 Serial.print("Initializing SD card...");

Could be

 Serial.print(F("Initializing SD card..."));

Which leaves the text in progmem.

Thanks for the tip!

using the F Macro i managed to put in more names but the problem remains.

Could you give me an example of how to get rid of the strings?

char *name[] =  { "Aaron", "Remy", "Twintzeps", "Armin", "Ilo", "B......

seems to use even more space

is there a way to get strings into progmem?

Why even store an array of names?

If you are storing on SD card, why not have files for each person by name or RFID, inside the file it would have the RFID you are checking or Name. This would allow you to expand the system considerably.

Sounds like a good idea!!!
would it be possible to have a txt file with the names and one with the uid?
or do i need to have 50 txt files with the uid as filename and inside the file the name of the person?

michagerhard:
Sounds like a good idea!!!
would it be possible to have a txt file with the names and one with the uid?
or do i need to have 50 txt files with the uid as filename and inside the file the name of the person?

you can use 1 character delimited file to store all data. it's like an Excel spreadsheet, but for rows and columns, one character (comma is common or tab (the character) seperates columns in a row, and one character (new line/line feed/carriage return/pipe/brace etc.) seperates the rows.

michagerhard:
Sounds like a good idea!!!
would it be possible to have a txt file with the names and one with the uid?
or do i need to have 50 txt files with the uid as filename and inside the file the name of the person?

The only issue I see with this....

If it is stored on one file, you have to read the contents of the file each time, find the match and perform logic. This could be a performance issue, my suggestion removes that possible performance issue.

If they are each in a different file, you simply check if the file exists, if it does open and do what you need.

As far as your storage of the collected data, yes you can still put that in your output file.

My suggestion, was how to NOT have all that in memory.

Romonaga:
The only issue I see with this....

If it is stored on one file, you have to read the contents of the file each time, find the match and perform logic. This could be a performance issue, my suggestion removes that possible performance issue.

If they are each in a different file, you simply check if the file exists, if it does open and do what you need.

As far as your storage of the collected data, yes you can still put that in your output file.

My suggestion, was how to NOT have all that in memory.

Yea I went for your approach, and I dont mind having multiple files.

How do I oppen the according file?

myFile2=SD.open("uidString.txt", FILE_WRITE);

uidString is the UID I get from the RFID reader

Romonaga:
The only issue I see with this....

If it is stored on one file, you have to read the contents of the file each time, find the match and perform logic. This could be a performance issue, my suggestion removes that possible performance issue.

There's not going to be a performance issue. the SPI bus can open the read, log, display etc. faster than the humans can shuffle RFID tags to the RFID reader.

Perehama:
There's not going to be a performance issue. the SPI bus can open the read, log, display etc. faster than the humans can shuffle RFID tags to the RFID reader.

The performance issue I am speaking of is the opening the file each time, reading each line, determining if this is the record you want. You are correct, this might not be a big issue with a few names.

Romonaga:
The performance issue I am speaking of is the opening the file each time, reading each line, determining if this is the record you want. You are correct, this might not be a big issue with a few names.

Surely there's enough Progmem to store 50 row numbers and RFIDs... Then just parse through the rows by the delimiter rowNum times. Alternatively, each record can have a fixed width, making jumping to the data you want simple pointer addition.

Perehama:
Surely there's enough Progmem to store 50 row numbers and RFIDs... Then just parse through the rows by the delimiter rowNum times. Alternatively, each record can have a fixed width, making jumping to the data you want simple pointer addition.

Could be, I am not trying to be combative, I have been programming for well over 30 years now. When I started programming we always took performance into consideration, as well as not shoehorn ourself into a wall.

Also, I will state that I never used a SD card in any of my projects as such, I do not know the performance of these devices. Hmmm, I have one of these, might have to play with it.

Romonaga:
The only issue I see with this....

If it is stored on one file, you have to read the contents of the file each time, find the match and perform logic. This could be a performance issue, my suggestion removes that possible performance issue.

If they are each in a different file, you simply check if the file exists, if it does open and do what you need.

As far as your storage of the collected data, yes you can still put that in your output file.

My suggestion, was how to NOT have all that in memory.

michagerhard:
Yea I went for your approach, and I dont mind having multiple files.

How do I oppen the according file?

myFile2=SD.open("uidString.txt", FILE_WRITE);

uidString is the UID I get from the RFID reader

You will need to create the filename on the fly. Once you get the UUID you need to take it, concatinate the .txt to it, and pass that string to the SD.open. I do not know what the uuids look like, I also do not know if the sd lib allows spaces. So you might have to remove spaces and create a file name.

Example UUID 129 129 135 50

File name should look like this once done. Again, if the library support spaces in names than this is not an issue and you will not need to do this step.

So at the end of the day, the filename you create should look like one of these. I suspect that it will not allow spaces in the name.

12912913550.txt
129 129 135 50.txt

Romonaga:
You will need to create the filename on the fly. Once you get the UUID you need to take it, concatinate the .txt to it, and pass that string to the SD.open. I do not know what the uuids look like, I also do not know if the sd lib allows spaces. So you might have to remove spaces and create a file name.

Example UUID 129 129 135 50

File name should look like this once done. Again, if the library support spaces in names than this is not an issue and you will not need to do this step.

So at the end of the day, the filename you create should look like one of these. I suspect that it will not allow spaces in the name.

12912913550.txt
129 129 135 50.txt

I found out that the sd card library only supports 8.3 characters so that won't be possible. Im now trying to have only one file with: "UID, Name of Person" on each line. so far I didnt find any useful information on how to compare the UID that I get from the RFID reader to this file. If the UID which the RFID reader reads matches with one in the list then i want the corresponding name to be displayed and saved in my log file.

michagerhard:
I found out that the sd card library only supports 8.3 characters so that won't be possible. Im now trying to have only one file with: "UID, Name of Person" on each line. so far I didnt find any useful information on how to compare the UID that I get from the RFID reader to this file. If the UID which the RFID reader reads matches with one in the list then i want the corresponding name to be displayed and saved in my log file.

That filename limitation is so 1980's.

So after all, you will need to go to a single file.

A CSV file would be best, this is a file where the fields are delimited normally with a comma.

You should be able to read a line, parse the fields by the comma.

Here is some untested sudo code that I hope will help you.

string in this snippit is the string you read from the SD card.

   char* ptr = strtok(string, ",");

    while(ptr != NULL) 
   {
        printf("found one part: %s\n", ptr);
        // create next part
        ptr = strtok(NULL, delimiter);
    }

michagerhard:
I found out that the sd card library only supports 8.3 characters so that won't be possible. Im now trying to have only one file with: "UID, Name of Person" on each line. so far I didnt find any useful information on how to compare the UID that I get from the RFID reader to this file. If the UID which the RFID reader reads matches with one in the list then i want the corresponding name to be displayed and saved in my log file.

That filename limitation is so 1980's.

So after all, you will need to go to a single file.

A CSV file would be best, this is a file where the fields are delimited normally with a comma.

You should be able to read a line, parse the fields by the comma.

Here is some untested sudo code that I hope will help you.

char* ptr = strtok(string, delimiter);

    while(ptr != NULL) {
        printf("found one part: %s\n", ptr);
        // create next part
        ptr = strtok(NULL, delimiter);
    }

If you decide to store the data in PROGMEM instead of on the SD card, here is an example of how it can be done. Storing arrays of character arrays in PROGMEM can get a bit confusing, the character array has to be stored first, then the pointer to the character array is stored in the second array.

Note that I've stored the RFID number as four byte values, since in your program the data from the rfid reader appears to be in bytes, storing it as the string representation is a waste of memory.

//names are stores in individual character arrays
const char name_Aaron[] PROGMEM = "Aaron";
const char name_Remy[] PROGMEM = "Remy";
const char name_Twintzeps[] PROGMEM = "Twintzeps";
const char name_Armin[] PROGMEM = "Armin";
const char name_Ilo[] PROGMEM = "Ilo";
const char name_Bolt[] PROGMEM = "Bolt";
const char name_Jamie[] PROGMEM = "Jamie";
const char name_Topo[] PROGMEM = "Topo";
const char name_Floss[] PROGMEM = "Floss";

//definition of structure to hold tagliste and corresponding name
struct tag_and_name {
  byte tagliste[4];
  const char * name;
};

//table that contains actual rfid tag number and pointer to the corrresponding name
const tag_and_name tag_and_name_table[] PROGMEM = {
  {{129, 129, 135, 50}, name_Aaron},
  {{113, 251, 237, 50}, name_Remy},
  {{113, 203, 107, 50},  name_Twintzeps},
  {{129, 180, 235, 50}, name_Armin},
  {{99, 225, 157, 52}, name_Ilo},
  {{99, 215, 242, 52}, name_Bolt},
  {{99, 180, 92, 52}, name_Jamie},
  {{99, 227, 167, 52}, name_Topo},
  {{83, 249, 207, 52}, name_Floss}
};

//calculate size of table, so you can add/remove table entries without having to alter additional code 
const byte table_size = sizeof(tag_and_name_table) / sizeof(tag_and_name_table[0]);

//temporary buffers to copy data from PROGMEM to ram
tag_and_name tag_and_name_buffer; //storage for table entry
char name_buffer[10]; //storage for name - length of longest name + 1
char tagliste_buffer[16]; //storage for character representation of rfid number

void setup() {
  Serial.begin(115200);
  Serial.println(F("startup"));
}

void loop() {
  for (byte i = 0; i < table_size; i++) {
    Serial.print(i);
    Serial.print(F(": "));

    //the following line copies the table entry from PROGMEM into ram
    memcpy_P(&tag_and_name_buffer, &tag_and_name_table[i], sizeof(tag_and_name_buffer));

    //the following line copies the name from PROGMEM into ram
    strcpy_P(name_buffer, tag_and_name_buffer.name);

    //the following line converts the rfid number from bytes to a character array
    sprintf(tagliste_buffer, "%d %d %d %d",
            tag_and_name_buffer.tagliste[0],
            tag_and_name_buffer.tagliste[1],
            tag_and_name_buffer.tagliste[2],
            tag_and_name_buffer.tagliste[3]);

    Serial.print(tagliste_buffer); //print the rfid number
    Serial.print(F(" "));
    Serial.print(name_buffer); //print the name
    Serial.println();
  }
  while (true); //stop sketch so data is only printed once
}

Thank you guys for the help!! Both approaches seem to be reasonable :slight_smile: I will test these methods as soon as I get home.

Alright I'm back from my weekend trip. I went for the Pogmem solution because it seamed easyer. So far it I managed to add it to my code and theres no Problem with the space of my arduino. When I run the code however it prints the whole list and not just the name corresponding with the tag I read on the RFID reader... could you please help me? heres my new code:

#include <MFRC522.h> // for the RFID
#include <SPI.h> // for the RFID and SD card module
#include <SD.h> // for the SD card
#include <RTClib.h> // for the RTC
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// define pins for RFID
#define CS_RFID 10
#define RST_RFID 9
// define select pin for SD card module
#define CS_SD 4 

// Create a file to store the data
File myFile;

// Instance of the class for RFID
MFRC522 rfid(CS_RFID, RST_RFID); 

// Variable to hold the tag's UID
String uidString;

// Instance of the class for RTC
RTC_DS1307 rtc;

// Define check in time
const int checkInHour = 16;
const int checkInMinute = 5;

//Variable to hold user check in
int userCheckInHour;
int userCheckInMinute;

// Pins for LEDs and buzzer
const int redLED = 6;
const int greenLED = 7;
const int buzzer = 5;

//names are stores in individual character arrays
const char name_Aaron[] PROGMEM = "Aaron";
const char name_Remy[] PROGMEM = "Remy";
const char name_Twintzeps[] PROGMEM = "Twintzeps";
const char name_Armin[] PROGMEM = "Armin";
const char name_Ilo[] PROGMEM = "Ilo";
const char name_Bolt[] PROGMEM = "Bolt";
const char name_Jamie[] PROGMEM = "Jamie";
const char name_Topo[] PROGMEM = "Topo";
const char name_Floss[] PROGMEM = "Floss";

//definition of structure to hold tagliste and corresponding name
struct tag_and_name {
  byte tagliste[4];
  const char * name;
};

//table that contains actual rfid tag number and pointer to the corrresponding name
const tag_and_name tag_and_name_table[] PROGMEM = {
  {{129, 129, 135, 50}, name_Aaron},
  {{113, 251, 237, 50}, name_Remy},
  {{113, 203, 107, 50},  name_Twintzeps},
  {{129, 180, 235, 50}, name_Armin},
  {{99, 225, 157, 52}, name_Ilo},
  {{99, 215, 242, 52}, name_Bolt},
  {{99, 180, 92, 52}, name_Jamie},
  {{99, 227, 167, 52}, name_Topo},
  {{83, 249, 207, 52}, name_Floss}
};

//calculate size of table, so you can add/remove table entries without having to alter additional code 
const byte table_size = sizeof(tag_and_name_table) / sizeof(tag_and_name_table[0]);

//temporary buffers to copy data from PROGMEM to ram
tag_and_name tag_and_name_buffer; //storage for table entry
char name_buffer[10]; //storage for name - length of longest name + 1
char tagliste_buffer[16]; //storage for character representation of rfid number

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display


void setup() {
  
  // Set LEDs and buzzer as outputs
  pinMode(redLED, OUTPUT);  
  pinMode(greenLED, OUTPUT);
  pinMode(buzzer, OUTPUT);
  lcd.init();                      // initialize the lcd 
  lcd.noDisplay();
  
  // Init Serial port
  Serial.begin(9600);
  Serial.println(F("startup"));
  while(!Serial); // for Leonardo/Micro/Zero
  
  // Init SPI bus
  SPI.begin(); 
  // Init MFRC522 
  rfid.PCD_Init(); 

  // Setup for the SD card
  Serial.print(F("Initializing SD card..."));
  if(!SD.begin(CS_SD)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));

  // Setup for the RTC  
  if(!rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    while(1);
  }
  if(!rtc.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
  }
}


void loop() {
  //look for new cards
  if(rfid.PICC_IsNewCardPresent()) {
    readRFID();
    logCard();
    verifyCheckIn();
  }
  delay(10);
}

void readRFID() {
  rfid.PICC_ReadCardSerial();
  Serial.print("Tag UID: ");
  uidString = String(rfid.uid.uidByte[0]) + " " + String(rfid.uid.uidByte[1]) + " " + 
    String(rfid.uid.uidByte[2]) + " " + String(rfid.uid.uidByte[3]);
  Serial.println(uidString);
 
  // Sound the buzzer when a card is read
  tone(buzzer, 2000); 
  delay(100);        
  noTone(buzzer);
  
  delay(100);
}

void logCard() {
  // Enables SD card chip select pin
  digitalWrite(CS_SD,LOW);
  
  // Open file
  myFile=SD.open("DATA.txt", FILE_WRITE);

  // If the file opened ok, write to it
  if (myFile) {
    Serial.println("File opened ok");
    for (byte i = 0; i < table_size; i++) {
      Serial.print(i);
      Serial.print(F(": "));

      //the following line copies the table entry from PROGMEM into ram
      memcpy_P(&tag_and_name_buffer, &tag_and_name_table[i], sizeof(tag_and_name_buffer));

      //the following line copies the name from PROGMEM into ram
      strcpy_P(name_buffer, tag_and_name_buffer.name);

      //the following line converts the rfid number from bytes to a character array
      sprintf(tagliste_buffer, "%d %d %d %d",
              tag_and_name_buffer.tagliste[0],
              tag_and_name_buffer.tagliste[1],
              tag_and_name_buffer.tagliste[2],
              tag_and_name_buffer.tagliste[3]);

      Serial.print(tagliste_buffer); //print the rfid number
      Serial.print(F(" "));
      Serial.print(name_buffer); //print the name
      Serial.println();
    }
    
    myFile.print(name_buffer);
    
    // Save time on SD card
    DateTime now = rtc.now();
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(',');
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.println(now.minute(), DEC);
    
    // Print time on Serial monitor
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.println(now.minute(), DEC);
    Serial.println("sucessfully written on SD card");
    myFile.close();
    

    // Print time on lcd display
    lcd.backlight();
    lcd.display();
    lcd.print(now.year(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.day(), DEC);
    lcd.print(' ');
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.println(now.minute(), DEC);
    lcd.setCursor(2,1);
    lcd.print(name_buffer);
    myFile.close();
    delay(1000);
    lcd.clear();
    
    // Save check in time;
    userCheckInHour = now.hour();
    userCheckInMinute = now.minute();
  }
  else {
    Serial.println("error opening data.txt");  
  }
  while (true); //stop sketch so data is only printed once
  // Disables SD card chip select pin  
  digitalWrite(CS_SD,HIGH);
}

void verifyCheckIn(){
  if((userCheckInHour < checkInHour)||((userCheckInHour==checkInHour) && (userCheckInMinute <= checkInMinute))){
    digitalWrite(greenLED, HIGH);
    Serial.println("Wilkomme am Deck!!!");
    lcd.println("Wilkomme am Deck!!!");
    delay(1000);
    digitalWrite(greenLED,LOW);
    lcd.clear();
    lcd.noDisplay();
    lcd.noBacklight();
  }
  else{
    digitalWrite(redLED, HIGH);
    Serial.println("Du bisch z spat...");
    lcd.println("Du bisch z spat...");
    delay(1000);
    digitalWrite(redLED,LOW);
    lcd.clear();
    lcd.noDisplay();
    lcd.noBacklight();
  }
}

and heres what the serial monitor prints:

startup
Initializing SD card...initialization done.
Tag UID: 113 251 237 50
File opened ok
0: 129 129 135 50 Aaron
1: 113 251 237 50 Remy
2: 113 203 107 50 Twintzeps
3: 129 180 235 50 Armin
4: 99 225 157 52 Ilo
5: 99 215 242 52 Bolt
6: 99 180 92 52 Jamie
7: 99 227 167 52 Topo
8: 83 249 207 52 Floss
2019/6/23 22:57
sucessfully written on SD card

Romonaga:
That filename limitation is so 1980's.

...when processors only had tiny amounts of RAM.

Oh. Wait.