Problem mit Sonderzeichen auf dem LCD-Display (Hitachi HD44780)

Auf dem LCD-Display (2x16-Zeichen, Hitachi HD44780, Nutzung der Standard-LiquidCrystal Library) möchte ich Texte mit Umlauten (äöü) und Gradzeichen (°) ausgeben.

Dies geht nicht, statt Umlauten (z.B. ä) kommen 2 japanische Zeichen.

Ich versuche nun zur Diagnose den Text Zeichenweise auszugeben und im Falle eines Sonderzeichens, den entsprechenden ASCII-Code auszugeben (Programmauszug siehe unten).
Funktioniert prinzipiell aber: Vor dem Sonderzeichen kommt immer noch ein japanisches Zeichen.

Dieses wird auch ausgeben, wenn (siehe Code) z.B. im Falle von "ä" statt z = char(225); folgendes benutze z = 'x';

Beispiel zur Illustration (% steht hier für das japanische Zeichen, wobei vor dem ° ein anderes jap. Zeichen steht als bei äöü).

"n%ämlich (100 %°C), m%üssen, k%önnen"

Wer hat eine Idee oder sehe ich den Wald vor lauter Bäumen nicht? Danke für jeden Hinweis. :wink:

...
  String text = "nämlich (100 °C) müssen, können";
  int  i = 0 ;
  int  n = 0 ;
  char z = ' ';
...
// (Loop durch ganzen String, i = aktuell auszugebendes Zeichen)
...
z = text.charAt(i);
    
    // Allfällige Sonderzeichen konverieren

    switch (z) {

      case 'ä':
        z = char(225); 
        break;
        
      case 'ö':
        z = char(239);
        break;
        
      case 'ü':
        z = char(245);
        break;
        
       case '°': 
        z = char(223);     
        break; 
    } 
    // Aktuelles Zeichen auf Display ausgeben
    lcd.write(z);
...

Den HD44780 gibt es mit verschiedenen Zeichensätzen. Alle haben die Standartbuchstaben a-z und je nach Version, Europäische Sonderzeichen, Japanische oder Kundenspezifische. (siehe Seite 2 von http://www.adafruit.com/datasheets/HD44780.pdf)
Seite 17 und 18 des gleichen Dokuments findest Du auch alle darstellbaren Zeichen.

Falls die Zeichen die Du brauchst nicht dabei sind kannst Du 8 Zeichen selbst definieren.
Näheres bei: LiquidCrystal - Arduino Reference der LiquidCrystal- Bibliothek

Viele Grüße Uwe

Danke für die Rückmeldung. Es ist ja so, dass meine Sonderzeichen im entsprechenden Zeichensatz erhalten und korrekt dargestellt werden. Mich irritiert mehr, warum bei der Ausgabe zusätzlich noch ein japanisches Zeichen erscheint.

Ich bin einen Schritt weiter. Das Problem scheint darin zu liegen, dass man in einer Variable/String definierte Umlaute nicht direkt ausgeben kann.

// Hinweis: £ steht für ein japanisches Zeichen

// include the library code:
#include <LiquidCrystal.h>

char text[] = "äöü°";


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(11, 9, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  
}

void loop(){
  
  // Case 1
  lcd.clear();
  lcd.home();
  lcd.write(text[0]);
  lcd.write(text[1]);
  lcd.write(text[2]);
  // Output is £££
  delay (1000);
  
  // Case 2
  lcd.clear();
  lcd.home();
  lcd.write(char(225));
  lcd.write(char(239));
  lcd.write(char(245));
  // Output is äöü
  delay (1000);
  
  // Case 3
  lcd.clear();
  lcd.home();
  lcd.write(text[3]);
  lcd.write(char(239));
  // Output is &ö
  delay(1000);
  
}

hallo borav

case 1: ist klar wieso falsche Zeichen ausgegeben werden: weil die Ascii-Kode der Umlaute nicht den Displaykode entsprechen.
case 2: sind die richtigen Displaycode für die Umlaute.
case 3: ist eine Mischung aus case 1 und case 2.

Das Problem ist, daß:
case 'ä':
z = char(225);
break;
nicht den Kode für ä produziert sondern 2 Werte.
(habs nicht auf einem Display kontrolliert sondern auf dem Terminal).

Weiter kann ich Dir leider nicht helfen.

Grüße Uwe

Danke Uwe für die Antwort.

nicht den Kode für ä produziert sondern 2 Werte.

Wie meinst Du das?

Das funktioniert ja auch auf meinem Display.

Wie löst man das sonst, wenn man einen String mit Umlauten z.b. "123äöü" auf einem LCD-Display ausgeben möchte?
Ich muss ein Arudino-Projekt vorbereiten, wo man längere Texte im Code eingeben sol. Natürlich könnte man dort manuell die Umlaute entsprechend ändern, aber das sollte doch automatisch gehen. Ich vermute dass beim Zugriff auf einen Char (z.B. text*) irgend etwas seltsames für einen Umlaut zurückkommt.*

Ich nehme an dass der Buchstabe, hier zum Beispiel 'ä', in der Textdatei des Quellcodes als UTF-8 abgespeichert wird (anstatt zum Beispiel ISO 8859-15, dem ANSI-Zeichensatz mit Euro). Dies bedeutet, dass Sonderzeichen, die nicht im ASCII-Zeichensatz enthalten sind (darunter fallen auch Umlaute) 16 Bit groß sind anstatt 8. Damit belegen sie auch 2 Plätze im String. Dein Switch/Case castet dann 'ä' auf 'ä'&0xFF, also nur auf das Low-Byte des 2-Byte-Zeichens. Das High-Byte läuft ungeparst durch deinen Sonderzeichen-Handler und taucht damit auf dem LCD auf.
UTF8 sieht so aus:
ä=0xC3A4, das entspricht in ANSI (und auf A02-LCDs) ä, auf A00-LCDs dem Katakana te und einem kleinen diagonalen Strich, der wahrscheinlich irgendwelche Bedeutung als Satzzeichen oder so etwas hat.
ö=0xC3B6 = ANSI ö = te ka
ü=0xC3BC = ANSI ü = te shi
Und das andere japanische Zeichen beim Grad-Symbol ist auch erklärt:
°=0xC2B0 = ANSI ° = tsuu (tsu mit Chouonpo, einem Verlängerungszeichen)
Ein

case 'Â':
case 'Ã': continue;

sollte zumindest für Umlaute, Grad und ß das Problem lindern.

Schön, Jemand der Japanisch kann (meine Hochachtung)! Und Danke für die gute Erklärung.

Eigentlich, soweit war ich auch schon, daß ein 16bit Wert verschickt wird.
Die Frage ist, wie vermeidet man das? Ich bin da auch am Ende meiner Weißheit.

Viele Grüße Uwe

Auch von meiner Seite her Dankeschön - die Ursache ist also verständlich erläutert und geklärt, jetzt wird noch die "Therapie" gesucht :wink:

uwefed:
Schön, Jemand der Japanisch kann (meine Hochachtung)! Und Danke für die gute Erklärung.

Eigentlich, soweit war ich auch schon, daß ein 16bit Wert verschickt wird.
Die Frage ist, wie vermeidet man das? Ich bin da auch am Ende meiner Weißheit.

Viele Grüße Uwe

Was heißt japanisch kann, ich bin bei japanischen Serien immer noch sehr auf Übersetzer angewiesen. Ich verstehe nur einige wenige Wörter, die Zuordnung der Zeichen aus dem Schriftsatz zu den Katakana hab ich aus ner Tabelle.
Wie ich bereits in meinen Post editiert habe, könnte man zum Beispiel die Extra-Zeichen mit einem case DASZEICHENDASSTOERT continue; abfangen, andernfalls muss man die IDE dazu überreden, ANSI statt UTF-8 zu nehmen. Wenn man die IDE aber mit ANSI-Sonderzeichen füttert, wirft sie Mist aus, weil sie nativ UTF-8 verwendet. Ist ja auch ein praktischer Zeichensatz, aber zum Programmieren nicht unbedingt geeignet.

case 'Â':
case 'Ã': continue;

von gerade wird aus dem gleichen Grund auch nicht funktionieren, daher müsste es eher sowas wie

case 0xC2:
case 0xC3: continue;

sein.
Wenn man bedenkt, dass sich das Arduino-Team (bzw. genauer gesagt das Processing-Team) extra die Mühe gemacht hat, den Code in UTF8 zu kodieren. Die sind qua si daran schuld dass dieser Fehler auftritt und eine Anfrage nach Rettung wurde abgelehnt: Google Code Archive - Long-term storage for Google Code Project Hosting.
Man könnte vielleicht die Zeichen gleich als UTF-8-Doppelzeichen abfangen. So könnte man zum Beispiel iterieren:

char prevchar = 0;
for(byte i=0;data[i]!=0;i++){
if (!prevchar && (data[i]&0xFF)){
 prevchar = data[i];
 continue;
}
short combochar = (prevchar<<8) + data[i];
prevchar = 0;
/* 16-Bit Handler */
}

Ich weiß aber nicht ob das mit dem Vergleich dann besser klappt, und 16bit ist für den Prozessor etwas schwerer verdaulich als 8, und demnach langsamer. Wenn nicht, dann kann man einfach prevchar=0 nach hinten schieben, combochar weglassen und in Situationen wie case 'ä' im Zweifelsfall noch prevchar prüfen.