Strings vergleichen und nur bei Änderung auf Display schreiben.

Hallo,

ich habe eine Funktion geschrieben, welches ein LCD-Display schneller updaten soll (lcd.print ist sehr langsam). Dazu habe ich das LCD-Display in 16 Sektoren (4x4) unterteilt und checke alle 150ms, ob sich der String aus dem entsprechendem Sektor auch wirklich geändert hat. Wenn ja, dann wird der entsprechende Sektor neu auf das Display geschrieben, alle Anderen bleiben erhalten und werden nicht aktualisiert. So viel zur Theorie. Dass das Display nur alle 150ms neu beschrieben wird funktioniert schonmal, aber leider werden immer alle Sektoren neu beschrieben, ob sich der Text geändert hat oder nicht. Ich vermute, es liegt an dem Vergleich der Strings mit den “alten” Strings, jedoch kann ich keinen Fehler erkennen.

void writeLCD(int x, int y, String text1) {
 String text[4][4];
 String text_old[4][4];
 text[x][y]=text1;


  if (timer - LCD_timer >= 150) {
    for (int i = 0; i < 4; i++) {
      for (int j = 0; j < 4; j++) {
        if (text[i][j] != text_old[i][j]) {
          lcd.setCursor(x * 5, y);
          lcd.print(text[i][j]);
          text_old[i][j]=text[i][j];
        }
      }

    }

   
    LCD_timer = timer;
    
  }
}

Du solltest keine Strings benutzen und diese dann wie Char-Arrays behandeln. Das funktioniert nicht.

char text[4][4];

Ist das, was Du willst.

Gruß Tommy

Tommy56:
Du solltest keine Strings benutzen und diese dann wie Char-Arrays behandeln. Das funktioniert nicht.

char text[4][4];

Ist das, was Du willst.

Gruß Tommy

Ich möchte keinen Char-Array, sondern einen String-Array. Also einen Array, welcher 4x4 Strings beinhaltet.

Die Klasse String ist für den Arduino ungeeignet, weil sie den Speicher fragmentiert.

Gruß Tommy

Edit: Wenn Du sie trotzdem verwenden möchtest, schaue in die Reference.

Ich möchte keinen Char-Array, sondern einen String-Array. Also einen Array, welcher 4x4 Strings beinhaltet.

Dann musst du auch mit den Folgen leben.

Eine Folge ist:

if (text[i][j] != text_old[i][j])

Dass obwohl in den jeweiligen String die gleichen Buchstaben drin sind, sich doch die Objekte unterscheiden. Denn es sind unterschiedliche Instanzen.
Damit schlägt der Vergleich fehl

Ich stimme Tommy zu:

Ich möchte keinen Char-Array, sondern einen String-Array. Also einen Array, welcher 4x4 Strings beinhaltet.

Nein, das möchtest du nicht!

Lesetipp

danke für die Antworten. Ich habe mich auf https://www.arduino.cc/en/Tutorial/StringComparisonOperators
bezogen, demnach ist ein Vergleich (der Inhalte) zweier Strings möglich :-\

Dann lass Dir doch mal die Partner am Vergleich ausgeben:

Serial.print("->");Serial.print(text[i][j]); 
Serial.print("<->"); Serial.print(text_old[i][j]);Serial.println("<-")
if (text[i][j] != text_old[i][j]) {

Gruß Tommy

habe ich ebend gemacht zur Kontrolle: ->Hallo<->Hallo<-
text_old ist definitiv gleich text*. Trotzdem greift die Bedingung != nicht. Ich bin ratlos. Das habe ich dadurch überprüft, indem ich einmal lcd.clear() aufgerufen habe, und Hallo immer noch da steht, dh. es wurde wieder aufs LCD geschrieben…*

Probiere mal als Vergleich:

if (!text[i][j].equals(text_old[i][j])) {

Gruß Tommy

Tommy56:
Probiere mal als Vergleich:

if (!text[i][j].equals(text_old[i][j])) {

Gruß Tommy

leider kein Erfolg.

ItsUnreal:
danke für die Antworten. Ich habe mich auf https://www.arduino.cc/en/Tutorial/StringComparisonOperators
bezogen, demnach ist ein Vergleich (der Inhalte) zweier Strings möglich :-\

Tja…
Das habe ich doch glatt noch nie getestet!

Naja, dann lasse ich dich doch mal machen…

Ich auch noch nie, weil die Klasse String auf dem Arduino meist Mist ist (und reserve() sowieso keiner verwendet).
Ein ordentliches strcmp genügt doch völlig.

Gruß Tommy

combie:
Dass obwohl in den jeweiligen String die gleichen Buchstaben drin sind, sich doch die Objekte unterscheiden. Denn es sind unterschiedliche Instanzen.
Damit schlägt der Vergleich fehl

Verwechselt du das nicht mit Java u.ä reinen OOP Sprachen? In bestimmten anderen Sprachen vergleicht == die Adressen der Objekte. Aber das liegt daran dass da alle Objekt-Variablen Referenzen sind und alle Klassen von einer absoluten Oberklasse wie Object abgeleitet sind. Das gilt nicht für C++. Damit man hier überhaupt == aufrufen kann muss der Operator in der Klasse überladen sein und damit existiert eine Implementierung für einen Vergleich des Inhalts

C# ist in gewisser Weise ein Sonderfall. Der vergleicht == normalerweise die Referenzen. Aber für String Objekte den Inhalt

Verwechselt du das nicht mit Java u.ä reinen OOP Sprachen?

Durchaus!

Wenn ich sie mal gebraucht hätte..... die String klasse... wäre das ein Grund gewesen sich kundig zu machen.
Aber bis jetzt gings auch ohne, meine alten C Kenntnisse waren bisher für alles ausreichend.

Das veranlasst mich zu 2 Dingen:

  1. In diesem Thread werde ich (zum Thema) die Klappe halten
  2. Mich bei Gelegenheit Kundig machen

Operator Überladung und der Umgang mit Referenzen ist mir eigentlich nicht fremd.

Wie sagt man: Eine Transferfehlleistung?

Hallo,

wenn das funktionieren soll, dannmüssen die Arrays aber static sein, sonst sind sie beim Verlassen der Funktion weg.

void writeLCD(int x, int y, String text1) {
 static String text[4][4];
 static String text_old[4][4];
 text[x][y]=text1;

sollte helfen oder eben die Arrays global anlegen.

Ansonsten geht ein Stringvergleich mit der Stringklasse mit = genau so.
Das man auf kleinen AVR mit wenig Ram die Stringklasse mit Vorsicht nutzen sollte, wurde schon erwähnt.

Gruß aus Berlin
Michael

amithlon:
Hallo,

wenn das funktionieren soll, dannmüssen die Arrays aber static sein, sonst sind sie beim Verlassen der Funktion weg.

void writeLCD(int x, int y, String text1) {

static String text[4][4];
static String text_old[4][4];
text[y]=text1;




sollte helfen oder eben die Arrays global anlegen.

Ansonsten geht ein Stringvergleich mit der Stringklasse mit = genau so.
Das man auf kleinen AVR mit wenig Ram die Stringklasse mit Vorsicht nutzen sollte, wurde schon erwähnt.

Gruß aus Berlin
Michael

Das war es! Jetzt funktioniert es. Vielen Dank!
Nochmal um mein Wissen zu erweitern: Ich habe durch static String text[4][4];
static String text_old[4][4]; 32 Strings. Was kann im schlimmsten Fall passieren? Sind die Folgen auch davon abhängig, wie lang die Strings sind? Ich nutze einen Due.

Im schlimmsten Fall bleibt Dein Programm nach einer mehr oder wenig langen Zeit stehen oder produziert unerklärliche Fehler.
Es gibt (anders als in JAVA und ähnlichen Sprachen) keinen Hintergrundprozess, der den Müll aufräumt.

Ich versuche es mal vereinfacht zu erklären.

Du hast einen String von 10 Zeichen und dahinter eine andere Variable. Jetzt hängst Du ein Zeichen ran.
An der alten Stelle ist kein Platz, also wird ein neuer freier Platz für 11 Zeichen gesucht (und am Anfang auch gefunden). Zurück bleibt ein Loch von 10 Zeichen.
Wenn das Ganze dann eine Weile gelaufen ist, hast Du viele kleine Löcher aus freiem Speicher aber keinen Platz für einen längeren String mehr, obwohl die Summe der freien Plätze ausreichen wäre. Aber eben keinen freiein Speicher am Stück.
Das war jetzt stark vereinfacht, sollte aber das Problem verständlich machen können.

Evtl. könntest Du mit reserve(4) im Setup in einer Schleife feste Längen reservieren. Das löst aber nicht die Probleme der anderen Strings.

Deswegen wird auf den Arduinos in der Regel darauf verzichtet.

Gruß Tommy

ItsUnreal:
Nochmal um mein Wissen zu erweitern: Ich habe durch static String text[4][4];
static String text_old[4][4]; 32 Strings. Was kann im schlimmsten Fall passieren? Sind die Folgen auch davon abhängig, wie lang die Strings sind? Ich nutze einen Due.

Auf einem Due sollte das keine Probleme hervorrufen, da gibt es eine Menge mehr RAM.

Hallo,

schön wenn es jetzt klappt. Auf die möglichen Probleme hat ja Tommy56 schon ausreichend hingewiesen.
Vielleicht als Orientierung: mein Webserver auf dem ESP8266 hat 50k Ram frei für dynamische Variablen und Heap. Unter ca. 20k free heap wird er instabil, weil ja WLAN, HTTP-Client usw aus den Bibliotheken auch Ram belegen. Real sind im Betrieb ca. 35kB Heap frei. Wenn ich einen String mit mehr als 6kB Größe mit etlichen String.replace zum Ersetzen der Platzhalter durch Variablenwerte bearbeite, stürzt er reproduzierbar mit Speichermangel ab. Praktisch sind meine längsten HTML-Strings ca. 2,5kB, damit ist er "ewig" im stabilen Bereich. Der Due hat ähnlich viel Ram, wieviel der Core da selbst belegt kann ich nicht sagen, nutze keinen Due.

Gruß aus Berlin
Michael