diff --git a/.build/build.options.json b/.build/build.options.json
new file mode 100644
index 0000000000000000000000000000000000000000..f213921ea7bd753452aa74a75cd6ff29cf8820aa
--- /dev/null
+++ b/.build/build.options.json
@@ -0,0 +1,12 @@
+{
+  "additionalFiles": "..,..",
+  "builtInLibrariesFolders": "/Applications/Arduino.app/Contents/Java/libraries",
+  "builtInToolsFolders": "/Applications/Arduino.app/Contents/Java/tools-builder,/Applications/Arduino.app/Contents/Java/hardware/tools/avr,/Users/to/Library/Arduino15/packages",
+  "compiler.optimization_flags": "",
+  "customBuildProperties": "build.path=/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build,build.warn_data_percentage=75,runtime.tools.arduinoOTA.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.arduinoOTA-1.3.0.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.avr-gcc.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avrdude.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17,runtime.tools.avrdude-6.3.0-arduino17.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17",
+  "fqbn": "arduino:avr:mega:cpu=atmega2560",
+  "hardwareFolders": "/Applications/Arduino.app/Contents/Java/hardware,/Users/to/Library/Arduino15/packages",
+  "otherLibrariesFolders": "/Users/to/sciebo/TT_Arduino/libraries",
+  "runtime.ide.version": "10819",
+  "sketchLocation": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino"
+}
\ No newline at end of file
diff --git a/.build/core/core.a b/.build/core/core.a
new file mode 100644
index 0000000000000000000000000000000000000000..99c9279bdecf1eb3ad99f7f5311871bc732536b1
Binary files /dev/null and b/.build/core/core.a differ
diff --git a/.build/includes.cache b/.build/includes.cache
new file mode 100644
index 0000000000000000000000000000000000000000..4b6f9d106d58bc17206fc08fa4719dafc4abee8b
--- /dev/null
+++ b/.build/includes.cache
@@ -0,0 +1,77 @@
+[
+  {
+    "Sourcefile": null,
+    "Include": "",
+    "Includepath": "/Users/to/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino"
+  },
+  {
+    "Sourcefile": null,
+    "Include": "",
+    "Includepath": "/Users/to/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/mega"
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build/sketch/serialTable.ino.cpp",
+    "Include": "AUnit.h",
+    "Includepath": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src"
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build/sketch/serialTable.ino.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/Assertion.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/Compare.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/FCString.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/MetaAssertion.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/Printer.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/Test.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/TestAgain.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/TestOnce.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/TestRunner.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/print64.cpp",
+    "Include": "",
+    "Includepath": null
+  },
+  {
+    "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src/aunit/string_util.cpp",
+    "Include": "",
+    "Includepath": null
+  }
+]
\ No newline at end of file
diff --git a/.build/preproc/ctags_target_for_gcc_minus_e.cpp b/.build/preproc/ctags_target_for_gcc_minus_e.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..924d9e23a4649a66c587fc5ab346018e605291bc
--- /dev/null
+++ b/.build/preproc/ctags_target_for_gcc_minus_e.cpp
@@ -0,0 +1,53 @@
+# 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino"
+# 2 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2
+# 3 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2
+# 4 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2
+
+void setup()
+{
+    // Initialisieren der seriellen Verbindung
+    Serial.begin(115200);
+
+        // Definieren der Kopfzeilen und Spaltenbreiten für 8 Spalten
+        const char *headers[] = {"Vorname", "Nachname", "Alter", "Stadt", "Beruf", "Unternehmen", "Hobby", "Bemerkung"};
+        int columnWidths[] = {10, 15, 5, 10, 10, 15, 10, 20};
+
+        SerialTable table(headers, columnWidths, 8);
+        table.printHeader();
+
+        // Erstellen von 20 Zeilen mit unterschiedlichen Einträgen
+        char *rows[20][8] = {
+            {"Alice", "Wonderland", "30", "Köln", "Ingenieur", "FirmaX", "Schwimmen", "Keine"},
+            {"Bob", "Builder\nJr", "35", "Berlin", "Architekt", "Architektur AG", "Bauen", "Sehr erfahren"},
+            {"Charlie", "Brown", "28", "Hamburg", "Designer", "Die Design", "Zeichnen", "Mag Karikaturen"},
+            {"David", "Tennant", "40", "München", "Schauspieler", "Freiberufler", "Lesen", "Doktor gewesen"},
+            {"Emma", "Watson", "33", "Frankfurt", "Schauspielerin", "Independent", "Yoga", "Bekannt aus Filmen"},
+            {"Frank", "Herbert", "45", "Stuttgart", "Autor", "Ein Verlag", "Schreiben", "Bücher geschrieben"},
+            {"Grace", "Hopper", "50", "Berlin", "Programmiererin", "Tech Corp", "Informatik", "Pionierin"},
+            {"Hugo", "Strange", "60", "Leipzig", "Psychiater", "Gesundheits GmbH", "Philosophie", "Ruhestand"},
+            {"Irene", "Adler", "29", "Dresden", "Detektivin", "Privat", "Abenteuer", "Scharfsinnig"},
+            {"John", "Doe", "49", "Bremen", "Buchhalter", "Kontorechner", "Radfahren", "Gewissenhaft"},
+            {"Klara", "Kühn", "39", "Hannover", "Lehrerin", "Schule ABC", "Lesen", "Einfühlsam"},
+            {"Lenny", "Small", "25", "Koblenz", "Musiker", "Orchester", "Gitarre", "Kreativ"},
+            {"Mona", "Lisa", "33", "Siegen", "Malerin", "Kunsthaus", "Kunst", "Geheimnisvoll"},
+            {"Nina", "Simone", "30", "Essen", "Sängerin", "Soul Musik", "Musik", "Talentiert"},
+            {"Oliver", "Twist", "19", "Potsdam", "Student", "Uni XY", "Fußball", "Engagiert"},
+            {"Pam", "Beesly", "32", "Wuppertal", "Sekretärin", "Dunder Mifflin", "Malen", "Freundlich"},
+            {"Quinn", "Fabray", "26", "Magdeburg", "Designer", "Agentur XYZ", "Tanzen", "Kreativ"},
+            {"Ron", "Swanson", "55", "Bielefeld", "Verwalter", "Rathaus", "Holzarbeiten", "Direkt"},
+            {"Sophia", "Loren", "70", "Osnabrück", "Schauspielerin", "Independent", "Kochen", "Ikonisch"},
+            {"Tom", "Hanson", "36", "Regensburg", "Polizist", "Polizei", "Jagen", "Schützend"},
+        };
+
+        // Drucke die Zeilen
+        for (int i = 0; i < 20; ++i)
+        {
+            table.printRow(rows[i]);
+        }
+
+}
+
+void loop()
+{
+    //TestRunner::run();
+}
diff --git a/.build/sketch/SerialTable.h b/.build/sketch/SerialTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..49057b62133c114faeb28f6d41379d1b99dac93e
--- /dev/null
+++ b/.build/sketch/SerialTable.h
@@ -0,0 +1,354 @@
+#line 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/SerialTable.h"
+#ifndef SERIALTABLE_H
+#define SERIALTABLE_H
+
+#include <Arduino.h>
+
+class SerialTable
+{
+public:
+    SerialTable(const char *headers[], const int columnWidths[], size_t size)
+        : headers(headers), columnWidths(columnWidths), size(size) {}
+
+    // Diese Methode gibt den Header an die serielle Schnittstelle aus
+    void printHeader()
+    {
+        String header = buildHeader();
+        Serial.print(header);
+    }
+
+    String buildHeader()
+    {
+        return buildLine('-') + buildRow(const_cast<char **>(headers), '='); // Kopfzeile mit '='
+    }
+
+    void printRow(char **t_row)
+    {
+        String row = buildRow(t_row);
+        Serial.print(row);
+    }
+
+    String buildRow(char **t_row, char line = '-')
+    {
+        String output;
+        char buffer[256];
+        int maxLines = 1; // Maximale Anzahl Zeilen über alle Spalten
+
+        // Erste Phase: Teile jede Zelle in Zeilen und finde maximale Zeilenzahl
+        for (size_t i = 0; i < size; ++i)
+        {
+            if (truncateText)
+            {
+                truncateToColumnWidth(t_row[i], columnWidths[i], buffer);
+            }
+            else
+            {
+                splitStringByLength(t_row[i], columnWidths[i], buffer);
+            }
+
+            // Zähle Zeilen in dieser Zelle
+            int lineCount = 1;
+            for (size_t j = 0; j < displayLength(buffer); j++)
+            {
+                if (buffer[j] == '\n')
+                    lineCount++;
+            }
+            if (lineCount > maxLines)
+                maxLines = lineCount;
+        }
+
+        // Zweite Phase: Baue die Zeilen auf
+        for (int line = 0; line < maxLines; line++)
+        {
+            output += "|";
+
+            // Gehe durch jede Spalte
+            for (size_t col = 0; col < size; ++col)
+            {
+                if (truncateText)
+                {
+                    truncateToColumnWidth(t_row[col], columnWidths[col], buffer);
+                }
+                else
+                {
+                    splitStringByLength(t_row[col], columnWidths[col], buffer);
+                }
+
+                // Finde die aktuelle Zeile für diese Spalte
+                char *currentLine = buffer;
+                int currentLineNum = 0;
+                char tempBuffer[256] = "";
+
+                while (currentLineNum < line)
+                {
+                    char *newline = strchr(currentLine, '\n');
+                    if (newline == NULL)
+                    {
+                        currentLine = "";
+                        break;
+                    }
+                    currentLine = newline + 1;
+                    currentLineNum++;
+                }
+
+                // Extrahiere die Zeile bis zum nächsten \n oder Ende
+                int j = 0;
+                while (currentLine[j] && currentLine[j] != '\n')
+                {
+                    tempBuffer[j] = currentLine[j];
+                    j++;
+                }
+                tempBuffer[j] = '\0';
+
+                // Berechne die tatsächliche Anzeigelänge
+                int printedLength = displayLength(tempBuffer);
+
+                // Füge den Inhalt und die fehlenden Leerzeichen hinzu
+                output += tempBuffer;
+                int spacesToAdd = columnWidths[col] - printedLength;
+                for (int k = 0; k < spacesToAdd; k++)
+                {
+                    output += " ";
+                }
+                output += "|";
+            }
+            output += "\n";
+        }
+
+        // Füge die Trennlinie hinzu
+        output += buildLine(line);
+        return output;
+    }
+
+    void setTruncateText(bool value)
+    {
+        truncateText = value;
+    }
+
+public: // private:
+    const char **headers;
+    const int *columnWidths;
+    size_t size;
+    bool truncateText = false;
+
+    static int displayLength(const char *text)
+    {
+        int length = 0;
+        for (int i = 0; text[i] != '\0'; ++i)
+        {
+            if ((text[i] & 0xC0) != 0x80)
+            { // Überspringe UTF-8 Fortsetzungsbytes
+                length++;
+            }
+        }
+        return length;
+    }
+
+    static void safeStringCopy(char *dest, const char *src, size_t bufferSize)
+    {
+        if (strlen(src) >= bufferSize)
+        {
+            strncpy(dest, src, bufferSize - 1);
+            dest[bufferSize - 1] = '\0'; // NULL-termination sichergestellt
+        }
+        else
+        {
+            strcpy(dest, src);
+        }
+    }
+
+    static void replaceUmlauts(char *text)
+    {
+        // UTF-8 Codes für Umlaute (hex): ä(c3 a4) ö(c3 b6) ü(c3 bc) Ä(c3 84) Ö(c3 96) Ü(c3 9c) ß(c3 9f)
+        struct UmlautPair
+        {
+            unsigned char bytes[2]; // UTF-8 bytes
+            const char *replacement;
+        };
+
+        const UmlautPair pairs[] = {
+            {{0xc3, 0xa4}, "ae"}, // ä
+            {{0xc3, 0xb6}, "oe"}, // ö
+            {{0xc3, 0xbc}, "ue"}, // ü
+            {{0xc3, 0x84}, "Ae"}, // Ä
+            {{0xc3, 0x96}, "Oe"}, // Ö
+            {{0xc3, 0x9c}, "Ue"}, // Ü
+            {{0xc3, 0x9f}, "ss"}  // ß
+        };
+        const int numPairs = sizeof(pairs) / sizeof(pairs[0]);
+
+        size_t maxOutputLength = strlen(text) * 2 + 1;
+        char *buffer = (char *)malloc(maxOutputLength);
+        if (!buffer)
+            return;
+
+        int k = 0; // Position im Ausgabepuffer
+        int i = 0; // Position im Eingabetext
+
+        while (text[i] != '\0')
+        {
+            bool replaced = false;
+
+            // Prüfe auf UTF-8 Sequenz
+            if ((unsigned char)text[i] == 0xc3 && text[i + 1] != '\0')
+            {
+                for (int j = 0; j < numPairs; ++j)
+                {
+                    if ((unsigned char)text[i] == pairs[j].bytes[0] &&
+                        (unsigned char)text[i + 1] == pairs[j].bytes[1])
+                    {
+                        // Kopiere Ersetzung
+                        const char *replacement = pairs[j].replacement;
+                        for (int r = 0; replacement[r] != '\0' && k < maxOutputLength - 1; ++r)
+                        {
+                            buffer[k++] = replacement[r];
+                        }
+                        replaced = true;
+                        i += 2; // Überspringe beide UTF-8 Bytes
+                        break;
+                    }
+                }
+            }
+
+            if (!replaced && k < maxOutputLength - 1)
+            {
+                buffer[k++] = text[i++];
+            }
+        }
+
+        buffer[k] = '\0';
+        strcpy(text, buffer);
+        free(buffer);
+    }
+
+    // Neue Version von splitStringByLength
+    static void splitStringByLength(const char *input, int L, char *output)
+    {
+        int len = strlen(input);
+        int outputIndex = 0;
+        int currentLength = 0;
+
+        for (int i = 0; i < len; ++i)
+        {
+            // Kopiere das aktuelle Zeichen zu Ausgabe
+            unsigned char curr = input[i];
+            output[outputIndex++] = curr;
+
+            // UTF-8-Handling: Überspringe zusätzliche Bytes für ein Multibyte-Zeichen
+            if ((curr & 0x80) != 0)
+            {
+                // Wenn das höchste Bit gesetzt ist, haben wir ein Multibyte-Zeichen
+                while ((input[i + 1] & 0xC0) == 0x80)
+                {
+                    output[outputIndex++] = input[++i];
+                }
+            }
+
+            currentLength++;
+
+            // Wenn die maximale Länge erreicht ist und das nächste Zeichen kein newline ist
+            if (currentLength == L && i + 1 < len && input[i + 1] != '\n')
+            {
+                output[outputIndex++] = '\n';
+                currentLength = 0;
+            }
+        }
+        output[outputIndex] = '\0'; // Beende den String
+    }
+
+    void truncateToColumnWidth(const char *input, int width, char *output)
+    {
+        int len = strlen(input);
+        if (len > width)
+        {
+            width = (width > 3) ? width - 3 : width;
+            strncpy(output, input, width);
+            strcpy(output + width, "...");
+        }
+        else
+        {
+            strcpy(output, input);
+        }
+    }
+
+    size_t calculateMaxLines(char **t_row)
+    {
+        size_t maxLines = 0;
+
+        for (size_t i = 0; i < size; ++i)
+        {
+            const char *text = t_row[i];
+            size_t textLength = strlen(text);
+            size_t lines = 1;
+
+            for (size_t j = 0; j < textLength; ++j)
+            {
+                if (text[j] == '\n')
+                {
+                    ++lines;
+                }
+            }
+
+            maxLines = max(maxLines, lines);
+        }
+
+        return maxLines;
+    }
+
+    const char *getRowSegment(const char *text, int width, size_t line, char *buffer)
+    {
+        size_t textLength = strlen(text);
+        size_t lineStart = 0;
+        size_t currentLine = 0;
+        buffer[0] = '\0';
+
+        for (size_t i = 0; i < textLength; ++i)
+        {
+            if (currentLine == line)
+            {
+                lineStart = i;
+                break;
+            }
+            if (text[i] == '\n' || (i > 0 && (i % width) == 0))
+            {
+                ++currentLine;
+            }
+        }
+
+        if (lineStart >= textLength || currentLine != line)
+        {
+            return buffer;
+        }
+
+        size_t charCount = 0;
+        for (size_t i = lineStart; i < textLength && charCount < width; ++i)
+        {
+            if (text[i] == '\n')
+            {
+                break;
+            }
+            buffer[charCount++] = text[i];
+        }
+
+        buffer[charCount] = '\0';
+
+        return buffer;
+    }
+
+    String buildLine(char lineChar)
+    {
+        String line;
+        for (size_t i = 0; i < size; ++i)
+        {
+            line += '+';
+            for (int j = 0; j < columnWidths[i]; ++j)
+            {
+                line += lineChar;
+            }
+        }
+        line += "+\n";
+        return line;
+    }
+};
+
+#endif // SERIALTABLE_H
\ No newline at end of file
diff --git a/.build/sketch/UnitTests.h b/.build/sketch/UnitTests.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a12d8ddeb70d4d08f61cff7b381dbc92e4e09c9
--- /dev/null
+++ b/.build/sketch/UnitTests.h
@@ -0,0 +1,343 @@
+#line 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/UnitTests.h"
+#include <AUnit.h>
+#include "SerialTable.h"
+using namespace aunit;
+
+test(SplitStringNoNewlines)
+{
+    char input[] = "This is a test string";
+    int length = 5;
+    char expectedOutput[] = "This \nis a \ntest \nstrin\ng";
+    char actualOutput[256] = {0}; // Ausreichend großer Puffer
+
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    // Überprüfung der Länge der Strings
+    assertEqual(strlen(expectedOutput), strlen(actualOutput));
+/*
+    // Zusätzliche Debug-Ausgabe, um Hex-Werte zu sehen
+    for (size_t i = 0; i < strlen(actualOutput); ++i)
+    {
+        Serial.print("Expected: ");
+        Serial.print((int)expectedOutput[i]);
+        Serial.print(", Actual: ");
+        Serial.println((int)actualOutput[i]);
+    }
+*/
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 2: Eingabe mit existierenden Zeilenumbrüchen
+test(SplitStringWithNewlines)
+{
+    char input[] = "This\nis\na\ntest";
+    int length = 4;
+    char expectedOutput[] = "This\nis\na\ntest";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 3: Länge größer als Eingabetext
+test(SplitStringLengthGreaterThanText)
+{
+    char input[] = "Short";
+    int length = 10;
+    char expectedOutput[] = "Short";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 4: Genau passende Länge
+test(SplitStringExactLength)
+{
+    char input[] = "Lengthy";
+    int length = 7;
+    char expectedOutput[] = "Lengthy";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 5: Länge von 1
+test(SplitStringLengthOfOne)
+{
+    char input[] = "One";
+    int length = 1;
+    char expectedOutput[] = "O\nn\ne";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 6: Leerer Eingabestring
+test(SplitStringEmptyInput)
+{
+    char input[] = "";
+    int length = 5;
+    char expectedOutput[] = "";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Erstelle eine Hilfsfunktion für replaceUmlauts-Tests
+test(replaceUmlautsTest)
+{
+    char text1[] = "Köln";
+    SerialTable::replaceUmlauts(text1);
+    assertEqual("Koeln", text1);
+
+    char text2[] = "München";
+    SerialTable::replaceUmlauts(text2);
+    assertEqual("Muenchen", text2);
+
+    char text3[] = "Straße";
+    SerialTable::replaceUmlauts(text3);
+    assertEqual("Strasse", text3);
+}
+
+// Erstelle eine Hilfsfunktion für truncateTextTest
+test(truncateTextTest)
+{
+    char buffer[20];
+    SerialTable table(nullptr, nullptr, 0);
+
+    // Fall: Text passt in die Spaltenbreite
+    strcpy(buffer, "Hello");
+    table.truncateToColumnWidth(buffer, 10, buffer);
+    assertEqual("Hello", buffer);
+
+    // Fall: Text wird abgeschnitten
+    strcpy(buffer, "HelloWorld!");
+    table.truncateToColumnWidth(buffer, 5, buffer);
+    assertEqual("He...", buffer);
+}
+
+test(buildHeaderTest1)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----------+-----+----------+\n"
+        "|Name      |Age  |City      |\n"
+        "+==========+=====+==========+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(buildHeaderTest2)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"NameName Name", "Age Age Age", "CityCityCity"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----------+-----+----------+\n"
+        "|NameName N|Age A|CityCityCi|\n"
+        "|ame       |ge Ag|ty        |\n"
+        "|          |e    |          |\n"
+        "+==========+=====+==========+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(buildHeaderTest3)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"ä123", "ö123", "ü123"};
+    const int columnWidths[] = {4, 4, 4};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----+----+----+\n"
+        "|ä123|ö123|ü123|\n"
+        "+====+====+====+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(printHeaderTest)
+{
+    // Verwende char*-Array statt String-Array
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    table.printHeader();
+    Serial.flush();
+
+    // Placeholder assertion, Verwendung eines Serial Monitor Tools empfohlen
+    assertTrue(true);
+}
+
+test(buildRowTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"Alice", "30", "Wonderland"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|Alice     |30   |Wonderland|\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printRowWithMultipleLinesTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 5};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"Alice", "30", "Wonderland"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|Alice     |30   |Wonde|\n"
+        "|          |     |rland|\n"
+        "+----------+-----+-----+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printRowWithLongTextTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"A very long name", "12345", "A very long city name"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|A very lon|12345|A very lon|\n"
+        "|g name    |     |g city nam|\n"
+        "|          |     |e         |\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printEmptyRowTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"", "", ""};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|          |     |          |\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(DisplayLengthBasic) {
+    assertEqual(5, SerialTable::displayLength("Hello"));
+}
+
+test(DisplayLengthWithSpace) {
+    assertEqual(11, SerialTable::displayLength("Hello World"));
+}
+
+test(DisplayLengthWithUmlauts) {
+    // "Müller" in UTF-8 hat eine Länge von 6 Zeichen (ä zählt als 1 Zeichen)
+    assertEqual(6, SerialTable::displayLength("Müller"));
+}
+
+test(DisplayLengthOnlyUmlauts) {
+    // "äöü" in UTF-8 sollten jeweils als ein Zeichen zählen
+    assertEqual(3, SerialTable::displayLength("äöü"));
+}
+
+test(DisplayLengthUTF8Emojis) {
+    // "😀😃😄" Emojis können mehrere Bytes haben, prüfen ob jedes nur als ein Zeichen gezählt wird
+    assertEqual(3, SerialTable::displayLength("😀😃😄"));
+}
+
+test(DisplayLengthWithNewline) {
+    // "Hello\nWorld" hat eine Länge von 11 Zeichen, da \n als einzelnes Zeichen zählt
+    assertEqual(11, SerialTable::displayLength("Hello\nWorld"));
+}
+
+test(DisplayLengthEmptyString) {
+    // Ein leerer String sollte eine Länge von 0 haben
+    assertEqual(0, SerialTable::displayLength(""));
+}
+
+test(DisplayLengthSpaces) {
+    // "   " hat eine Länge von 3 Leerzeichen
+    assertEqual(3, SerialTable::displayLength("   "));
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d17daf97dd08da406728b4f2812eddf287596e88
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,52 @@
+# Allgemeine VSCode-Einstellungen
+.vscode/
+*.code-workspace
+
+# ESP32 spezifische Dateien
+build/
+*.elf
+*.bin
+*.map
+*.hex
+*.o
+sdkconfig
+sdkconfig.old
+partition_table.csv
+partition_table.bin
+
+# Temporäre Dateien
+*.log
+*.tmp
+*.bak
+*.swp
+*.swo
+*.DS_Store
+*.pyc
+__pycache__/
+*.d
+*.lst
+
+# Arduino Core (falls verwendet)
+*.ino.*
+*.cpp~
+*.h~
+
+# Debugging und Flashing
+flash_project_args
+build.log
+flash.log
+
+# PlattformIO (falls genutzt)
+.pio/
+.env
+.clangd/
+ipch/
+project_config.json
+
+# Betriebssystem-spezifische Dateien
+Thumbs.db
+Desktop.ini
+
+# Andere IDEs (falls versehentlich hinzugefügt)
+.idea/
+*.iml
diff --git a/SerialTable.h b/SerialTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..27731954972edfdee428fc4f1042a2a00c1318b1
--- /dev/null
+++ b/SerialTable.h
@@ -0,0 +1,353 @@
+#ifndef SERIALTABLE_H
+#define SERIALTABLE_H
+
+#include <Arduino.h>
+
+class SerialTable
+{
+public:
+    SerialTable(const char *headers[], const int columnWidths[], size_t size)
+        : headers(headers), columnWidths(columnWidths), size(size) {}
+
+    // Diese Methode gibt den Header an die serielle Schnittstelle aus
+    void printHeader()
+    {
+        String header = buildHeader();
+        Serial.print(header);
+    }
+
+    String buildHeader()
+    {
+        return buildLine('-') + buildRow(const_cast<char **>(headers), '='); // Kopfzeile mit '='
+    }
+
+    void printRow(char **t_row)
+    {
+        String row = buildRow(t_row);
+        Serial.print(row);
+    }
+
+    String buildRow(char **t_row, char line = '-')
+    {
+        String output;
+        char buffer[256];
+        int maxLines = 1; // Maximale Anzahl Zeilen über alle Spalten
+
+        // Erste Phase: Teile jede Zelle in Zeilen und finde maximale Zeilenzahl
+        for (size_t i = 0; i < size; ++i)
+        {
+            if (truncateText)
+            {
+                truncateToColumnWidth(t_row[i], columnWidths[i], buffer);
+            }
+            else
+            {
+                splitStringByLength(t_row[i], columnWidths[i], buffer);
+            }
+
+            // Zähle Zeilen in dieser Zelle
+            int lineCount = 1;
+            for (size_t j = 0; j < displayLength(buffer); j++)
+            {
+                if (buffer[j] == '\n')
+                    lineCount++;
+            }
+            if (lineCount > maxLines)
+                maxLines = lineCount;
+        }
+
+        // Zweite Phase: Baue die Zeilen auf
+        for (int line = 0; line < maxLines; line++)
+        {
+            output += "|";
+
+            // Gehe durch jede Spalte
+            for (size_t col = 0; col < size; ++col)
+            {
+                if (truncateText)
+                {
+                    truncateToColumnWidth(t_row[col], columnWidths[col], buffer);
+                }
+                else
+                {
+                    splitStringByLength(t_row[col], columnWidths[col], buffer);
+                }
+
+                // Finde die aktuelle Zeile für diese Spalte
+                char *currentLine = buffer;
+                int currentLineNum = 0;
+                char tempBuffer[256] = "";
+
+                while (currentLineNum < line)
+                {
+                    char *newline = strchr(currentLine, '\n');
+                    if (newline == NULL)
+                    {
+                        currentLine = "";
+                        break;
+                    }
+                    currentLine = newline + 1;
+                    currentLineNum++;
+                }
+
+                // Extrahiere die Zeile bis zum nächsten \n oder Ende
+                int j = 0;
+                while (currentLine[j] && currentLine[j] != '\n')
+                {
+                    tempBuffer[j] = currentLine[j];
+                    j++;
+                }
+                tempBuffer[j] = '\0';
+
+                // Berechne die tatsächliche Anzeigelänge
+                int printedLength = displayLength(tempBuffer);
+
+                // Füge den Inhalt und die fehlenden Leerzeichen hinzu
+                output += tempBuffer;
+                int spacesToAdd = columnWidths[col] - printedLength;
+                for (int k = 0; k < spacesToAdd; k++)
+                {
+                    output += " ";
+                }
+                output += "|";
+            }
+            output += "\n";
+        }
+
+        // Füge die Trennlinie hinzu
+        output += buildLine(line);
+        return output;
+    }
+
+    void setTruncateText(bool value)
+    {
+        truncateText = value;
+    }
+
+public: // private:
+    const char **headers;
+    const int *columnWidths;
+    size_t size;
+    bool truncateText = false;
+
+    static int displayLength(const char *text)
+    {
+        int length = 0;
+        for (int i = 0; text[i] != '\0'; ++i)
+        {
+            if ((text[i] & 0xC0) != 0x80)
+            { // Überspringe UTF-8 Fortsetzungsbytes
+                length++;
+            }
+        }
+        return length;
+    }
+
+    static void safeStringCopy(char *dest, const char *src, size_t bufferSize)
+    {
+        if (strlen(src) >= bufferSize)
+        {
+            strncpy(dest, src, bufferSize - 1);
+            dest[bufferSize - 1] = '\0'; // NULL-termination sichergestellt
+        }
+        else
+        {
+            strcpy(dest, src);
+        }
+    }
+
+    static void replaceUmlauts(char *text)
+    {
+        // UTF-8 Codes für Umlaute (hex): ä(c3 a4) ö(c3 b6) ü(c3 bc) Ä(c3 84) Ö(c3 96) Ü(c3 9c) ß(c3 9f)
+        struct UmlautPair
+        {
+            unsigned char bytes[2]; // UTF-8 bytes
+            const char *replacement;
+        };
+
+        const UmlautPair pairs[] = {
+            {{0xc3, 0xa4}, "ae"}, // ä
+            {{0xc3, 0xb6}, "oe"}, // ö
+            {{0xc3, 0xbc}, "ue"}, // ü
+            {{0xc3, 0x84}, "Ae"}, // Ä
+            {{0xc3, 0x96}, "Oe"}, // Ö
+            {{0xc3, 0x9c}, "Ue"}, // Ü
+            {{0xc3, 0x9f}, "ss"}  // ß
+        };
+        const int numPairs = sizeof(pairs) / sizeof(pairs[0]);
+
+        size_t maxOutputLength = strlen(text) * 2 + 1;
+        char *buffer = (char *)malloc(maxOutputLength);
+        if (!buffer)
+            return;
+
+        int k = 0; // Position im Ausgabepuffer
+        int i = 0; // Position im Eingabetext
+
+        while (text[i] != '\0')
+        {
+            bool replaced = false;
+
+            // Prüfe auf UTF-8 Sequenz
+            if ((unsigned char)text[i] == 0xc3 && text[i + 1] != '\0')
+            {
+                for (int j = 0; j < numPairs; ++j)
+                {
+                    if ((unsigned char)text[i] == pairs[j].bytes[0] &&
+                        (unsigned char)text[i + 1] == pairs[j].bytes[1])
+                    {
+                        // Kopiere Ersetzung
+                        const char *replacement = pairs[j].replacement;
+                        for (int r = 0; replacement[r] != '\0' && k < maxOutputLength - 1; ++r)
+                        {
+                            buffer[k++] = replacement[r];
+                        }
+                        replaced = true;
+                        i += 2; // Überspringe beide UTF-8 Bytes
+                        break;
+                    }
+                }
+            }
+
+            if (!replaced && k < maxOutputLength - 1)
+            {
+                buffer[k++] = text[i++];
+            }
+        }
+
+        buffer[k] = '\0';
+        strcpy(text, buffer);
+        free(buffer);
+    }
+
+    // Neue Version von splitStringByLength
+    static void splitStringByLength(const char *input, int L, char *output)
+    {
+        int len = strlen(input);
+        int outputIndex = 0;
+        int currentLength = 0;
+
+        for (int i = 0; i < len; ++i)
+        {
+            // Kopiere das aktuelle Zeichen zu Ausgabe
+            unsigned char curr = input[i];
+            output[outputIndex++] = curr;
+
+            // UTF-8-Handling: Überspringe zusätzliche Bytes für ein Multibyte-Zeichen
+            if ((curr & 0x80) != 0)
+            {
+                // Wenn das höchste Bit gesetzt ist, haben wir ein Multibyte-Zeichen
+                while ((input[i + 1] & 0xC0) == 0x80)
+                {
+                    output[outputIndex++] = input[++i];
+                }
+            }
+
+            currentLength++;
+
+            // Wenn die maximale Länge erreicht ist und das nächste Zeichen kein newline ist
+            if (currentLength == L && i + 1 < len && input[i + 1] != '\n')
+            {
+                output[outputIndex++] = '\n';
+                currentLength = 0;
+            }
+        }
+        output[outputIndex] = '\0'; // Beende den String
+    }
+
+    void truncateToColumnWidth(const char *input, int width, char *output)
+    {
+        int len = strlen(input);
+        if (len > width)
+        {
+            width = (width > 3) ? width - 3 : width;
+            strncpy(output, input, width);
+            strcpy(output + width, "...");
+        }
+        else
+        {
+            strcpy(output, input);
+        }
+    }
+
+    size_t calculateMaxLines(char **t_row)
+    {
+        size_t maxLines = 0;
+
+        for (size_t i = 0; i < size; ++i)
+        {
+            const char *text = t_row[i];
+            size_t textLength = strlen(text);
+            size_t lines = 1;
+
+            for (size_t j = 0; j < textLength; ++j)
+            {
+                if (text[j] == '\n')
+                {
+                    ++lines;
+                }
+            }
+
+            maxLines = max(maxLines, lines);
+        }
+
+        return maxLines;
+    }
+
+    const char *getRowSegment(const char *text, int width, size_t line, char *buffer)
+    {
+        size_t textLength = strlen(text);
+        size_t lineStart = 0;
+        size_t currentLine = 0;
+        buffer[0] = '\0';
+
+        for (size_t i = 0; i < textLength; ++i)
+        {
+            if (currentLine == line)
+            {
+                lineStart = i;
+                break;
+            }
+            if (text[i] == '\n' || (i > 0 && (i % width) == 0))
+            {
+                ++currentLine;
+            }
+        }
+
+        if (lineStart >= textLength || currentLine != line)
+        {
+            return buffer;
+        }
+
+        size_t charCount = 0;
+        for (size_t i = lineStart; i < textLength && charCount < width; ++i)
+        {
+            if (text[i] == '\n')
+            {
+                break;
+            }
+            buffer[charCount++] = text[i];
+        }
+
+        buffer[charCount] = '\0';
+
+        return buffer;
+    }
+
+    String buildLine(char lineChar)
+    {
+        String line;
+        for (size_t i = 0; i < size; ++i)
+        {
+            line += '+';
+            for (int j = 0; j < columnWidths[i]; ++j)
+            {
+                line += lineChar;
+            }
+        }
+        line += "+\n";
+        return line;
+    }
+};
+
+#endif // SERIALTABLE_H
\ No newline at end of file
diff --git a/UnitTests.h b/UnitTests.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d67725577d202525c4eefd8a92f2ce52abb0c4b
--- /dev/null
+++ b/UnitTests.h
@@ -0,0 +1,342 @@
+#include <AUnit.h>
+#include "SerialTable.h"
+using namespace aunit;
+
+test(SplitStringNoNewlines)
+{
+    char input[] = "This is a test string";
+    int length = 5;
+    char expectedOutput[] = "This \nis a \ntest \nstrin\ng";
+    char actualOutput[256] = {0}; // Ausreichend großer Puffer
+
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    // Überprüfung der Länge der Strings
+    assertEqual(strlen(expectedOutput), strlen(actualOutput));
+/*
+    // Zusätzliche Debug-Ausgabe, um Hex-Werte zu sehen
+    for (size_t i = 0; i < strlen(actualOutput); ++i)
+    {
+        Serial.print("Expected: ");
+        Serial.print((int)expectedOutput[i]);
+        Serial.print(", Actual: ");
+        Serial.println((int)actualOutput[i]);
+    }
+*/
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 2: Eingabe mit existierenden Zeilenumbrüchen
+test(SplitStringWithNewlines)
+{
+    char input[] = "This\nis\na\ntest";
+    int length = 4;
+    char expectedOutput[] = "This\nis\na\ntest";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 3: Länge größer als Eingabetext
+test(SplitStringLengthGreaterThanText)
+{
+    char input[] = "Short";
+    int length = 10;
+    char expectedOutput[] = "Short";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 4: Genau passende Länge
+test(SplitStringExactLength)
+{
+    char input[] = "Lengthy";
+    int length = 7;
+    char expectedOutput[] = "Lengthy";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 5: Länge von 1
+test(SplitStringLengthOfOne)
+{
+    char input[] = "One";
+    int length = 1;
+    char expectedOutput[] = "O\nn\ne";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Einzelner Testfall 6: Leerer Eingabestring
+test(SplitStringEmptyInput)
+{
+    char input[] = "";
+    int length = 5;
+    char expectedOutput[] = "";
+    char actualOutput[256] = {0};
+    SerialTable::splitStringByLength(input, length, actualOutput);
+    assertEqual(String(expectedOutput), String(actualOutput));
+}
+
+// Erstelle eine Hilfsfunktion für replaceUmlauts-Tests
+test(replaceUmlautsTest)
+{
+    char text1[] = "Köln";
+    SerialTable::replaceUmlauts(text1);
+    assertEqual("Koeln", text1);
+
+    char text2[] = "München";
+    SerialTable::replaceUmlauts(text2);
+    assertEqual("Muenchen", text2);
+
+    char text3[] = "Straße";
+    SerialTable::replaceUmlauts(text3);
+    assertEqual("Strasse", text3);
+}
+
+// Erstelle eine Hilfsfunktion für truncateTextTest
+test(truncateTextTest)
+{
+    char buffer[20];
+    SerialTable table(nullptr, nullptr, 0);
+
+    // Fall: Text passt in die Spaltenbreite
+    strcpy(buffer, "Hello");
+    table.truncateToColumnWidth(buffer, 10, buffer);
+    assertEqual("Hello", buffer);
+
+    // Fall: Text wird abgeschnitten
+    strcpy(buffer, "HelloWorld!");
+    table.truncateToColumnWidth(buffer, 5, buffer);
+    assertEqual("He...", buffer);
+}
+
+test(buildHeaderTest1)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----------+-----+----------+\n"
+        "|Name      |Age  |City      |\n"
+        "+==========+=====+==========+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(buildHeaderTest2)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"NameName Name", "Age Age Age", "CityCityCity"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----------+-----+----------+\n"
+        "|NameName N|Age A|CityCityCi|\n"
+        "|ame       |ge Ag|ty        |\n"
+        "|          |e    |          |\n"
+        "+==========+=====+==========+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(buildHeaderTest3)
+{
+    // Definiere header mit char*-Zeigern
+    const char *headers[] = {"ä123", "ö123", "ü123"};
+    const int columnWidths[] = {4, 4, 4};
+    SerialTable table(headers, columnWidths, 3);
+
+    // Verwende buildHeader, um den Header-String zu erhalten
+    String header = table.buildHeader();
+
+    // Gib den Header über Serial aus
+    Serial.print(header);
+    Serial.flush();
+
+    // Erwartete Ausgabe des Headers
+    String expectedHeader =
+        "+----+----+----+\n"
+        "|ä123|ö123|ü123|\n"
+        "+====+====+====+\n";
+
+    // Vergleiche den erzeugten Header mit dem erwarteten Header
+    assertEqual(expectedHeader, header);
+}
+
+test(printHeaderTest)
+{
+    // Verwende char*-Array statt String-Array
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    table.printHeader();
+    Serial.flush();
+
+    // Placeholder assertion, Verwendung eines Serial Monitor Tools empfohlen
+    assertTrue(true);
+}
+
+test(buildRowTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"Alice", "30", "Wonderland"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|Alice     |30   |Wonderland|\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printRowWithMultipleLinesTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 5};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"Alice", "30", "Wonderland"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|Alice     |30   |Wonde|\n"
+        "|          |     |rland|\n"
+        "+----------+-----+-----+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printRowWithLongTextTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"A very long name", "12345", "A very long city name"};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|A very lon|12345|A very lon|\n"
+        "|g name    |     |g city nam|\n"
+        "|          |     |e         |\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(printEmptyRowTest)
+{
+    const char *headers[] = {"Name", "Age", "City"};
+    const int columnWidths[] = {10, 5, 10};
+    SerialTable table(headers, columnWidths, 3);
+
+    char *rows[] = {"", "", ""};
+
+    // Verwende buildRow, um den Zeilen-String zu bekommen
+    String rowOutput = table.buildRow(rows);
+
+    // Gib die Zeile über Serial aus
+    Serial.print(rowOutput);
+    Serial.flush();
+
+    // Erwartete Ausgabe der Zeile
+    String expectedRowOutput =
+        "|          |     |          |\n"
+        "+----------+-----+----------+\n";
+
+    // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String
+    assertEqual(expectedRowOutput, rowOutput);
+}
+
+test(DisplayLengthBasic) {
+    assertEqual(5, SerialTable::displayLength("Hello"));
+}
+
+test(DisplayLengthWithSpace) {
+    assertEqual(11, SerialTable::displayLength("Hello World"));
+}
+
+test(DisplayLengthWithUmlauts) {
+    // "Müller" in UTF-8 hat eine Länge von 6 Zeichen (ä zählt als 1 Zeichen)
+    assertEqual(6, SerialTable::displayLength("Müller"));
+}
+
+test(DisplayLengthOnlyUmlauts) {
+    // "äöü" in UTF-8 sollten jeweils als ein Zeichen zählen
+    assertEqual(3, SerialTable::displayLength("äöü"));
+}
+
+test(DisplayLengthUTF8Emojis) {
+    // "😀😃😄" Emojis können mehrere Bytes haben, prüfen ob jedes nur als ein Zeichen gezählt wird
+    assertEqual(3, SerialTable::displayLength("😀😃😄"));
+}
+
+test(DisplayLengthWithNewline) {
+    // "Hello\nWorld" hat eine Länge von 11 Zeichen, da \n als einzelnes Zeichen zählt
+    assertEqual(11, SerialTable::displayLength("Hello\nWorld"));
+}
+
+test(DisplayLengthEmptyString) {
+    // Ein leerer String sollte eine Länge von 0 haben
+    assertEqual(0, SerialTable::displayLength(""));
+}
+
+test(DisplayLengthSpaces) {
+    // "   " hat eine Länge von 3 Leerzeichen
+    assertEqual(3, SerialTable::displayLength("   "));
+}
diff --git a/output.txt b/output.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d9207f8797def018532d7b7f9a40c9e68fc9d020
--- /dev/null
+++ b/output.txt
@@ -0,0 +1,26 @@
++---------------+--------------------+----------+
+|Header 1       |Header 2            |Header 3  |
++===============+====================+==========+
+|Text           |                    |Text      |
++---------------+--------------------+----------+
+|Text           |Text                |          |
++---------------+--------------------+----------+
+|               |Text                |Text1     |
+|Text           |                    |Text2     |
++---------------+--------------------+----------+
+
+|Alice     |30   |Wonde|
+|          |     |rland|
++----------+-----+-----+
+
+|Alice     |30   |Wonderland|
++----------+-----+-----+
+
+
+|Alice     |30   |Wonde|
+|          |     |rland|
++----------+-----+-----+
+
+|Alice     |30   |Wonde
+rland|
++----------+-----+-----+
diff --git a/serialTable.ino b/serialTable.ino
new file mode 100644
index 0000000000000000000000000000000000000000..ac42ae46fb8c1ee4de7a9a161dabb0117dbc58ad
--- /dev/null
+++ b/serialTable.ino
@@ -0,0 +1,52 @@
+#include <Arduino.h>
+#include "UnitTests.h"
+#include "SerialTable.h"
+
+void setup()
+{
+    // Initialisieren der seriellen Verbindung
+    Serial.begin(115200);
+    
+        // Definieren der Kopfzeilen und Spaltenbreiten für 8 Spalten
+        const char *headers[] = {"Vorname", "Nachname", "Alter", "Stadt", "Beruf", "Unternehmen", "Hobby", "Bemerkung"};
+        int columnWidths[] = {10, 15, 5, 10, 10, 15, 10, 20};
+
+        SerialTable table(headers, columnWidths, 8);
+        table.printHeader();
+
+        // Erstellen von 20 Zeilen mit unterschiedlichen Einträgen
+        char *rows[20][8] = {
+            {"Alice", "Wonderland", "30", "Köln", "Ingenieur", "FirmaX", "Schwimmen", "Keine"},
+            {"Bob", "Builder\nJr", "35", "Berlin", "Architekt", "Architektur AG", "Bauen", "Sehr erfahren"},
+            {"Charlie", "Brown", "28", "Hamburg", "Designer", "Die Design", "Zeichnen", "Mag Karikaturen"},
+            {"David", "Tennant", "40", "München", "Schauspieler", "Freiberufler", "Lesen", "Doktor gewesen"},
+            {"Emma", "Watson", "33", "Frankfurt", "Schauspielerin", "Independent", "Yoga", "Bekannt aus Filmen"},
+            {"Frank", "Herbert", "45", "Stuttgart", "Autor", "Ein Verlag", "Schreiben", "Bücher geschrieben"},
+            {"Grace", "Hopper", "50", "Berlin", "Programmiererin", "Tech Corp", "Informatik", "Pionierin"},
+            {"Hugo", "Strange", "60", "Leipzig", "Psychiater", "Gesundheits GmbH", "Philosophie", "Ruhestand"},
+            {"Irene", "Adler", "29", "Dresden", "Detektivin", "Privat", "Abenteuer", "Scharfsinnig"},
+            {"John", "Doe", "49", "Bremen", "Buchhalter", "Kontorechner", "Radfahren", "Gewissenhaft"},
+            {"Klara", "Kühn", "39", "Hannover", "Lehrerin", "Schule ABC", "Lesen", "Einfühlsam"},
+            {"Lenny", "Small", "25", "Koblenz", "Musiker", "Orchester", "Gitarre", "Kreativ"},
+            {"Mona", "Lisa", "33", "Siegen", "Malerin", "Kunsthaus", "Kunst", "Geheimnisvoll"},
+            {"Nina", "Simone", "30", "Essen", "Sängerin", "Soul Musik", "Musik", "Talentiert"},
+            {"Oliver", "Twist", "19", "Potsdam", "Student", "Uni XY", "Fußball", "Engagiert"},
+            {"Pam", "Beesly", "32", "Wuppertal", "Sekretärin", "Dunder Mifflin", "Malen", "Freundlich"},
+            {"Quinn", "Fabray", "26", "Magdeburg", "Designer", "Agentur XYZ", "Tanzen", "Kreativ"},
+            {"Ron", "Swanson", "55", "Bielefeld", "Verwalter", "Rathaus", "Holzarbeiten", "Direkt"},
+            {"Sophia", "Loren", "70", "Osnabrück", "Schauspielerin", "Independent", "Kochen", "Ikonisch"},
+            {"Tom", "Hanson", "36", "Regensburg", "Polizist", "Polizei", "Jagen", "Schützend"},
+        };
+
+        // Drucke die Zeilen
+        for (int i = 0; i < 20; ++i)
+        {
+            table.printRow(rows[i]);
+        }
+        
+}
+
+void loop()
+{
+    //TestRunner::run();
+}
\ No newline at end of file