Serial.println, String und der Fehler

Servus,
vor kurzem hatte ich einen sehr seltsames Problem mit meinem Arduino:
Das Ausführen der Methode ReadIDs() funktionierte zwei Mal, und beim dritten mal nicht mehr. Danach hängt sich der Arduino auf oder resetet.

String ReadID(int index){
  String ID;
  for (int j = 0; j < 8; j++){
    //ID += char( EEPROM.read(index * 8 + j + 1));
    //ID += char( 65);
    ID += 'A';
    //ID = ID + 'A';
  }
  return ID;  
}

String ReadIDs()
{
  int cnt = getcount();
  Serial.println(cnt);  
  for (int i = 0; i < cnt; i++){
    //Serial.println("loop");
    //ReadID(i);
    Serial.println(ReadID(i));
  }
}

Serial Ready

1
AAAAAAAA
1
AAAAAAAA
1

Nach stundenlangen rumprobieren glaube ich, die Fehlerquelle gefunden zu haben. Der Fehler taucht nur auf, wenn ich den zurückgegebenen String über println ausgeben möchte, nicht wenn ich die Funktion ReadID(index) aufrufe ohne den Wert auszugeben.
Habe ich etwas übersehen oder könnte das Problem tatsächlich bei der println-Methode, bzw. dem String-Objekt selbst liegen?

Viele Grüße
Werni

String und unerklärliches Verhalten hat eine einfache Lösung: Keine Strings verwenden !

** **ID += 'A'; // GANZ BÖSE** **

Dass es nur 38 mal geht, wundert mich zwar etwas, ( 2008 wäre klarer ) aber vielleicht hast du ja in den nicht gezeigten Code Zeilen noch mehr Speicherfresser, oder du machst es so schnell, dass die eigentliche serielle Ausgabe nicht mitkommt, bevor es knallt.

Um acht 'A' auszugeben brauchst du kein String Objekt, klar.
Aber auch sonst kommt man sehr gut ohne aus.

Mehrspaltige Anzeige hab ich
noch nicht oft gesehen

:smiley: :smiley:
trés chic

michael_x:

Mehrspaltige Anzeige hab ich
noch nicht oft gesehen

:smiley: :smiley:
trés chic

Ja, ich bin eben ein praktisch denkender Mensch :smiley: Deshalb fande ich Strings auch so toll :frowning:
Wenn du mir jetzt noch sagen könntest was diesmal falsch ist, wäre ich dir sehr dankbar:

char* ReadID(int index){
  //String _ID;
  char ID[9];
  for (int j = 0; j < 8; j++){
    char c = char( EEPROM.read(index * 8 + j + 1));
    Serial.print(c);
    ID[j] = c;
    //ID[j] = '0';
  }
  ID[8] = '\0';
  Serial.println("");
  return ID;  
}

String ReadIDs()
{
  int cnt = getcount();
  Serial.println(cnt);  
  for (int i = 0; i < cnt; i++){
    Serial.println(ReadID(i));
  }
}

Serial Ready
h-1.0.0
1
003D640D
Ç Ç
(konnte nicht CopyPaste machen, enthält also irgendwelche stoppzeichen)

Man dafür müsste es echt einen Button im Editor geben
(Ich bin so ein Formatierungskünstler :D)

[/table]

[color=green]char ID[9]; // am einfachsten mit einer globalen Variable[/color]
char* ReadID(int index){

  [color=red]// char ID[9];  // eine lokale Variable ist weg, wenn die Funktion zu Ende ist[/color]
  for (int j = 0; j < 8; j++){
    char c = EEPROM.read(index * 8 + j + 1);
    Serial.print(c);
    ID[j] = c;
  }
  ID[8] = '\0';
  Serial.println();
  return ID;  
}

Bitte sehr ... :wink:

Wer der Philosophie "keine globalen Variablen" zuneigt, kann natürlich einer Funktion einen Puffer und dessen Länge mitgeben.

byte ReadID(byte index, char* buf, byte bufsize); // liefert die tatsächlich geschriebene Länge zurück, falls das interessant sein sollte.

Aber ich brauch die Variable doch gar nicht mehr.
Der Wert wird doch mit return übergeben. Oder etwa nur ein Pointer auf die variable im Speicher?

Oder etwa nur ein Pointer auf die variable im Speicher?

Natürlich ist ein char* ein Pointer.
Ob du diesen Pointer auf eine globale Variable als Rückgabewert lieferst oder nicht, ist eigentlich Geschmackssache.

Ich finde (Motto: "Vermeide globale Variablen") es schön, wenn man einer Funktion ansieht, was sie an Daten benutzt und was sie verändert, mehr oder weniger.
ReadID sollte also eigentlich jetzt
** **void SetIDFromEPROM(byte index);** **
heissen...

Ein String Objekt wird übrigens bei c++, java oder c# auch nur als Pointer bzw. Referenz übergeben, aber es wurde dynamisch auf dem heap erzeugt, öfters umkopiert als man glaubt, und alle nicht mehr benötigten Kopien warten auf die Müllabfuhr. Arduino ist aus Italien, und da ist die Müllabfuhr ein Problem. :wink:

(SCNR, Hoffentlich liest Uwe nicht mit, oder stellt fest dass 1. er aus Südtirol ist, 2. Arduino aus Turin, 3. diese blöden Klischees sich, wenn überhaupt, nur auf Neapel und weiter südlich beziehen)

Auf jeden Fall sind die 2048 Byte RAM eines Ardiuno Uno für solchen Schnickschnack zu schade.
Zumal eine Fehlerbehandlung auch nicht wirklich stattfindet. (Kostet erstens Programmcode-Platz und zweitens, was soll ein µC auch groß machen ... )
Schön, dass einige c++ Features trotzdem gehen, z.B. dass print() so schön vererbt wird.