Darstellung großer Ziffern auf LCD 20X4 hochkannt

Hallo Zusammen

da ich einen größeren Posten LCDs 4Zeilig 20Spalten, bekommen habe, möchte ich eine JumboUhr bauen.
Meine Idee sieht wie folgt aus:Mehrere Displays möchte ich hochkannt nebeneinander stellen und jeweils eine Zahl der Uhrzeit auf einem LCD (hochkannt) darstellen.Mehrere Displays sollten dann nebeneinander stehen.
Die einzelnen Displays möchte ich mitels I²C ansteuern.
Es gibt zwar im Netz mehrere Beschreibung die sogar auf einem 20X4 LCD große Ziffern darstellen, doch ich möchte das Ganze eben noch etwas größer.
Ist es möglich die Sketche so umzuschreiben dass ganz große Ziffern entstehen?

Schon im Vorraus vielen Dank Rudi

Rudi01:
Schon im Vorraus vielen Dank Rudi

Möglich ist vieles.

Aber hast Du Dir mal vorgestellt, wie verzerrt Zeichen aussehen würden, die 20 "Pixel" hoch und dabei nur 4 "Pixel" breit dargestellt werden?

Unabhängig von der konkreten Ausführung, am Beispiel der Ziffer 2, mit 4 Zeichen Breite und 20 Zeichen Höhe ganz grob dargestellt:

---+
   |
   |
   |
   |
   |
   |
   |
   |
+--+
|
|
|
|
|
|
|
|
|
+---

Dreh mal das LCD hochkant, das hat dann schon das Format einer Ziffer, ist meines Erachtens also durchaus machbar. Letztlich würde ich die einzelnen Ziffern wohl aus ganzen Blöcken, also ausgefüllten 5x8-Stellen bauen. Dazu muss man nicht einmal Sonderzeichen bauen.
I2C ist natürlich immer so eine Sache, wenn die Module es gestatten unterschiedliche Adressen anzulegen, sollte das wohl klappen.

Es gibt 2 verschiedene Ausführungen der I2C Adapter, jeder kann (besser gesagt sollte können) auf 8 verschiedene Adressen eingestellt werden. Von daher schon mal kein Problem, bis zu 16 Displays wären möglich.
Der Rest ist Fleißarbeit.

Du legst byte Arrays oder structs mit 80 Stellen für die Ziffern an, d.h. jede Stelle im Display ist ein "Pixel", und schreibst dir eine Kleine Routine, die das ganze ausgibt. Stichwort Zeichensatz für Grafikdisplays.
Idealerweise legst du das Array ins Flash, da es doch einiges an Speicher braucht.

Wenn du es komplizierter und speichersparender machen willst, kannst du das ganze auch bitweise in den Bytes ablegen, dann braucht eine Ziffer nur noch 10 statt 80 Bytes. Aber das dann im nächsten Schritt.

Hallo Zusammen

vielen Dank für Eure Antworten.
Das Prinzip habe ich grob verstanden , allerdings hapert es noch an der Umsetzung.
Leider konnte ich keine deutsche Beschreibung darüber finden.
Kennt eventuell jemand einen Link?

Grüße Rudi

Rudi01:
Das Prinzip habe ich grob verstanden , allerdings hapert es noch an der Umsetzung.
Leider konnte ich keine deutsche Beschreibung darüber finden.
Kennt eventuell jemand einen Link?

Ich habe zwar kein 20x4 Display, aber ich habe mal trotzdem versucht, Dir ein kleines Beispielprogramm für 4 Ziffern (0,1,2,3) zu machen, das mit nur zwei verschiedenen Zeichen auskommt (voller Block oder leerer Block), und das daher binär mit Nullen und Einsen codiert werden kann.

1 == voller Block
0 == leerer Block

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);

long digits[][4]={
  { // 0
    0b11111111111111111111,
    0b10000000000000000001,
    0b10000000000000000001,
    0b11111111111111111111, 
  },
  { // 1
    0b00000000000000000000,
    0b11111111111111111111,
    0b00000000000000000000,
    0b00000000000000000000,
  },
  { // 2
    0b11111111110000000001,
    0b10000000010000000001,
    0b10000000010000000001,
    0b10000000011111111111,
  },
  { // 3
    0b11111111111111111111,
    0b10000000010000000001,
    0b10000000010000000001,
    0b10000000010000000001,
  },
};

void showDigit(byte d)
{
  for (int i=0;i<4;i++) // print 4 lines
  {
    lcd.setCursor(0,i);
    for (int j=19;j>=0;j--) // from high-bit to low-bit
    {
      byte bit=bitRead(digits[d][i],j);
      if (bit)
      {
        lcd.print('\377');
        Serial.print('X');
      }
      else
      {
        lcd.print(' ');
        Serial.print(' ');
      }
    }
    Serial.println();
  }
  Serial.println();
  
}


void setup()
{
  Serial.begin(9600);
  lcd.begin(20,4);
  
}


void loop()
{
  for (int i=0;i<=3;i++)
  {
    showDigit(i);
    delay(1000);
  }
}

Ausgabe erfolgt dabei sowohl auf "Serial" als auch auf LCD.

Die Ziffern sind sowohl im Quelltext als auch auf LCD und auf dem seriellen Monitor "liegend von rechts" zu lesen.

Die Ziffern 4 bis 9 im Daten-Array "digits" zu definieren, überlasse ich Dir.

Hi Jurs

Danke habs gerade mit meinem 20X4 Display ausprobiert. Es funkt perfekt.
Bei der Erweiterung auf das Zeichen 5 ist mir allerdings aufgefallen dass diese Zahl nicht schön drgestellt wird.
Nach einer Recherche habe ich entdeckt dass der Befehllcd.print('\377'); eine Darstellung mit allen Punkten bedeutet.
Für die Darstellung runder Zahlen währe es schön wenn ich auch halb gefüllte Felder anzeigen kann.
Gibt es da eine Möglichkeit?

Grüsse Rudi

Schau dir das custom character RAM Beispiel bei deiner LCD Library an. Da wird gezeigt wie man eigene Zeichen definiert. Es sind 8 benutzerdefinierte Zeichen möglich.

Da gibt es auch nette Code Generatoren dafür:
https://omerk.github.io/lcdchargen/
Ist für ein parallel Display aber bei I2C ist nur die LCD Initialisierung anders

Rudi01:
Danke habs gerade mit meinem 20X4 Display ausprobiert. Es funkt perfekt.
Bei der Erweiterung auf das Zeichen 5 ist mir allerdings aufgefallen dass diese Zahl nicht schön drgestellt wird.
Nach einer Recherche habe ich entdeckt dass der Befehllcd.print('\377'); eine Darstellung mit allen Punkten bedeutet.
Für die Darstellung runder Zahlen währe es schön wenn ich auch halb gefüllte Felder anzeigen kann.
Gibt es da eine Möglichkeit?

Natürlich kannst Du Dir Deine Ziffern aus dem gesamten vorhandenen Zeichenvorrat des LCD-Controllers und zusätzlichen 8 selbstdefinierten Sonderzeichen zusammenstellen.

Sobald Du aber mehr als zwei Code-Möglichkeiten für jeden Bildpunkt vorsehen möchtest, kannst Du die Daten nicht mehr mit zwei Bits (0/1) darstellen, sondern benötigst mehr Bits pro Bildpunkt und damit auch mehr Speicherplatz für das Array mit dem Zeichensatz.

Auch das ist im Prinzip möglich, denn da es sich bei den Zeichensätzen um Konstanten handelt, könnte man das Zeichensatz-Array im PROGMEM Flash-Speicher als Konstanten anlegen, so dass ein hoher RAM-Speicherverbrauch kein Thema wird.

Das von mir erstellte Codebeispiel war nur die einfachste Möglichkeit: Es gibt nur zwei verschiedene Zeichen (voller Block, leerer Block), und diese werden in der Zeichensatz-Datenstruktur einfach durch Einsen und Nullen repräsentiert.

Aber je mehr verschiedene Zeichen Du in Deiner Zifferndarstellung haben möchtest, desto komplexer und umfangreicher wird eben auch die Daten-Array und die Programmlogik, um damit umzugehen.

Komplizierter und aufwändiger geht immer.

Fragt sich nur, mit wieviel Komplexität Du umgehen kannst und wie aufwändig Du es realisieren möchtest.

Komplex? Also ich finde die Sache auf Bit Ebene schon komplex genug für einen Anfänger. Deswegen mein Ansatz mit Byte pro Pixel. Damit und ein paar selbst definierten "Ecken und Rundungen" liese sich das doch einfach realisieren.

So jetzt melde ich mich mal wieder

Nach vieel Fleißarbeit habe ich den Sketch zur Darstellung der großen Zahlen nun fertig.
Da der Sketch zu groß ist um ihn hier direkt anzuzeigen habe ich ihn angehängt.

Vielen Dank nochmals für Eure Hilfe.

Der nächste Punkt ist nun das Einbinden mehrerer LCDs.
Eventuell mache ich das ohne I2C muss es nochmals überlegen ob die Pins ausreichen.

_2_____0-9_fertig_bereinigen_6.ino (39.7 KB)

Rudi01:
Der nächste Punkt ist nun das Einbinden mehrerer LCDs.
Eventuell mache ich das ohne I2C muss es nochmals überlegen ob die Pins ausreichen.

Aber gerade dafür ist doch I2C wie geschaffen. :wink:

Mehrere LCD ohne I2C? Wo nimmst du denn die ganzen Pins her? Mega?

Hi

Es gibt die Möglichkeit mehrere LCDs paralell zu betreiben alle Signalleitungen können paralell betrieben werden nur die E (Enable-Signal) muss für jedes Display seperat zur Verfügung gestellt werden.
Das sieht im Sketch dann so aus:

//LCD Pin    RS, E, D4,D5,D6,D7
LiquidCrystal lcd1(12, 11, 5,  4,   3,   2);
LiquidCrystal lcd2(12, 13, 5,  4,   3,   2);

Die einzelnen Displays werden dann so angesprochen:

 setCursor.lcd1(0, 0);
print.lcd1("dies ist das Display1");

Das habe ich schon probiert es funkt wunderbar und ich spare mir ein paar I2C platinchen.
Ds währen dann 5 Pins + Anzahl der Displays .

Rudi01:
ich spare mir ein paar I2C platinchen.

unter 1€ gibt es die schon

//LCD Pin    RS, E, D4,D5,D6,D7
LiquidCrystal lcd1(12, 11, 5,  4,   3,   2);
LiquidCrystal lcd2(12, 13, 5,  4,   3,   2);

Geht es nicht auch per index?

//LCD Pin    RS, E, D4,D5,D6,D7

LiquidCrystal lcd[1](12, 11, 5,  4,   3,   2);
LiquidCrystal lcd[2](12, 13, 5,  4,   3,   2); 

und dann lcd[x],print("Test");

das ist doch später einfacher anzusprechen

ElEspanol:
unter 1€ gibt es die schon

Verstehe nicht, was ihr immer an dem I2C so toll findet, aber egal.
I2C sollte in den meisten Fällen (eigentlich immer) mehr Code verursachen und somit fallen schnell mal kleinere Controller weg.

Habe das Vorgehen wie Rudi es gemacht hat, ebenfalls in avr-gcc bereits gemacht mit 5 Displays. Das mit dem Display sollte so nicht gehen (index). Ist auch sehr umständlich.

Warum nicht einfach mehrere Objekte anlegen?

lcd1.printf("xay");
lcd2.printf("scs");

sschultewolter:
Verstehe nicht, was ihr immer an dem I2C so toll findet, aber egal.

Weil es damit recht einfach geht externe Module/Sensoren anzusprechen und die gibt es reichlich.
Man benötigt dazu nur 2(4) Leitungen.
Und es ist mit entsprechender Hardware eine "längere" Verbindung zwischen den Modulen möglich.

ElEspanol:

Rudi01:
Das habe ich schon probiert es funkt wunderbar und ich spare mir ein paar I2C platinchen.
Ds währen dann 5 Pins + Anzahl der Displays .

unter 1€ gibt es die schon

Ein Vorteil dürfte auch die Geschwindigkeit sein. Die Ansteuerung über die I2C-Platinchen geht ja immer sehr gemächlich.

Theseus:
Die Ansteuerung über die I2C-Platinchen geht ja immer sehr gemächlich.

Aber immer noch schnell genug, das ein menschliches Auge nichts mit bekommt. :astonished:

HotSystems:
Aber immer noch schnell genug, das ein menschliches Auge nichts mit bekommt. :astonished:

Dem Widerspreche ich nach Programmierung eines Timers mit Großziffern auf 20x4Display über I2C-Adapter. Man muss sich schon etwas einfallen lassen, damit der Inhaltswechsel nicht störend auffällt.