Benutzerdef. Zeichen in 20x4 LCD-Anzeige

Ich möchte innerhalb der Hauptschleife den Inhalt eines benutzerdefinierten Zeichens verändern. Späteres Ziel: grafische Darstellung eines Wertes als Balkengrafik.

Dafür habe ich folgenden Sketch geschrieben:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x20,16,4);

void setup(void)
{
Serial.begin(9600);
Wire.begin();
lcd.init();
lcd.setBacklight(1);
}

void loop()
{
  lcd.setCursor(0,0);
  for (int i = 0;i<256; i++)
  {
    lcd.print ("f"); //zu Testzwecken
    uint8_t strich[8]= {i,144,144,144,144,144,144,i};
    // wenn die nachfolgende Zeile nicht deaktiviert wird
    // bleibt der sketch ohne Fehlermeldung stehen 
    lcd.createChar(4, strich);
    lcd.write(4);
    delay (1000);
  }
}

Wie im Code vermerkt, bleibt die Anzeige nach Darstellung des “f” stehen. Wenn ich die besagte Zeile deaktiviere; wird dier Wert lcd.write(4); angzeigt und zwar mit einem zufälligen Zeichenmuster, was ja durchaus auch verständlich ist. In einem anderen Sketch liegt die Definition von strich() außerhalb von setup() und loop(). Da wird das benutzerdefinierte Zeichen angezeigt.

Was habe ich falsch gemacht? Zusätzliche delay(1000); helfen auch nicht.

Eberhard

eberduino: uint8_t strich[8]= {i,144,144,144,144,144,144,i}; // wenn die nachfolgende Zeile nicht deaktiviert wird // bleibt der sketch ohne Fehlermeldung stehen lcd.createChar(4, strich);

Was soll denn das für ein Sonderzeichen ergeben?

Für ein 8x5 Pixel grosses Zeichen werden 8 Bytes mit je einem 5 Bit Wert übergeben. Ein 5 Bit Wert kann maximal 2^5-1 = 31 gross werden, was sollen denn da die 144 bei der Sonderzeichengenerierung bezwecken?

Und hast Du Dir mal die Programmierbeispiele zur Sonderzeichengenerierung angesehen?

Sonderzeichen werden nicht jedesmal neu generiert, bevor eins ausgegeben wird, sondern Sonderzeichen werden in den Beispielen generiert, bevor irgendwas ausgegeben wird, typische Reihenfolge im setup(): lcd.createChar(...); // erst das Sonderzeichen erzeugen lcd.begin(...); // dann die Ausgabeverarbeitung starten lcd.write(...); // dann die Zeichen ausgeben

Nach vielem Rumprobieren habe ich es gefunden, habe aber keine Ahnung, warum es funktioniert. Reines try and error - Verfahren.

Wenn ich die Zeile lcd.write(4); vor die Zeile uint8_t strich[8]= {i,144,144,144,144,144,144,i}; setze, bleibt nichts stehen und der neue Wert wird im Display angezeigt.

Kann mir jemand erklären, warum es jetzt funktioniert?.

Gruß Eberhard

Die Werte der Sonderzeichen habe ich aus dem Custom Character Calculator http://www.dinceraydin.com/lcd/charcalc.htm. Der Calculator geht tadellos. der Wert 144 - 128 (nicht veränderbar) = 16. Dann bin ich wieder in Deinem Bereich 0 bis 31. Der Wert 16 funtioniert genau so.

Das erklärt leider nicht wieso es funktioniert. Mein Problem ist dann gegenwärtig, wenn man/frau mehr als 8 Sonderzeichen benutzen möchte.

Gruß Eberhard

eberduino: Mein Problem ist dann gegenwärtig, wenn man/frau mehr als 8 Sonderzeichen benutzen möchte.

Und wie viele Sonderzeichen - laut Datenblatt - werden von dem LCD-Display unterstützt?

Habe eine HD44780-kompatible Anzeige 20x4. Die sollte nur 8 freidefnierbare Zeichen habe. Ich probiere es mal aus, ob da noch mehr drin ist :)

Eberhard

Nach acht Zeichen wird das erste Zeichen wieder überschrieben --> ergo definitiv nur 8 frei definierbare Zeichen. Mehr ist nicht drin. Schade!

Gruß Eberhard

Wenn Du selbstdefinierte Zeichen nicht benutzt kannst Du sie umprogrammieren. Das heißt Du kannst 8 selbstdefinierte Zeichen gleichzeitig darstellen (die einzelnen Zeichen auch mehrmals) und die Zeichen müssen nicht die ganze Zeit die gleichen sein. Grüße Uwe

@uwe

...und die Zeichen müssen nicht die ganze Zeit die gleichen sein.

Das war ja genau ja auch mein Bestreben. In meinem ursprünglichen Sketch war die zeile lcd.write(4);offensichtlich an der falschen Stelle. Ergebnis: nix wurde angezeigt. Nachdem die Zeile versetzt wurde klappt es. Kannst Du erklären warum?

Ich möchte nicht nur, dass es funktioniert, sondern auch verstehen. Sonst kann man nichts lernen.

gruß Eberhard

eberduino: In meinem ursprünglichen Sketch war die zeile lcd.write(4);offensichtlich an der falschen Stelle. Ergebnis: nix wurde angezeigt. Nachdem die Zeile versetzt wurde klappt es. Kannst Du erklären warum?

Ich möchte nicht nur, dass es funktioniert, sondern auch verstehen. Sonst kann man nichts lernen.

Soweit ich das Datenblatt verstehe, gibt es beim HD44780 Controller zwei verschiedene Arten von RAM-Speicher, und per Befehl wird festgelegt, welcher RAM-Speicher angesprochen wird.

Es gibt das "CGRAM" (Character Generator Random Access Memory, zum Speichern der Zeichencodierung) und das normale "DDRAM" für den Zeichenspeicher (welche Zeichen wo auf dem Display gezeigt werden sollen).

Befehle zur Definition neuer Zeichen schalten auf das CGRAM. Befehle zur Änderung der Cursorposition schalten auf das DDRAM.

Nur "Befehle", nicht aber "Daten" an den Controller ändern die Art des RAMs, auf das zugegriffen wird.

Und wenn der letzte Befehl war "Schalte auf das CGRAM zum Speichern eines benutzerdefinierten Zeichens", dann wird nach diesem Befehl NICHT automatisch zurückgeschaltet vom CGRAM-Zugriff auf den DDRAM-Zugriff, sondern das muss per Befehl gemacht werden.

Erst wenn Du nach der Definition eines neuen Zeichens einen Befehl gibst, der die Cursorposition beeinflusst, wird wieder auf das DDRAM umgeschaltet und Du kannst wieder Zeichen auf dem Display ausgeben.

Also nach dem Definieren eines neuen Zeichens immer erst einen "Befehl" geben, mit dem der Cursor positioniert wird, als da beispielsweise wären: - clear - home - setCursor(uint8_t, uint8_t)

Also nach einem createChar immer zuerst einen dieser Befehle verwenden, bevor irgendwas mit print oder write ausgegeben wird, dann wird auch der richtige und beabsichtigte Speicherbereich im Controller beschrieben.

… also habe ich im ursprünglichen Sketch ganz oben die Cursorpositionierung unmittelbar vor den Befehl lcd.write(i) gesetzt. Und was sehe ich?? Das war’s.

1000 Dank für die Hilfe, Diskussion und Erläuterung.

Guten Rutsch ins Neue Jahr für Alle hier im Forum.

Eberhard