String kette erzeugen

selfmade:
wieso kann ich nicht alles wie in meinem Sketch in eine Funktion packen

Das kann man machen. Aber schön ist es nicht. Man sollte generell Dinge in einem vernünftigen Rahmen trennen. Jeder erfahrene Programmierer wird dir sagen, dass es übersichtlicher ist Code in kleinere Funktionen auszulagern (sofern jede Funktion eine klare Aufgabe hat wie Eingabe oder Ausgabe) statt alles in eine große Funktion zu packen. Das ist so ziemlich die erste Software Engineering Technik die man lernt. Du nennst deine Funktion z.B. daten_senden(), aber wenn du mehr als wirklich nur das Senden reinpackst ist das schon keine korrekte Beschreibung des Codes mehr.

Das hängt aber auch mit der verwendenden IDE zusammen. Die Arduino IDE ist generell sehr unübersichtlich. Aber in Atmel Studio oder Visual Studio z.B. hat man eine Liste mit allen Funktionen einer Klasse oder Datei. Dann kann man einfach die Funktion in der Liste auswählen und dahin springen. Oder man kann auf einen Funktionsaufruf rechts klicken und sagen er soll dahin springen wo die Funktion definiert ist. Daher muss man da nicht wissen wo was im Code genau steht.

Nicht-blockierenden Code zu schreiben ist auch schöner, wenn auch bei solchen Logging-Geschichten nicht unbedingt immer nötig. Bei deiner Version kann während der Übertragung nichts anderes gemacht werden. Wenn da z.B. noch ein Touch Screen oder Taster dran hingen wären die außer Betrieb.

Wenn du damit besser zurecht kommst wenn alles in einer Funktion ist, ok, dann mach es so. Aber irgendwann willst du vielleicht auch mal ein Programm mit mehr Interaktivität des Benutzers schreiben wo du mit solchen Sachen nicht weit kommst.

Meine Vorschläge sind hier auch nicht unbedingt die Muster-Lösung, aber es sollte theoretisch funktionieren. Ich kann es halt nur mit Serial testen.

Ich dachte eine Funktion würde man mit void deklarieren.

Nein. Void heißt einfach, dass die Funktion nichts zurückgibt. Man kann aber auch alle elementaren Datentypen und Zeiger zurückgeben (und auch noch mehr, aber das lasse ich mal außen vor). Zeiger auf lokale Variablen darf man normalerweise nicht zurückgeben, aber hier ist das Array static deklariert und existiert daher immer, statt am Ende der Funktion seinen Speicher zu verlieren.

Rückgabe-Werte sind meistens besser als globale Variablen um Funktionen miteinander kommunizieren zu lassen. Man kann z.B. auch booleans zurückgeben um zu sagen dass ein bestimmtes Ereignis eingetreten ist. Manchmal kommt man auch im globale Variablen nicht herum. Siehe z.B. boolean requestSent

In meinem Vorschlag ruft loop() ständig stringRead() auf um nachzuschauen ob was da ist (diese ständigen Funktionsaufrufe kosten natürlich auch Performance, aber Programme dieser Art sind insgesamt recht langsam). Wenn nichts da ist liefert die Funktion NULL zurück. Wenn der String komplett eingelesen werden liefert sie einen Zeiger auf das Array. Der ist dann != NULL und loop() startet die Verarbeitung.

"invalid conversion from 'char' to 'char'

Macht nicht viel Sinn. In welcher Zeile genau? Welchen Typ haben die beteiligten Variablen in der Zeile? So wie ich es oben hingeschrieben habe funktioniert das.

Normalerweise kommen solche Fehler mit unterschiedlichen Datentypen wie char und char*. Oder const char und char.

Ich habe übrigens in meinem Code nirgendswo daten_senden() aufgerufen, da ich nicht weiß wie du das genau handhaben willst. Ich nehme mal zeitgesteuert in irgendeiner anderen Funktion.