LCD am I2C-Bus beim Arduino

Prof. Jürgen Plate

LCD am I2C-Bus beim Arduino

Allgemeines

Die gängigen Dot-Matrix-LCDs mit einer Zeichenmatrix von 5x8 Pixeln haben zwei oder vier Zeilen mit je 16 oder 20 Zeichen. Die Kontakte sind meist einreihig mit 16 Polen, es gibt aber auch Displays mit seitlich zwei Reihen. Die Kontakte sind üblicherweise von links nach rechts mit 1 bis 16 nummeriert. Zumindest ist der Pin 1 markiert. An den Kontakten 15 und 16 ist normalerweise die Hintergrundbeleuchtung (LED) angeschlossen. Die Zuordnung von Anode und Kathode ist oft nicht immer eindeutig. Hier hilft nur ausprobieren. Ganz frühe LCDs hatten nur einen 14-poligen Anschluss, die Hinterleuchtung wurde an separaten Pins mit Energie versorgt. Es gibt in seltenen Fällen auch eine 15-polige Anschllussleiste, bei der die Kathode der LED mit dem GND-Anschluss des Controllers verbunden ist und Pin 15 an die Anode der LED angeschlossen ist. Hintergrundinfos zu LCD finden Sie im Skript zu Displays.

Ob die Hintergrundbeleuchtung eventuell einen Vorwiderstand benötigt, ist von Modell zu Modell verschieden. Im Zweifelsfall muss man auch hier ausprobieren, indem ein Widerstand von 470 Ω zwischen 5 V und LED geschaltet wird. Durch Messen des Stroms kann man dann auf einen internen Widerstand schließen.

Die folgende Tabelle zeigt die gängigste Pin-Belegung eines üblichen Text-LCDs. Leider gibt es auch Anzeigen, bei denen die Stromversorgungsanschlüsse (Pins 1 und 2) vertauscht sind. Also auf jeden Fall einen Blick ins Datenblatt werfen.

Pin DisplayFunktionBeschreibungPin ArduinoBemerkung
1VSSGND GND 
2VDDVcc+5 V 
3V0Kontrasteinstellung+5 Vüber Poti 10 kΩ
4RSRegister Select12 digital 
5R/W GND
6E Enable 11 digital 
7DB0Datenleitung 0--4-Bit-Modus
8DB1Datenleitung 1-4-Bit-Modus
9DB2Datenleitung 2-4-Bit-Modus
10DB3Datenleitung 3-4-Bit-Modus
11DB4Datenleitung 45 digital 
12DB5Datenleitung 54 digital 
13DB6Datenleitung 63 digital 
14DB7Datenleitung 72 digital 
15LED - Gemeinsame Kathode GND 
16LED + Gemeinsame Anode+5 Vüber Widerstand 10 Ω

Bemerkungen:

Bei den LCDs mit zweireihigem 14-poligen Anschluss sind die Pinnummern meist der Bedruckung auf der Oberseite zu entnehmen. Die Pin 15 und 16 für die Versorgung der LED-Hintergrundbeleuchtung sind meist auf der gegenüber liegenden Seite zu finden. Die Pinbelegung entsprichtim Übrigen der Tabelle oben.

Achtung: Beim Anschluss-Schema von Displays mit zweireihigem Steckverbinder sind bei einigen Displays die Anschlüsse Vdd und Vs vertauscht! Das müssen Sie beachten, wenn Sie beispielsweise das Controllerboard getrennt vom Display beschaffen und das Display selbst anlöten. Lesen Sie vor dem Anschließen auf jeden Fall das Datenblatt.

Die üblichen LCD-Anzeigen sind in der Regel mit einem Hitachi HD44780 Controller (oder einem oder kompatiblen Typ) und dem Displaytreiber HD44100 asgerüstet. Sie erlauben maximal 80 Stellen, was bedeutet, dass das größte Display der Typ mit 4x20 Zeichen (alternativ 2x40 Zeichen) ist. Displays mit mehr Stellen werden über mehrere Controller angesteuert.

Das "klassische" LCD am Arduino

Wie oben schon angedeutet, kann solch ein LCD kann im 4-Bit- oder 8-Bit-Modus angesprochen werden, dementsprechend werden vier oder acht Datenleitungen benötigt, die an die digitalen Pins des Arduino angeschlossen werden. Um Leitungen zu sparen, wird meist der 4-Bit-Modus verwendet. neben der Stromversorgung und der Kontrastregelung werden sechs digitale Leitungen benötigt, da die R/W-Leitung des Displays fest mit GND verbunden ist. Eine übliche Belegung ist:

Die Library für das LCD ist in der Arduino-IDE enthalten. Es muss also nichts installiert werden. Beim Programmieren ist nur die Pinbelegung zu achten, die davon abhängt, wie das LCD angeschlossen wurde. Diese Belegung wird beim Erzeugen eines LCD-Objekts mitgegeben:

#include <LiquidCrystal.h<  // Bibliothek LiquidCrystal einbinden
// Pin-Zuordnung: RS  E   D4 D5 D6 D7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Objekt erzeugen
Im Setup wird die Displaykonfiguration übergeben. Die beiden Parameter stehen für die Zeichen pro Zeile und die Zeilenanzahl. In diesem Beispiel 20 Zeichen und 2 Zeilen:
lcd.begin(20, 2);

Die LCD-Bibliothek ist in der über die Hilfe-Funktion der Arduno-IDE erreichbare Referenz gut dokumentiert. Unter Datei → Beispiele → LiquidCrystal finden Sie etliche Beispiele, die ebenfalls in der Referenz beschrieben sind. Deshalb folgt hier nur ein einfaches "Hello World"-Programm:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
  {
  lcd.begin(20,4);  // setze LCD auf 20 Zeichen und 4 Zeilen
  lcd.clear();
  lcd.setCursor(0, 0);      // Cursor auf Position 1, Zeile 1 (0, 0)
  lcd.print("Hello World"); // Ausgabe Text an LCD
  }

void loop()
  {
  lcd.setCursor(0, 1);      // Cursor auf Position 1, Zeile 2 (0, 1)
  lcd.print(millis()/1000); // Anzahl der Sekunden seit dem Start
  delay(1000);              // Warten
  }
Neben den Beispielen der Arduino-IDE gibt es genügend Infos im Web zu finden, so dass hier das obige Beispiel genügen soll.

LCD per I2C am Arduino

Wesentlich Leitungsökonomischer ist der Anschluss eines Dot-Matrix-LCDs über den I2C-Bus. Hier werden nur vier Leitungen benötigt: +5 V, GND, SDA und SCL. Natürlich bedarf dazu das LCD einer Erweiterung der Hardware. Mit Hilfe des I2C-I/O-Portexpanderbausteins PCF8574 läßt sich das LCD ansteuern. Dieser Baustein bietet acht bidirektionale Portleitungen, die man einzeln über den I2C-Bus gesetzt und abgefragt werden können.

Belegung des PCF8574

  • A0 – A2: Auswahl der I2C Bus Adresse
  • P0 – P7: Digitale I/O Ports
  • SDA: Datenleitung – Verbindung zum I2C Bus
  • SCL: Taktleitung – Verbindung zum I2C Bus
  • INT: Interrupt Ausgang
  • VDD: +5 V
  • VSS: GND

Die Erweiterung muss man auch nicht selbst bauen, sondern es gibt sie als fertiges Modul zum Aufstecken oder auch bereits komplett mit Display. Die winzige Platine besitzt vier Anschlüsse auf der rechten Seite (GND, VCC; SDA, SCL) und einen Jumper auf der Linken Seite, mit dem die Hintergrundbeleuchtung abgeschaltet werden kann. Auch das Potenziometer für die Kontrastregelung ist mit auf der Patine. Die I2C-Displays werden von verschiedenen Unternehmen angeboten, einfach mal bei Ebay oder Amazon nachsehen.

Über drei Lötbrücken kann die I2C-Adresse des Moduls eingestellt werden. Per Default sind alle Verbindungen offen, wodurch das Modul über die Adresse 0x27 angesprochen werden kann. Über Jumper oder Lötbrücken können sieben weitere Adressen eingestellt werden.

A0A1A2Adresse
o     oo     oo     o0x27
o—oo     oo     o0x26
o     oo—oo     o0x25
o—oo—oo     o0x24
o     oo     oo—o0x23
o—oo     oo—o0x22
o     oo—oo—o0x21
o—oo—oo—o0x20

Aber auch der Nachbau wäre nicht schwierig. Die Schaltung besteht praktisch nur aus dem Portexpander PCF8574 und dem Potenziometer für den Kontrast (was im folgenden Bild weggelassen wurde).

Je nachdem, welchen Arduino-Typ Sie verwenden, müssen die Leitungen SDA und SCL des LCD an unterschiedliche Ports des Arduino angeschlossen werden:

Arduino-TypSDASCL
UNOA4/SDAA5/SCL
Mega 25602021
Leonardo23

Bei der Verdrahtung (siehe Schaltbild oben) hält man sich am besten au das Schema der kommerziell angebotenen Boards.

PCF8574ArduinoDisplay
Pin 16 (VDD)+5V-
Pin 15 (SDA)A4 (SDA)-
Pin 14 (SCL)A5 (SCL)-
Pin 13 (INT) --
Pin 12 (P7) --
Pin 11 (P6) -Pin 4 (RS)
Pin 10 (P5) -Pin 5 (R/W)
Pin 9 (P4) -Pin 6 (E)
Pin 8 (VSS)GND-
Pin 7 (P3) -Pin 14 (DB7)
Pin 6 (P2) -Pin 13 (DB6)
Pin 5 (P1) -Pin 12 (DB5)
Pin 4 (P0) -Pin 11 (DB4)
Pin 3 (A2) GND-
Pin 2 (A1) GND-
Pin 1 (A0) GND-

Für die Programmierung des I2C-Moduls benötigt man eine Library, die nicht in der Arduino-IDE vorinstalliert ist. Diese kann unter https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library als ZIP-Datei heruntergeladen werden. Danach fügt man die Library in der Arduino-IDE zu den vorhandenen Bibliotheken hinzu. Dies wird unter dem Menüpunkt Sketch → Bibliothek einbinden → .ZIP Bibliothek hinzufügen erledigt. Danach kann die Bibliothek im Code verwendet werden. Nach Aufruf der Arduino-IDE findet man in den Beispielen zu LiquidCrystal_I2C drei Beispiele. Hier soll als erstes Beispiel eine übliche "Hello-World"-Variante dienen:

#include <Wire.h>  // binde Bibliothek Wire fuer I2C ein
#include <LiquidCrystal_I2C.h> // binde Bibliothek LiquidCrystal_I2C ein

LiquidCrystal_I2C lcd(0x27,20,4);  // setze LCD auf 16 Zeichen und 4 Zeilen

void setup()
  {
  lcd.begin();                // initalisiere LCD 
  lcd.backlight();           // Hintergrundbeleuchtung an
  lcd.clear();
  lcd.setCursor(0, 0);      // Cursor auf Position 1, Zeile 1 (0, 0)
  lcd.print("Hello World"); // senden Nachricht an LCD
  }

void loop()
  {
  lcd.setCursor(0, 1);      // Cursor auf Position 1, Zeile 2 (0, 1)
  lcd.print(millis()/1000); // zeige Anzahl Sekunden seit Start
  delay(500);
  // Display aus, Info bleibt erhalten
  lcd.noDisplay();
  delay(500);
  // Display an, Info wird angezeigt
  lcd.display();
  }

Die ersten drei Zeilen brauchen Sie bei jedem Programm, das mit dem I2C-Modul arbeitet. Die Bibliotheksfunktionen sind jenen der Standard-LCD-Libraryp nachempfunden, so dass die Programme beider Schaltungsvarianten laufen, sofern man die richtigen Bibliotheken einbindet und die Funktion init() entsprechend anpasst. Als kleines Extra wird gezeigt, wie man das Display ein- und ausschalten kann, ohne die angezeigte Info zu verlieren.

Programmierung

In diesem Abschnitt werden einige Beispielprogramme gezeigt, die demonstrieren sollen, das man auch mit einem so einfachen Display einige interessante Dinge anstellen kann. Das erste Programm soll Sie einstimmen und es soll als Schema für Ihre eigenen ersten Versuche dienen.

Früher oder später werden Sie bemerken, dass die deutschen Umlaute nicht mit dem Zeichensatz Ihres PC übereinstimmen. Es gibt zwar eine Variante des LCD-Controllers mit dem "passenden" Zeichensatz (ROM Code A02), aber im Handel gibt es meist nur die Standardvariante (ROM Code A00), deren Zeichensatz die folgende Tabelle zeigt:

Wie Sie sehen, werden alle Zeichen in einer 5x8 Pixel großen Matrix dargestellt. Die Spalte 1 der Zeichentabelle oben (RAM Character Generator) erlaubt die Definition eigener Zeichen-Bitmuster. Dieses Feature wird in den folgenden Beispielen mehrfach genutzt. Die erste Anwendung des programmierbaren Zeichengenerators ist die Definition der groß geschriebenen Umlaute.

Umlaute darstellen

Die Umlaute ä, ö, ü, ß und das Grad-Zeichen sind im Zeichensatz des LCD-Controllers enthalten, sie stehen nur leider an einer anderen Stelle. Im Programmcode kann man das mit einigen Zeilen abfangen und die Zeichencodes konvertieren. Eine Funktion für die klein geschreibenen Umlaute sieht beispielsweise so aus:

char Umlaut(byte ascii) 
  {
  switch (ascii) 
    {
    case 228: return  225; break; // ä
    case 246: return  239; break; // ö
    case 252: return  245; break; // ü
    case 223: return  226; break; // ß
    case 176: return  223; break; // grad
    default:  return  ascii; break;
    }
  }
Für Ä, Ö und Ü müssen eigene Zeichen für das LCD definiert werden. Die Methode in der Library heisst lcd.createChar(num, bitarray), wobei num der Zeichencode zwischen 0 und 7 ist. bitarray ist ein Array, das die Bitdefinition beinhaltet. Diese Definition stellt ein Zeichen als Muster von 5x8 Pixeln als Gruppe von 8 Zeilen zu je 5 Bits dar. Das folgende Bild zeigt den Aufbau am Beispiel des Buchstabens 'R':

Das Array für dieses Zeichen würde definert als:

byte Auml[8] =  { B11110, B10001, B10001, B11110, B10100, B10010, B10001, B00000 };
Das folgende Programm definiert die Zeichenmuster für die Umlaute Ä, Ö und Ü als Arrays. Diese Zeichendefinition wird dann mittels lcd.createChar() in der Funktion setup() ins LCD geladen. In der Hauptschleife werden für den Test ASCII-Zeichen von der seriellen Schnittstelle eingelesen und auf das Display ausgegeben. Der Aufruf der Umcodierungfuntion wird in die Ausgaberoutine eingebettet, der Aufruf autet dann: lcd.write(Umlaut(Serial.read())).
#include <Wire.h>  // binde Bibliothek Wire ein
#include <LiquidCrystal_I2C.h> // binde Bibliothek LiquidCrystal_I2C ein

// Bitmuster fuer grosse Umlaute
byte Auml[8] =  { B01010, B00000, B01110, B10001, B10001, B11111, B10001, B10001 };
byte Uuml[8] =  { B01010, B00000, B10001, B10001, B10001, B10001, B10001, B01110 };
byte Ouml[8] =  { B01010, B00000, B01110, B10001, B10001, B10001, B10001, B01110 };

LiquidCrystal_I2C lcd(0x27,20,4);  // setze LCD auf 16 Zeichen und 4 Zeilen

char Umlaut(byte ascii) 
  {
  switch (ascii) 
    {
      case 228: return  225; break; // ä
      case 246: return  239; break; // ö
      case 252: return  245; break; // ü
      case 223: return  226; break; // ß
      case 196: return  0; break;   // Ä
      case 214: return  2; break;   // Ö
      case 220: return  1; break;   // Ü
      case 176: return  223; break; // grad
      default:  return  ascii; break;
    }
  }

void setup()
  {
  Serial.begin(9600);
  lcd.begin();                // initalisiere LCD 
  lcd.backlight();           // Hintergrundbeleuchtung an
  lcd.createChar(0, Auml);   // Umlaute definieren
  lcd.createChar(1, Uuml);
  lcd.createChar(2, Ouml);
  lcd.clear();
  }

void loop()
  {
  if (Serial.available()) 
    {
    // bisserl warten
    delay(100);
    // clear the screen
    lcd.clear();
    // zeichenweise ausgeben
    while (Serial.available() > 0) 
      {
      lcd.write(Umlaut(Serial.read()));
      }
    }  
  }

Balkengrafik

Waagrechte Balkengrafik geht recht einfach, indem man das Leerzeichen nimmt und das Zeichen mit dem Code 255, ein "Klötzchen", das eine Displayposition voll ausfüllt. So kann man waagrechte Balken mit 16 oder 20 Stellen darstellen. Bei vertikalen Balken wird es etwas komplizierter. Dafür werden acht neue Zeichen definiert. Das erste Zeichen hat eine gefüllte Zeile ganz unten, das zweite dann schon zwei Zeilen von unten usw. Das letzte definierte Zeichen ist dann komplett gefüllt. Das kann man aus der Arraydefinition im Listing unten schön erkennen. Um die Programmierung kompakter zu machen, werden nicht wie bei den Umlauten einzelne Arrays definiert, sondern ein zweidimensionales 8x8-Array. Die Methode lcd.createChar() kann dan in einer Schleife aufgerufen werden.

Um den Balken mit n Linien auszugeben, genügt der Befehl lcd.write(i), wie es im Beispielprogramm gezeigt wird. Da acht Werte aber nur eine recht grobe Auflösung haben, gibt es die Funktion Balken(), die eine Auflösung von 16 Linien hat und in zwei aufeinanderfolgenden Zeilen ausgegeben wird. Neben dem auszugebenden Wert kann der Funktion noch Zeile und Spalte des Displays übergeben werden (beginnend bei 0). Die Ausgabe erfolgt dann in der angegebenen Zeile und der Zeile darunter.


#include <Wire.h>  // binde Bibliothek Wire ein
#include <LiquidCrystal_I2C.h> // binde Bibliothek LiquidCrystal_I2C ein

// Balkengrafik-Muster
byte bar[8][8] = {
  { B00000,B00000,B00000,B00000,B00000,B00000,B00000,B11111 },  // 0
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111 },  // 1
  { B00000,B00000,B00000,B00000,B00000,B11111,B11111,B11111 },  // 2
  { B00000,B00000,B00000,B00000,B11111,B11111,B11111,B11111 },  // 3
  { B00000,B00000,B00000,B11111,B11111,B11111,B11111,B11111 },  // 4
  { B00000,B00000,B11111,B11111,B11111,B11111,B11111,B11111 },  // 5
  { B00000,B11111,B11111,B11111,B11111,B11111,B11111,B11111 },  // 6
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111 }}; // 7

LiquidCrystal_I2C lcd(0x27,20,4);  // setze LCD auf 16 Zeichen und 4 Zeilen

void Balken(int value, int zeile, int spalte)
  {
  // 16-Schritte-Balkengrafik ausgeben
  // zeile gibt die Displazeile an, wobei die Ausgabe in 
  // der angegebenen Zeile und der darunterliegenden erfolgt
  // spalte gibt die displayspalte des Balkens an
  char upper, lower;
  
  if(value < 8)
    { upper = ' '; lower = value; }
  else
    { upper = value - 8; lower = 7; }
  lcd.setCursor(spalte, zeile); // Obere Haelfte ausgeben
  lcd.write(upper);
  lcd.setCursor(spalte, zeile + 1); // Untere Haelfe ausgeben
  lcd.write(lower);
  }
  
void setup()
  {
  int i;
  
  Serial.begin(9600);
  lcd.begin();             // initalisiere LCD 
  lcd.backlight();        // Hintergrundbeleuchtung an
  for(i = 0; i < 8; i++)  // Balken definieren
    lcd.createChar(i, bar[i]);
  lcd.clear();

  lcd.print("Hello ");
  for(i = 0; i < 8; i++)
    {
    lcd.write(i);  // Alle einzeiligen Balken darstellen
    delay(200);
    } 
  for(i = 15; i >= 0; i--)
    {
    Balken(i, 2, i); // Alle zweizeiligen Balken darstellen
    delay(200);
    } 
  }

void loop()
  {
  // Nix
  }
Das folgende Programmstück gibt beispielsweise einen Wert als Balken aus, der über den analogen Eingang 0 eingelesen wurde:
int wert = analogRead(0);
byte code = map(wert, 0, 1023,0,16); // proportionalen Wert zwischen 0 und 15 ermitteln
Balken(code, 0, 0); ;

Große Ziffern

Durch die geschickte Definition und Kombination von Grafiksymbolen lassen sich größere Symbole darstellen. Dazu werden fünf Grafiksymbole definiert, die so kombiniert werden können, dass sich mit ihnen große Ziffern darstellen lassen. Die Symbole haben folgende Muster und sind im Array pattern abgelegt, wobei das letzte Muster nicht zum Darstellen von Ziffern dient, sondern den "großen" Dezimalpunkt definiert.

byte pattern[5][8] = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000 }, // 0
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111 }, // 1
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111 }, // 2
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111 }, // 3
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110 }};// 4
Jede große Ziffer belegt zwei Zeilen und setzt sich aus sechs der Grafiksymbole zusammen, drei für die obere und drei für die untere Hälfte. Die Arrays DigitsTop und DigitsBot definieren, aus welchen Grafiksymbolen die oberen und unteren Zeilen auf dem LCD zusammengesetzt sind. Auf dem LCD sehen die Zahlen dann so aus:

Bei der Definition kommen nur die Symbole 0 bis 3 vor. Wo alle Pixel dunkel sein sollen, steht ein Leerzeichen, das unten mit seiner ASCII-Codierung 32 auftaucht:

const char DigitsTop[10][digitWidth]={
   {3,0,3}, {0,3,32}, {2,2,3}, {0,2,3}, {3,1,3},
   {3,2,2}, {3,2,2},  {0,0,3}, {3,2,3}, {3,2,3}};
const char DigitsBot[10][digitWidth]={
   {3,1,3}, {1,3,1}, {3,1,1},   {1,1,3}, {32,32,3},
   {1,1,3}, {3,1,3}, {32,32,3}, {3,1,3}, {1,1,3}};
Im folgenden Beispielprogramm sind die beiden Arrays in der Funktion showDigit() definiert. Diese Funktion stellt eine große Ziffer (Parameter digit) an der durch zeile und spalte vorgegebenen Position dar, wobei diese Werte bereits in den Dimensionen der großen Ziffern rechnen. So würde beispielsweise zeile = 0 die Displayzeilen 0 und 1 belegen zeile = 1 dementsprechen die Displayzeilen 2 und 3. Analog würde der Wert spalte = 3 die Displayspalten 10 bis 13 belegen.

Das Programm zeigt zuerst alle darstellbaren Ziffern und realisiert dann eine Digitaluhr für Minuten und Sekunden.

#include <Wire.h>  // binde Bibliothek Wire ein
#include <LiquidCrystal_I2C.h> // binde Bibliothek LiquidCrystal_I2C ein

// Breite der grossen Ziffern (Anzahl Stellen)
#define digitWidth 3 
// Hoehe der grossen Ziffern
#define digitHeight 2

// Muster, aus denen die grossen Ziffern zusammengesetzt werden
byte pattern[5][8] = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000 },  // 0
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111 },  // 1
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111 },  // 2
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111 } , // 3
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110 }}; // 4

LiquidCrystal_I2C lcd(0x27,20,4);  // setze LCD auf 16 Zeichen und 4 Zeilen

void showDigit(int digit, int zeile, int spalte)
  {
  // Stellt eine grosse Ziffer dar. Die Position wird
  // durch zeile und spalte festgelegt, wobei diese
  // Werte bereits in den Dimensionen der Ziffern rechnen
  // zeile=0 belegt z. B. die Displayzeilen 0 und 1, zeile=1
  // entsprechen die  Displayzeilen 2 und 3.
  // Ebenso wuerde der Wert spalte=3 die Displayspalten 
  // 10 bis 13 belegen.
  
  byte i;
  // Arrays zur Indexierung der selbstdefinierten Zeichen, 
  // aus denen die großen Ziffern bestehen
  const char DigitsTop[10][digitWidth]={
     {3,0,3}, {0,3,32}, {2,2,3}, {0,2,3}, {3,1,3},
     {3,2,2}, {3,2,2},  {0,0,3}, {3,2,3}, {3,2,3}};
  const char DigitsBot[10][digitWidth]={
     {3,1,3}, {1,3,1}, {3,1,1},   {1,1,3}, {32,32,3},
     {1,1,3}, {3,1,3}, {32,32,3}, {3,1,3}, {1,1,3}};
     
  lcd.setCursor(spalte*(digitWidth + 1), zeile*digitHeight);
  for(i = 0; i < digitWidth; i++)
    lcd.write(DigitsTop[digit][i]);
  lcd.setCursor(spalte*(digitWidth + 1), zeile*digitHeight + 1);
  for(i = 0; i < digitWidth; i++)
    lcd.write(DigitsBot[digit][i]);
  }


void setup()
  {
  int i;
  
  Serial.begin(9600);
  lcd.begin();                 // initalisiere LCD 
  lcd.backlight();            // Hintergrundbeleuchtung an
  for(i = 0; i < 5; i++)      // Sonderzeichen definieren
    lcd.createChar(i, pattern[i]);
  lcd.clear();

  for(i = 4; i >= 0; i--)
    {
    showDigit(i, 0, i);
    delay(500);
    } 
  for(i = 9; i >= 5; i--)
    {
    showDigit(i, 1, i-5);
    delay(500);
    } 
  lcd.clear();
  }

void loop()
  {
  byte j, k;

  j = 0; k = 0;

  for (;;)
    {
    showDigit(j/10, 0, 0);
    showDigit(j%10, 0, 1);
    lcd.setCursor(digitWidth*2 + 1, 0);
    lcd.write(4);
    lcd.setCursor(digitWidth*2 + 1, 1);
    lcd.write(4);
    showDigit(k/10, 0, 2);
    showDigit(k%10, 0, 3);
    delay(1000);
    k++;
    if (k == 60)
      { j++; k = 0; }
    if (j == 60)
      j = 0;
    }
  }
Ein letztes Beispiel, das hier nicht aufgelistet ist, zeigt die Anwendung diverser anderer Displayfunktionen (siehe Links).

Links


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate
Letzte Aktualisierung: