Umlaute mit der Lib Max72xxPanel.h und Adafruit_GFX.h darstellen [gelöst]

Hallo und guten Abend zusammen,
bin gerade dabei meine Matrix 8x32 Anzeige für die Rennbahn endlich fertig zu machen. Wenn da nicht die Umlaute wären..... mein erster Ansatz war "replace"
um zumindest die Fragezeichen gegen fehlende ü-Punkte zu ersetzen, leider Fehlanzeige. Das ersetzte ü wird dann so -u dargestellt.

Das war mein Versuch....

        case 'F':                                 // Fahrername für die Spur
          strcpy(F, strtok(NULL, " ")); // F= Jan Dürholt 
          strcat(F, " ");
          strcat(F, strtok(NULL, " "));
          Serial.println(F);  
          replace (F, 'ü','u');
          replace (F, 'ß','ss');
          Serial.print(F);
          break;

void replace( char * str, const char old, const char _new )
{
  while(*str)
  {
    if( *str == old ) *str = _new;
    str++;

  }
}

Dann bin ich auf diesem Beitrag aufmerksam geworden....klingt vielversprechend
Umlaute in String liefern Fragezeichen](Umlaute in String liefern Fragezeichen)

Leider kann ich mit der lib MD MAX72xx nicht arbeiten... braucht einfach zuviel Speicherplatz.Da kann ich zwar durch ändern der Font aus einem ? ein ü auf der Matrix anzeigen lassen, aber A mit der lib komme ich nicht so zurecht und B der Speicherplatz. Auch wegen Platzmangel im Gehäuse kommt der NANO leider nur in Frage.

Gibt es da noch eine andere Möglichkeit mit den o.g. Lib's ?
Bedanke mich vorab....
Viele Grüße aus dem Tal

Matrix_Empfaenger_NANO_V1.01.ino (16.3 KB)

Du schreibst überall lib MAX72xx.h und
in deinem Sourcecode verwendest du die lib MAX72xx

dann sagst du

Welches sind denn die anderen oben genannten libs?

Wenn es unbedingt die Größe eines Nanos haben muss dann nimm einen Teensy 4.0
https://www.pjrc.com/store/teensy40.html


Flash und RAM SATT

Da kannste dann gleich noch das Spiel Pong mit integrieren
Ist bei Antratek vorrätig

oder wenn der zu teuer ist und 10 IO-pins reichen

Seeeduino XIAO

vgs

Hallo StefanL38,
ich gebe zu es ist etwas verwirrend die eine Lib heißt MD MAX72xx.h und die andere MAX 72xxPanel.h die ich auch gerade verwende und um die es gerade geht.

Der Teensy 4.0 ist ja ein richtiger Kraftzwerg, das muss ich mir mal näher ansehen. Aber bei 8 Anzeigen ist das schon ne stolze Summe.

Danke für deine Tipps

Wie viel IO-pins brauchst du?
Ich habe mir die Libs installiert und dann für Seeeduino XIAO kompilieren lassen

Der Sketch verwendet 50016 Bytes (19%) des Programmspeicherplatzes. 
Das Maximum sind 262144 Bytes.

3 I/O für die Taster und halt SPI plus einen I/O für CS der Matrix. Serial wäre nicht schlecht muss aber nicht unbedingt sein.

Und wenn man die Pins jetzt durchzählt auf was für eine Zahl kommt man dann?

Das klingt sehr gut, kommt zwar noch was bei aber der sollte reichen. :wink:

** 7 ** damit möchtest du bestimmt sagen, nehme den XIAO.

Werde mir das mal durch den Kopf gehen lassen…oder vielmehr einen bestellen und testen.

Bei Berrybase 5,60 Euro
hach f.... nicht vorrätig

Danke für den Hinweis, mal gucken ob ich damit was hinbekomme.

Distrelec

oder Eckstein

1 Like

Da meine LCD Library "Umlaute" - behandeln kann, habe ich mir gedacht das könnte man vieleicht reusen.

Ich habe in der utitilty/NoiascaUTF8.h ein Mapping von den meisten Latin-Zeichen (in UTF8) auf reine ASCII Zeichen.

Wenn man sich da einen Konverter schreibt, könnte man von einem Char Array mit UTF-8 Sonderzeichen auf reines ASCII umschlüsseln.

ca so

#include <NoiascaLiquidCrystal.h>       // download library from https://werner.rothschopf.net/202009_arduino_liquid_crystal_intro.htm 
//#include <utility/NoiascaUTF8.h>      // this is the needed file, but you must include the library
const uint8_t charNum = 26;             // max Anzahl Zeichen (derzeit Fahrername (25+1))
char f[charNum] = {0};                  // Fahrername

char n[charNum] = {0};                  // a new variable for the converted plain ASCII name
uint32_t special = 0;                   // temp storage for UTF-8 bytes

// convert UTF-8 characters to ASCII
void convert(char * in, char * out)
{
  size_t j = 0;
  for (size_t i = 0; i < charNum; i++)
  {
    uint8_t value = in[i];
    // überschreibe gegebenenfalls value mit dem gemappten ASCII character
    uint8_t printable = convert_generic(special, value, lang_gmw, sizeof(lang_gmw)/sizeof(lang_gmw[0]));  // west germanic languages
    //uint8_t printable = convert_generic(special, value, UTF8_ASCII, sizeof(UTF8_ASCII)/sizeof(UTF8_ASCII[0]));  // full Latin mapping
    if (printable)
    {
      out[j] = value;
      j++;
    }
    if (value == 0) break;
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("convert Latin UTF-8 to plain ASCII"));

  strcpy(f, "Jän Dürhölt ß");  // einlesen
  Serial.println(f);
  convert (f, n);
  Serial.println(n);
}

void loop() {
  // put your main code here, to run repeatedly:

}

gibt folgendes aus:

convert Latin UTF-8 to plain ASCII
Jän Dürhölt ß
Jan Durholt s

Und da das ganze Latin Mapping vieleicht wirklich zu umfangreich ist, könnte man sich auch auf die Westgermanischen Sprachen beschränken. Daher das lang_gmw statt UTF8_ASCII

Das "convert_generic" braucht Referenzen auf eine temporäre Variable um eventuelle UTF-8 Mehrbyte - Zeichen zu speichern, den eigentlichen Character der ausgegeben werden soll sowie eine Mapping Tabelle im Progmem und dessen Anzahl an enthaltenen Mappings.
Der Rückgabewert der Funktion gibt an ob der Character ausgegeben werden kann (1..3) oder ob es sich um ein Startbyte/Folgebyte von einem UTF-8 Mehrzeichen Character handelt. Abhängig vom Rückgabewert kopiert man dann also einfach den Character (der eventuell gewandelt) ist - an die nächste Freie Stelle

Sorry für das viele Blabla.

Geht sicher auch einfacher, aber wenn man einen Hammer hat, schaut alles aus wie ein Nagel :wink:

1 Like

Da ich faul bin, suche ich zunächst nach fertigen Lösungen.

Oli als Europäer ist diesbezüglich sensibler als der durchschnittliche Nordamerikaner, behaupte ich einfach mal. Seine Bibliothek U8x8 habe ich mit Max7219 leider nicht zum Laufen gebracht. U8g2 geht dafür mit einer großen Fontauswahl, leider steht die Schrift auf dem Kopf:

#include <Arduino.h>
#include <U8g2lib.h>  // Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
#include <SPI.h>

U8G2_MAX7219_32X8_F_4W_HW_SPI u8g2(U8G2_R0, /* clock= 13, data= 11, cs=*/ 10, /* dc=*/ U8X8_PIN_NONE, /* reset=*/ U8X8_PIN_NONE);

void setup(void) {
  u8g2.begin();
  u8g2.enableUTF8Print();   // enable UTF8 support for the Arduino print() function
  u8g2.setFont(u8g2_font_pxplusibmcgathin_8f);
}

void loop(void) {
  u8g2.clearBuffer();
  u8g2.setCursor(0, 7);
  u8g2.print("äöüßÄÖÜ");
  u8g2.sendBuffer();
  delay(1000);
}

Außerdem hat Oli noch U8g2_for_Adafruit_GFX im Angebot, das zusammen mit Max72xxPanel richtigherum die Fonts von Oli ermöglicht:

#include <SPI.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <Max72xxPanel.h>

Max72xxPanel matrix = Max72xxPanel(10, 4, 1);  // CS, Elemente, Zeilen
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

void setup()
{
  for (uint8_t i = 0; i < 4 ; i++)
  {
    matrix.setRotation(i, 1);                // The Display is Position
  }
  matrix.setIntensity(2);                  // Helligkeit Matrix 0 und 15 0=schwach, 15=sehr hell
  u8g2_for_adafruit_gfx.begin(matrix);                 // connect u8g2 procedures to Adafruit GFX
  u8g2_for_adafruit_gfx.setFont(u8g2_font_pxplusibmcgathin_8f);
}

void loop()
{
  matrix.fillScreen(LOW);
  u8g2_for_adafruit_gfx.setCursor(0, 7);               // start writing at this position
  u8g2_for_adafruit_gfx.print("ÄäöüX");            // UTF-8 string
  matrix.write();
  delay(2000);
}

Man muß bedenken, daß UTF-8-Zeichen aus bis zu vier Byte bestehen können. Daher funktioniert kein 1 zu 1 Tausch. Aber @noiasca hat eine Steilvorlage geliefert, um in Grundbuchstaben zu tauschen. Da der Font von Max72xxPanel durchaus Umlaute im Angebot hat, kann man anstelle der Grundbuchstaben auch Umlaute anzeigen.

Fummelt man schon an der Tabelle, kann man auch den Rest aus der Bibliothek in das eigene Programm kopieren:

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
Max72xxPanel matrix =  Max72xxPanel(10, 4, 1);  // CS (DIN 11, CLK 13), Anzahl Displays horizontal, vertikal

const uint8_t charNum = 26;             // max Anzahl Zeichen (derzeit Fahrername (25+1))
char f[charNum] = {0};                  // Fahrername

char n[charNum] = {0};                  // a new variable for the converted plain ASCII name
uint32_t special = 0;                   // temp storage for UTF-8 bytes

// -- Anfang --------------
// Quelle: https://werner.rothschopf.net/202009_arduino_liquid_crystal_intro.htm
//         utility/NoiascaUTF8.h

// the structure of the UTF8 -> single character (mapping)
struct Mapping {
  uint16_t utf8; // the 2 least significant bytes of the 4 byte UTF-8 character
  uint8_t c;     // the final 1 byte charactter to print
};

constexpr byte NOPRINT = 0;
constexpr byte PRINT = 1;

// West Germanic - gmw
// de en nl (sco fy)
const Mapping lang_max72xxpanel[] PROGMEM = {
  {0xc386,  'A'},     // Æ  LATIN CAPITAL LETTER AE
  {0xc384, 0x8E},     // Ä  LATIN CAPITAL LETTER A WITH DIAERESIS
  {0xc38b,  'E'},     // Ë  LATIN CAPITAL LETTER E WITH DIAERESIS
  {0xc38f,  'I'},     // Ï  LATIN CAPITAL LETTER I WITH DIAERESIS
  {0xc396, 0x99},     // Ö  LATIN CAPITAL LETTER O WITH DIAERESIS
  {0xc39c, 0x9A},     // Ü  LATIN CAPITAL LETTER U WITH DIAERESIS 
  {0xC39F, 0xE0},     // ß 
  {0xc3a4, 0x84},     // ä  LATIN SMALL LETTER A WITH DIAERESIS
  {0xc3a6,  'a'},     // æ  LATIN SMALL LETTER AE
  {0xc3af,  'i'},     // ï  LATIN SMALL LETTER I WITH DIAERESIS
  {0xc3ab,  'e'},     // ë  LATIN SMALL LETTER E WITH DIAERESIS
  {0xc3b6, 0x94},     // ö  LATIN SMALL LETTER O WITH DIAERESIS
  {0xc3bc, 0x81},     // ü  LATIN SMALL LETTER U WITH DIAERESIS
  {0xc4b2,  'I'},     // IJ  LATIN CAPITAL LIGATURE IJ  - somehow - J should be added for Dutch
  {0xc4b3,  'i'}      // ij  LATIN SMALL LIGATURE IJ - somehow - J should be added for Dutch
};

uint8_t convert_generic(uint32_t &special, uint8_t &value, const Mapping *language, size_t lang_len) {
  //Serial.print("D521 convert_SPLC780D1_003A 0x"); Serial.println(value, HEX);
  uint8_t isWriteable = NOPRINT;
  if ((value & 0b11000000) == 0b11000000)        // start byte
  {
    special = value;
  }
  else if ((value & 0b11000000) == 0b10000000)   // sequence byte (Folgebyte)
  {
    special = special << 8;                      // MISSING should get improvement to check on 3rd sequence byte
    special += value;
    if (special > 0xC000 && special < 0xE000)    // if 2 byte character
    {
      isWriteable = PRINT;
    }
    else if (special > 0xE00000 && special < 0xF0000000)   // 3 byte character: 0b11100000 00000000 00000000 im dritten byte von hinten
    {
      isWriteable = PRINT;
    }
    else if (special > 0xF0000000)               // 4 byte character: 0b11110000 ganz vorne
    {
      isWriteable = PRINT;
    }
  }
  else                                                     // not a sequence byte - reset special
  {            
    special = 0;
  }
  if (special == 0)          // Single Character
  {
    // no difference mapping to ASCII needed
    isWriteable = PRINT;     // any other character just send to display
  }
  else if (isWriteable)      // was UTF-8 2 bytes or more
  {
    // Step 1: general ROM Mapping
    // Lookup with in UTF8->ROM Mapping overrides the character to be send to the LCD
    uint16_t index = 0;
    for (size_t i = 0; i < lang_len; i++)
    {
    index = pgm_read_dword_near(&language[i].utf8);
      if (index == (special & 0xFFFF))
      {
        memcpy_P(&value, &language[i].c, 1);
        break;
      }
    }
    // Step 2: Ä Ö Ü overruleUml
    // not in this converter 
    // Step 3: Send
    // any other character just send to display
    special = 0;
    // Step 4: only in Ae Variant to add the e
  }
  return isWriteable;                  
}

// -- Ende  ---------------

// convert UTF-8 characters to ASCII
void convert(char * in, char * out)
{
  size_t j = 0;
  for (size_t i = 0; i < charNum; i++)
  {
    uint8_t value = in[i];
    // überschreibe gegebenenfalls value mit dem gemappten ASCII character
    uint8_t printable = convert_generic(special, value, lang_max72xxpanel, sizeof(lang_max72xxpanel) / sizeof(lang_max72xxpanel[0])); // west germanic languages
    if (printable)
    {
      out[j] = value;
      j++;
    }
    if (value == 0) break;
  }
}

void setup() {
  delay(1000);
  for (uint8_t i = 0; i < 4 ; i++) matrix.setRotation(i, 1);
  matrix.setIntensity(2);                  // Helligkeit Matrix 0 und 15 0=schwach, 15=sehr hell

  strcpy(f, "äöüßÄ");  // einlesen
  convert (f, n);
  matrix.fillScreen(LOW);
  matrix.setCursor(0, 0);
  matrix.print(n);
  matrix.write();
  delay(10000);
}

void loop() {
  /* Zur Anzeige weiterer Zeichen
  static uint8_t z = 0x80;
  if(z<255){
  matrix.fillScreen(LOW);
  matrix.setCursor(0, 0);
  matrix.print(z, HEX);
  matrix.print(' ');
  matrix.print(char(z));
  matrix.write();
  z++;
  }
  */
  delay(1000);
}

Mir gefällt das Ergebnis, Dir auch?

grafik

Ich bin stumm vor Glück....

Das ist ja der n… Wahnsinn, dass was noiasca gemacht hat war ja 100% besser wie die kurulischen Zeichen und hat auch super in meinem Sketch funktioniert, vielen Dank an dieser Stelle. Aber das jetzt….. bin immer noch fasziniert, Hut ab agmue und 1000 Dank. Ich bringe das nun mal in meinen Sketch unter und hoffe dass mein Ram ausreicht.

Derzeit sitze ich noch bei einem Problem mit einer simplen Taster-Abfrage mit <Bounce2.h>
daher habe ich mich noch nicht zurückgemeldet. (TasterSET.fell()) bleibt High und bestätigt mir direkt die nächste Abfrage in meinem Menü…….. :thinking: ich verstehe es einfach (noch) nicht.

Aber wird jetzt warten müssen, nu sind die Umlaute erst mal wieder dran….
Ob ich es heute fertig bekomme weiß noch nicht….Frau wollte schon Foto von mir machen damit sie weiß wie ich aussehe. Hat mich in der letzten Zeit kaum gesehen.Upps

Vielen Dank Ihr lieben Menschen

Wird TasterSET.update(); möglicherweise nicht erreicht?

Viel wichtiger als Anzeigen und Taster!

Auch alte Säcke brauchen gelegentlich einen Tritt in den Hintern :innocent:

Habe fertig... :smiley: :smiley: :smiley: und was soll ich sagen es funktioniert. Freu freu freu, Danke @agmue
Euch Allen die mitwirken... :wink mein Projekt weiterzubringen bzw. zu vollenden , ein Herzliches Dankeschön.

Da stimme ich dir zu 100% zu.

….nach 5 x mal antworten mit “Nur mal eben was ausprobieren…..komme gleich“ ….ist er wirklich spürbar :wink::joy:

Da er im Loop steht sollte er eigentlich doch immer erreichbar sein oder?

Es wäre gut, wenn ja, aber mit blockierender Programmierung kann man das verhindern.

Du kannst loop-Durchläufe mit Ausgaben auf dem seriellen Monitor überprüfen.

Ich habe es überprüft, er läuft durch die loop. Ich denke das mein/unserer Sketch insgesamt hier und da ein wenig bremst. Hab eh gerade ein ganzes Sägewerk vor den Kopf ….versuche @my_xy_projekt LCD Menü aus Taster umzubauen.Und die dazugehörigen Ausgaben dann aber auf die Matrix zu bringen....Ich muss noch viel lernen.

Nun wünsche ich Euch allen einen guten Rutsch ins neue Jahr 2023
Viel Gesundheit und Glück bei allem was Ihr vorhabt.

Der Irre aus dem Tal :wink:
Matrix_Empfaenger_NANO_V1.8.ino (37.3 KB)

Ach schau, da ist noch jemand wach!?
Rutschen wirds nicht, eher vom Winde verweht.

Dir auch alles Gute!