Hi,

willkommen beim Arduino Onlinekurs. Hier habe ich die fünfte Arduino Lektion für dich. Zur Feier der kleinen Prämiere gibt es etwas besonders spannendes.

Wir werden in den nächsten beiden Lektionen ein kleines Projekt verwirklichen, das einen ganz typischen Einsatz von Mikrocontrollern im Alltag zeigt. Wir bauen heute eine Digitaluhr und beim nächsten Mal erweitern wir sie um eine Weltzeituhr und eine Alarmfunktion.

Dabei lernst du zunächst ein neues, sehr nützliches Bauteil kennen, das du in vielen anderen Projekten gut gebrauchen kannst:  Das  LCD-Display HD44780.

LCD-Display HD44780

Dieses Display kann zwei Zeilen mit jeweils 16 Zeichen darstellen und ermöglicht es dir damit, Daten und Werte anzuzeigen. Es ist so etwas wie ein kleiner Bildschirm für den Arduino.  HD44780 ist eigentlich die Bezeichnung für den Controllerchip, der die Daten vom Arduino annimmt und damit die Anzeige ansteuert. Es hat 16 Eingangspins, von denen 8 für die Übertragung der Anzeigedaten vorgesehen sind. Die restlichen 8 Pins dienen der Steuerung, Spannungsversorgung und Beleuchtung des Displays.

Die Pinbelegung dieses Bauteils folgt einem  weit verbreiteten Standard und  wird von der Arduino-Porgrammiersprache bereits mit vielen Funktionen unterstützt, die das Darstellen von Daten auf dem Display zum Kinderspiel machen. Die meisten Displays, die du im Elektronikhandel für wenige Euro kaufen kannst sind schon mit Baustein bestückt und können direkt am Arduino betrieben werden. Am besten besorgst du dir ein Modul mit angelöteter Stiftleiste, die du dann direkt ins Breadboard stecken kannst.

LCD Display

Auf der Softwareseite wirst du diesmal paar neue Programmierkonzepte kennen lernen, allen voran den String-Datentyp und die Verarbeitung von Zeichenketten.

Das LCD-Display anschließen

Um das LCD-Display zu verdrahten und an den Arduino anzuschließen, brauchst du eine ganze Menge Drahtstückchen. Bei voller Beschaltung belegt das Display 9 Pins am Arduino, außerdem musst du auf dem Breadboard noch einige Pins miteinander verbinden. Wenn du es also noch nicht gemacht hast, ist jetzt eine Gelegenheit, aus einer Rolle Klingeldraht kurze Verbindungsstücke zu machen, so wie es in der zweiten Lektion erklärt wurde. Es gibt im Elektronikhandel auch fertige Sets sogenannter Jumperkabel, die du natürlich auch verwenden kannst.

 

Die Pins am Display werden von links nach rechts gezählt. An die ersten beiden kommen die 5V Versorgungsspannung. Pin 3 ist für die Einstellung des Kontrasts verantwortlich. Manche Schaltungen, die du im Internet findest, sehen hier einen veränderbaren Widerstand vor, um den Kontrast der Anzeige einstellen zu können. Normalerweise reicht es aber aus, den Pin einfach auf GND zu legen und man erzielt damit schon eine gute Darstellung. Solltest du Probleme mit einer zu blassen Anzeige haben, kannst du über diesen Pin eingreifen. Bei Schwierigkeiten melde dich einfach im Forum dazu. Die Pins 4-6 steuern die Datenübertragung zwischen Arduino und LCD-Controller. Darauf wollen wir erstmal nicht im Einzelnen eingehen, denn der Arduino-Compiler kümmert sich automatisch um die korrekte Ansteuerung des Displays.

Die Pins 7 bis 14 sind die Datenleitungen. Wir haben also 8 Bit zur Verfügung, um Anzeigedaten auf das Display zu schicken. Der LCD-Controller bietet aber auch einen „Light-Modus“, in dem nur 4 Datenleitungen benötigt werden. Dadurch wird die Übertragung etwas langsamer laufen, aber die Geschwindigkeit reicht für unsere Zwecke noch dicke aus. Daher schließen wir hier nur 4 Pins an.

Die Pins 15 und 16 dienen schließlich der Spannungsversorgung für die Hintergrundbeleuchtung des Displays.  Wir schließen hier die +3.3V  Ausgangsspannung des Arduino an.

Die Abbildung zeigt dir, wie du die Schaltung aufbauen kannst, wenn du das LCD-Display mit der Stiftleiste ins Breadboard steckst.

Anschluss des LCD-Displays
Anschluss des LCD-Displays

Hier haben wir nochmal die Verdrahtung übersichtlich in einer Tabelle zusammengefasst:

LCD Pin LCD Bezeichnung Arduino Anschluss Funktion
1 VSS GND Spannung  –
2 VDD +5V Spannung +
3 V0 GND Kontrast (0-5V)
4 RS DIGITAL  12 Register Select
5 R/W GND Read/Write
6 E DIGITAL 11 Enable
7-10 DB0-DB3 nicht verwendet Datenpins
11 DB4 DIGITAL 5 Datenpins
12 DB5 DIGITAL 4 Datenpins
13 DB6 DIGITAL 3 Datenpins
14 DB7 DIGITAL 2 Datenpins
15 A +3.3V LED Backlight +
16 K GND LED Backlight –
Schaltplan für den LCD Display Aufbau
Schaltplan für den LCD Display Aufbau

 

aufbau1

Dein Text auf dem Display

Alles korrekt angeschlossen? Prima, dann können wir loslegen. Dein Aufbau wird wahrscheinlich so ähnlich aussehen, wie auf dem Bild oben. Nun gilt es, das Display per Software anzusteuern.

Bevor wir uns um die Funktionen der Uhr kümmern, testen wir das Display mit einem Sketch, der eine Meldung auf dem Display ausgibt. Wir entscheiden uns für das klassische „Hallo Welt“, aber du kannst natürlich einen beliebigen Text ausgeben.

Hier gibt es einige Neuheiten, die wir kurz zusammen durchgehen:

  • Zeile 2: Die Anweisung #include <LiquidCrystal.h>  dient dazu, den Inhalt einer anderen Datei in deinen Code einzubinden. Der Compiler behandelt das so, als ob der Text aus dieser Datei direkt an dieser Stelle stehen würde. Meist verwendet man dies, um externe Programmbibliotheken einzubinden. In diesem Fall binden wir die Funktionen zur Ansteuerung des LCD-Displays ein, die in der Datei LiquidCrystal.h stehen.
  • Zeile 5: Hier erzeugen wir ein  Objekt vom Typ LiquidCrystal mit Namen lcd und übergeben der Software mit  LiquidCrystal lcd(12, 11, 5, 4, 3, 2); gleich das Pin-Layout unserer Schaltung. Immer wenn wir in Zukunft auf das Display schreiben, passiert das über dieses Objekt. Eine ausführliche Dokumentation findest du unter  LiquidCrystal Library auf der Arduino-Website.
  • Zeile 9: Hier initialisieren wir das Display, d.h. wir legen die Zeilen- und Spaltenzahl fest und löschen die Anzeige
  • Zeile 11: Mit lcd.print()  schicken wir eine Zeichenkette auf das Display
  • Zeile 17: Die Funktion lcd.setCursor()  erhält Zeile und Spalte als Parameter und legt fest, an welcher Stelle auf dem Display der nächste print-Befehl ausgegeben wird.

 

Im loop-Block des Testsketches nutzen wir schon den Arduino als Timer: Die Funktion millis() liefert zurück, wie viele Milliskunden seit dem letzten Reset oder Einschalten des Arduino vergangen sind. Aufs Display schicken wir diesen Wert geteilt durch 1000, also haben wir einen Sekundenzähler. Diesen Wert nehmen wir auch gleich als Basis für das Programmieren der Uhren-Funktionen.

Strings oder Rechnen mit Wörtern

Nachdem nun das Display einsatzbereit ist, kommen wir zu unserem eigentlichen Vorhaben: Wir möchten auf dem Display zunächst mal die aktuelle Uhrzeit darstellen und zwar wie bei anderen Digitaluhren im Format HH:MM:SS, also je zwei Stellen für Stunde, Minute und Sekunde, getrennt durch Doppelpunkte.

Dazu bedienen wir uns eines neuen Datentyps, der Zeichenketten abspeichern und verarbeiten kann: der Stringtyp. Eine Stringvariable speichert einfach eine Zeichenkette. Du hast in den Letzten Lektionen bereits kennengelernt, dass man Zahlen als Variablen unter einem bestimmten Namen abspeichern kann und dann im Sketch unter diesem Namen darauf zugreifen und damit rechnen kann. Dazu hatten wir den Datentyp int verwendet. Das steht für „Integer“ und solche Variablen sind immer ganzzahlige Werte. Genauso können wir aber auch Texte oder Zeichen als Variable abspeichern. Diese haben dann den Typ String.

Man kann sie genauso wie Zahlen in Funktionsaufrufen verwenden oder Operationen damit anstellen. Du kannst es ausprobieren, indem du im Testsketch den lcd.print() -Befehl ersetzt:

Im Ergebnis steht wieder „Hallo Welt!“ auf dem Display, aber wir haben die Ausgabe zusammengesetzt aus zwei Stringvariablen und eine Stringkonstanten. Mit dem „+“ Operator kannst du so beliebige Ausgabezeilen aus konstanten Textstückchen und Stringvariablen zusammensetzen. Das nutzen wir gleich aus für die Anzeige der Uhrzeit!

 

 

Was schlägt die Stunde? –  Arduino als Digitaluhr

Hier kommt zunächst mal der Sketch für die Uhr. Bevor wir die Funktion genauer durchgehen, kannst du erstmal den ganzen Code per copy & paste in die Arduino-Entwicklungsumgebung kopieren und abspeichern. Dann setzt du in Zeile 35 die aktuelle Uhrzeit ein und schickst den Sketch an den Arduino. Wir müssen dem Programm die Startzeit mitgeben, weil der Arduino keine eingebaute Uhr hat wie z. B. dein PC oder Laptop.  Außerdem kannst du in Zeile 44  eintragen, was in der ersten Zeile angezeigt werden soll, zum Beispiel deine Stadt.

Wenn alles geklappt hat, dann hast du jetzt eine nette Zeitanzeige auf dem Display. Gehen wir den Code wieder zusammen durch.

Bits und Bytes bis zum Überlaufen

Als erstes fällt auf, dass wir wieder einen neuen Datentyp benutzen, und zwar unsigned long. Das sind eigentlich auch nur ganze Zahlen, genau wie beim Typ int. Allerdings bedeutet long, dass doppelt so viel Speicherplatz für die variable reserviert wird. Statt 16 bit wie für int hat eine long Variable 32 bit. Das brauchen wir, weil wir damit die Sekunden seit dem Start des Programms zählen wollen. Eine int Variable kann maximal Werte bis 216=65536 annehmen. So viele Sekunden sind nach 18 Stunden bereits gezählt, dann würden die Variablen überlaufen und wieder auf Null springen. Mit 32-bit Variablen passiert das erst nach 50 Tagen. Daher müssen wir für diese Anwendung die längeren, speicherintensiven long-Typen verwenden.
Aus demselben Grund sagen wir dem Compiler mit dem Schlüsselwort unsigned, dass wir keine negativen Zahlen verwenden wollen, denn auch dadurch erweitert sich der Bereich bis zum Überlauf. Wenn du mehr über Variablen und Datentypen wissen möchtest, findest du Informationen dazu in Programmierkursen für die Sprachen C und C++.

Wie Funktionen funktionieren

In Zeile 5 definieren wir eine eigene Funktion. Das ist ein wichtiges Konzept bei der Programmierung. Bisher haben wir immer bereits vordefinierte Funktionen verwendet und aufgerufen. Wir können aber genauso eigene Funktionen definieren und dadurch  sich wiederhole Aufgaben  effizient von einem Funktionsaufruf erledigen lassen.

Hier definieren wir die Funktion number_to_string() , die eine Zahl (eine int oder long-Variable) in einen String umwandelt. Daraus werden wir dann die Uhrzeit auf dem LCD-Display zusammensetzen.

Es wird immer zuerst der Rückgabetyp genannt, dann der frei wählbare Funktionsname und in Klammern die Parameter, die an die Funktion übergeben werden, immer mit Typangabe und Name. Das sieht dann so aus:

String number_to_string(long secs, int DIV, int MOD)

Danach kommt ein Block in geschweiften Klammern,. Dort wird implementiert, was diese Funktion macht.

Ein wenig Zeitrechnung muss sein

Für die Funktion number_to_string  schauen wir erstmal auf Zeile 14:

unsigned long number=secs/DIV%MOD;

Die zeile hat’s in sich und sieht etwas kryptisch aus. Aber wir werden sie Schritt für Schritt erklären. Wir nehmen die Sekundenzahl in der Variablen  secs  und teilen sie erstmal durch den Wert DIV, der beim Aufruf der Funktion mit übergeben wurde. Damit kann man entweder Sekunden in Minuten oder in Stunden umrechnen, je nachdem was man für DIV einsetzt.

Danach kommt ein neuer Operator: Das Zeichen %  nennt man Modulo-Operator. Das klingt vielleicht kompliziert und mathematisch, aber es ist ganz einfach: Die Zahl, die hinter dem % steht ist wie eine Grenze, die nicht überschritten wird. Genauer gesagt ergibt die Modulo-Operation den Rest, der beim Teilen entsteht. Für den Sekundenzähler benutzen wir z. B. %60 und das bewirkt, dass nach 59 Sekunden eben nicht 60 kommt, sondern der Zähler wieder bei 0 anfängt. Denn 60 geht ja geteilt durch 60 glatt auf und der Divisionsrest ist 0. Bei 120 passiert das ganze wieder u.s.w. Also statt die Sekunden immer weiterzuzählen springen wir immer bei 60 wieder auf 0 zurück, genau wie eine Uhr eben. Das erledigt der Modulo-Operator für uns ganz automatisch!

In den Zeilen 17 und 18 sorgen wir nun dafür, dass der Rückgabestring immer genau zwei Zeichen hat. Bei Zahlen kleiner als 10 ist er aber einstellig, dann setzen wir einfach eine „0“ vorne dran.

Das in der Variablen  Str  gespeicherte Ergebnis wird dann in Zeile 19 an den Funktionsaufrufer zurückgegeben. Jetzt können wir später überall im Code auf diese Funktion zurückgreifen, indem wir einfach  number_to_string()  mit den entsprechenden Werten aufrufen.  

In Zeile 23 definieren wir noch eine Funktion, diese ist die wichtigste des ganzen Programms. Sie nimmt die Absolute Sekundenanzahl und wandelt sie in eine Uhrzeit im Format HH:MM:SS um. Und zwar passiert das, indem ein String mit dem „+“-Operator zusammengesetzt wird und dreimal die Funktion number_to_string()  aufgerufen wird, jeweils mit den Parametern für Stunden, Minuten und Sekunden.

In Zeile 35 definieren wir einen Wert namens Offset, den wir auf die Sekundenzählung des Arduino noch aufschlagen. Da der Arduino ja mit 0 beginnt zu zählen, wäre sonst die angezeigt Uhrzeit beim Start immer 00:00:00. Aber das wollen wir ja nicht, sondern wir möchten hier die aktuelle Zeit angezeigt bekommen. Dazu behelfen wir uns mit einem Trick: Wir addieren die Zahl der Sekunden seit 0:00:00 Uhr zum Timer-Wert hinzu.

Den Rest verstehst du jetzt schnell: Im Loop-Block nehmen wir die Laufzeit des Arduino aus der Funktion millis(), berechnen daraus die absolute Sekundenzahl, packen unseren Offset drauf und schicken das Ganze an die Funktion timeString() , die einen String im Uhrzeitformat daraus macht. Und der geht dann natürlich mittels lcd.print()  ans LCD-Display.

Es geht noch weiter

Puh – das war es erstmal!  Die Uhr läuft und  du hast diesmal wieder eine Menge Neues erfahren.

Mit dem LCD-Display hast du jetzt einen einfachen Bildschirm für deine Arduino-Experimente bekommen. Außerdem  hast du die wichtigen Programmierkonzepte Strings und Funktionen kennen gelernt. Lass die LCD-Schaltung ruhig noch aufgebaut, denn nächstes Mal machen wir an dieser Stelle weiter und erweitern unsere Uhr um eine Weltzeitanzeige und eine Alarmfunktion!

Bis dahin kannst du erstmal mit dem Display experimentieren und eigene Ideen umsetzen, zum Beispiel mit zwei Tastern eine Funktion zum Zeit stellen einbauen.

Fragen und Anregungen wie immer in die Comments oder ins Forum.

Viel Spaß und bis zum nächsten Arduino Tutorial zur Weltzeituhr!

Die Weltzeituhr mit Alarmfunktion Teil 1 von 2

2 Gedanken zu „Die Weltzeituhr mit Alarmfunktion Teil 1 von 2

  • 9. Juli 2015 um 13:39
    Permalink

    Hallo,

    Wie immer, Interessant und gut erklärt! Schön das es diese Seite gibt!

    Antworten
    • 9. Juli 2015 um 13:48
      Permalink

      Hallo Detlef,

      danke, so soll es sein. 🙂 Wenn Du Themenwünsche für weitere Lektionen hast . . . immer her damit.

      Viel Spaß und herzliche Grüße,

      Robert

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.