Dynamischer Speicher voll bei Blink-Testbeispiel

Hallo zusammen,

ich habe einen Arduino Uno und einen Arduino MKR WAN 1300.
Wenn ich den Blink Democode, auf den Uno lade, benötigt dieser 9 Bytes des dynamischen Speichers, was auch Sinn macht.
Wenn ich diesen Code aber auf den MRK lade heißt es, dass 2936 Bytes verwendet werden und es steht nichtmal mehr die Prozentzahl des dynamischen Speichers dahinter (bei anderen Programmen so ähnlich, meistens ~3kB).

Hat jemand eine Idee, was da los ist, bzw. wie ich das Problem lösen kann?

Grüße Daniel.

MKR WAN 1300: SRAM 32 KB

dass 2936 Bytes verwendet werden

Das wird für das USB und Funk Gedönse drauf gehen....
(schau nach)

Das ist alles ok.
Kein Problem!

und es steht nichtmal mehr die Prozentzahl des dynamischen Speichers dahinter

Die Berechnung ist für dieses Board nicht vorhanden, oder möglich.

Kannste ja versuchen nachzurüsten...

Danke für die schnell Antwort, dann muss das Problem an einer anderen Stelle liegen, vielleicht magst und kannst du mir ja hierbei auch helfen:).

Wenn ich meinen eigentlich Code auf den Uno spiele, im seriellen Monitor "310FCD0FCD0FCD0F4C0F31313a30100F31333a3030" eingebe, dann wird an jedem 0F getrennt und mir wird die abgewandelte Version (X statt 0F) und die einzelen "Nachrichten", wie sie sollen ausgegeben.

String data[6];

void setup() {
  Serial.begin(9600);

}
void loop() {
  getData();
  for(int i =0; i<=6;i++){
    Serial.println(data[i]);
  }
  delay(10000);
}


void getData() {

  String inp;
  int l;
  while (!Serial.available()); {
    inp = Serial.readStringUntil('\n');     //Das wird Eingegeben 310FCD0FCD0FCD0F4C0F31313a30100F31333a3030
  }
  inp.replace("0F","X");
  Serial.println(inp);
  l = inp.length()+1;
  char rcv[l];
  inp.toCharArray(rcv, l);
  
  char* pside = strtok(rcv, "X");
  char* pname = strtok(NULL, "X");
  char* pstate = strtok(NULL, "X");
  char* proom = strtok(NULL, "X");
  char* pday = strtok(NULL, "X");
  char* ptbegin = strtok(NULL, "X");
  char* ptend = strtok(NULL, "X");

  data[0] = pside;
  data[1] = proom;
  data[2] = pname;
  data[3] = pstate;
  data[4] = pday;
  data[5] = ptbegin;
  data[6] = ptend;
    }

Wenn ich das ganze jedoch auf dem MKR versuche, wird manchmal nur die abgewandelte Version ausgegeben, manchmal auch garnichts, aber die IDE hängt sich danach immer auf.

Bin auch offen für Verbesserungsvorschläge, mir ist bewusst dass der Code nicht so dolle sein wird.

Ich habe keine Ahnung von MKR, aber String fragmentiert den Speicher, was auch auf den UNOs zu Abstürzen führen soll, weshalb ich String nicht verwende. Alternative ist char[].

Ob es das ist, weiß ich nicht, wäre aber möglich.

Ja das hatte ich auch schon hier im Forum gelesen, das Problem war für mich dann nur, dass ich nicht weiß wie ich als char[], meine "0F" zu "X" bekomme, da ich bei 0F in strtok() nurnoch Werte bis ...31313a3 bekomme und der Rest verschluckt wird.

Du brauchst doch für strtok() sowieso ein char Array. Was soll also der Umweg über die String Klasse? Völlig überflüssig.

Einlesen kann man auch direkt in ein char Array:

Oder auch völlig nicht-blockierend wenn man es per Hand macht:
https://forum.arduino.cc/index.php?topic=634159.msg4293510#msg4293510

Und wenn du das Ergebnis sowieso in einem Array willst kann man das auch in einer Schleife machen die solange läuft bis strtok() NULL liefert oder das Array voll ist

Habe ich versucht, Code sieht so aus

  char rcv[] = "310FCD0FCD0FCD0F4C0F31313a30100F31333a3030";
 
  char *ptr;                    //@ https://forum.arduino.cc/index.php?topic=648077.0
    ptr = strtok(rcv,"0F");
    while(ptr != 0){
      for( int i=0;i<7;i++){
        data[i] = ptr;
        Serial.println(data[i]);
        ptr = strtok(NULL,"0F");
      }
    }

Ergebniss bleibt aber immer noch ab ...31313a3 dann falsch.
Ausgabe :

31
CD
CD
CD
4C
31313a3
1
31333a3
3

Es sollte eigentlich :

31
CD
CD
CD
4C
31313a3010
31333a3030

strtok() funktioniert nicht so wie du denkst. Der String den du übergibst ist eine Liste von Zeichen. Nicht ein längerer String an dem gesplittet wird. Das müsste man ganz anders machen

Und das mit der for-Schleife ist falsch

Wie wäre dein Ansatz, das ganz anders zu machen, bin hier ziemlich am verzweifel.

Das mit der for-Schleife hatte funktioniert, solange keine 0 for einem 0F steht.

daniblpr2020:
Das mit der for-Schleife hatte funktioniert, solange keine 0 for einem 0F steht.

Das ist aber nur Zufall weil die Anzahl der Teil-Strings bekannt ist. Dann kannst du dir auch die while-Schleife sparen. Das kann ok sein, aber den Zusammenhang hast du nicht ganz verstanden

strtok(rcv,"0F")

Die Zeichenkette "0F" wird als zwei einzelne Zeichen interpretiert. Bei ",;", also trenne bei ',' oder ';' macht das Sinn.

daniblpr2020:
... das Problem war für mich dann nur, dass ich nicht weiß wie ich als char[], meine "0F" zu "X" bekomme, da ich bei 0F in strtok() nurnoch Werte bis ...31313a3 bekomme und der Rest verschluckt wird.

Dafür kann man sich eine kleine Funktion basteln, die die Zeichen im Zweierrhythmus abfragt und mit zwei Zeigern (nicht C-Zeiger) durch die Elememte geht, weil sich die Zeichenkettenlänge ja reduziert:

void setup() {
  Serial.begin(9600);
  Serial.println("\nAnfang");
  getData();
}

void ersetze(char * buf, const char ers) {
  byte j = 0, k = 0;
  while (buf[k] != '\0') {
    if (buf[k] == '0' && buf[k + 1] == 'F') {
      buf[j] = ers;
      j = j + 1;
      k = k + 2;
    } else {
      buf[j] = buf[k];
      buf[j + 1] = buf[k + 1];
      j = j + 2;
      k = k + 2;
    }
  }
  buf[j] = '\0';
}

void getData() {
  char rcv[] = "310FCD0FCD0FCD0F4C0F31313a30100F31333a3030";
  Serial.println(rcv);
  ersetze(rcv, ';');
  Serial.println(rcv);
  char * pside = strtok(rcv, ";");
  char * pname = strtok(NULL, ";");
  char * pstate = strtok(NULL, ";");
  char * proom = strtok(NULL, ";");
  char * pday = strtok(NULL, ";");
  char * ptbegin = strtok(NULL, ";");
  char * ptend = strtok(NULL, ";");

  Serial.println(pside);
  Serial.println(pname);
  Serial.println(pstate);
  Serial.println(proom);
  Serial.println(pday);
  Serial.println(ptbegin);
  Serial.println(ptend);
}

void loop() {}

Es geht auch mit anderen Zeigern:

void setup() {
  Serial.begin(9600);
  Serial.println("\nAnfang");
  getData();
}

void ersetze(char * buf, const char ers) {
  char * j = buf;
  char * k = buf;
  while (k[0] != '\0') {
    if (k[0] == '0' && k[1] == 'F') {
      j[0] = ers;
      j = j + 1;
      k = k + 2;
    } else {
      j[0] = k[0];
      j[1] = k[1];
      j = j + 2;
      k = k + 2;
    }
  }
  j[0] = '\0';
}

void getData() {
  char rcv[] = "310FCD0FCD0FCD0F4C0F31313a30100F31333a3030";
  Serial.println(rcv);
  ersetze(rcv, ';');
  Serial.println(rcv);
  char * pside = strtok(rcv, ";");
  char * pname = strtok(NULL, ";");
  char * pstate = strtok(NULL, ";");
  char * proom = strtok(NULL, ";");
  char * pday = strtok(NULL, ";");
  char * ptbegin = strtok(NULL, ";");
  char * ptend = strtok(NULL, ";");

  Serial.println(pside);
  Serial.println(pname);
  Serial.println(pstate);
  Serial.println(proom);
  Serial.println(pday);
  Serial.println(ptbegin);
  Serial.println(ptend);
}

void loop() {}

Inwieweit diese Vorverarbeitung sinnvoll ist, hängt vom Zusammenhang ab, denn man könnte auch gleich auf mehrere Variablen oder Feldelemente verteilen:

void setup() {
  Serial.begin(9600);
  Serial.println("\nAnfang");
  getData();
}

char * zeiger(char * p) {
  char * r = strstr(p, "0F");
  r[0] = '\0';
  r[1] = '\0';
  r = r + 2;
  return r;
}
void getData() {
  char rcv[] = "310FCD0FCD0FCD0F4C0F31313a30100F31333a3030";
  Serial.println(rcv);
  char * pside = rcv;
  char * pname = zeiger(pside);
  char * pstate = zeiger(pname);
  char * proom = zeiger(pstate);
  char * pday = zeiger(proom);
  char * ptbegin = zeiger(pday);
  char * ptend = zeiger(ptbegin);

  Serial.println(pside);
  Serial.println(pname);
  Serial.println(pstate);
  Serial.println(proom);
  Serial.println(pday);
  Serial.println(ptbegin);
  Serial.println(ptend);
}

void loop() {}

Lesestoff: strstr

In #2 habe ich gerade dies gefunden:

String data[6];
...
  data[6] = ptend;

Das erzeugt einen Speicherkonflikt, der möglicherweise Dein Grundproblem ist. Mit

String data[7];

stürzt das Programm bei ein paar Versuchen auf einem UNO nicht ab.