Deine Binäruhr

Deine Binäruhr Titelbild

Binär Uhr - Was soll das sein?

Heutzutage ist es ziemlich wichtig, stets über die aktuelle Uhrzeit informiert zu sein. Unter anderem hängen aus diesem Grund auch überall Uhren herum. Überhaupt kann man eigentlich nirgends mehr hin gehen, ohne dass einem aufgefordert oder unaufgefordert die aktuelle Uhrzeit aufgedrängt wird. Blöd nur, dass die meisten Uhren so schnöde aussehen, dass es gar keinen Spaß mehr macht, die so wichtige Uhrzeit überhaupt abzulesen. Wie könnte man dieses Problem nur lösen?

Die Antwort liegt ja eigentlich schon auf der Hand: Wir stellen die Zeit einfach mit LEDs dar! Das ist die aller beste Lösung, die man sich nur vorstellen kann, nicht weil es der einfachste oder effektivste Weg ist dieses Problem zu lösen, sondern einfach nur, weil die ganze Geschichte am Ende super cool aussehen wird. Und jetzt bitte keine weiteren Fragen zu dieser Logik.

Da es nichts besonderes ist, eine Uhr zu bauen, die gewöhnliche Zahlen anzeigt, ist das hier eine Anleitung zum Bau einer Binäruhr. Diese Uhr stellt die Stunden und Minuten also im sogenannten Binärsystem dar. Zufälliger Weise ist das Binärsystem auch eine wichtige Grundlage, um die Funktionalität von Computern zu verstehen. Im Binärsystem gibt es nur Einsen und Nullen und in der Sprache der Computer besteht alles aus Einsen und Nullen. Zwar wird diese Sprache der Computer in etwas für uns verständliches übersetzt, wenn wir mit diesen kommunizieren, aber unter der Haube deiner Daddel-Konsole regiert die Sprache der Binärzahlen.

Das Prinzip von Binärzahlen ist einfach und schnell erklärt.

Dezimalzahl Binärzahl
eins 0001
zwei 0010
drei 0011
vier 0100
fünf 0101
sechs 0110
sieben 0111
acht 1000
neun 1001
zehn 1010
elf 1011
zwölf 1100
dreizehn 1101
vierzehn 1110
fünfzehn 1111

Hinter dem ganzen Zahlengewusel steckt ein ganz einfaches System. Wenn wir uns schon mal die Zahl fünfzehn im Dualsystem ansehen lautet diese 1111. Wenn wir diese wieder zurück übersetzen wollen, können wir das mit dieser einfachen Tabelle machen. Jede stelle in dieser Reihenfolge hat einen bestimmten Wert:

8 4 2 1 Dezimalzahl
0 0 0 1 eins
0 1 1 1 sieben
1 1 1 1 fünfzehn

In unserem System, das Dezimalsystem, haben wir die Zahlen 0-9 und wenn wir jetzt aber die Zahl 15 darstellen wollen hohlen wir uns einfach nur eine zweite Zahl dazu. Im Binärsystem ist das nicht so einfach möglich, den wir haben nur 1 und 0! Deswegen lesen wir von links und jede Zahl in der Spalte hat einen festen Wert. Dieses verdoppelt sich immer wieder und deswegen können wir mit einer Binärzahl auch unendlich große Zahlen speichern. Wenn eine 1 unter dem Wert steht müssen wir die Zahl oben in der Spalte dazu rechnen, bei einer 0 nicht. 101 ist dann folglich fünf den wir haben bei der einser Spalte eine 1 und bei der vierer Spalte eine 1. Eins+vier ist gleich fünf. Übung macht den Meister und im Kopf umrechnen macht das viel einfacher.

Wir fangen dabei immer an von Links zu lesen. Die Zeile ganz oben lässt sich auch beliebig erweitern in dem du die Werte einfach verdoppelst. Das heißt, die Dezimalzahl 60 wäre folgende Binärzahl: 111100

Das Dualsystem in Python

Jetzt weißt du genug über die Hintergründe, aber wie funktioniert das ganze nun mit unserer liebsten Programmiersprache Python? Dafür gibt es die Funktion: bin() in die wir eine Dezimalzahl eingeben können, die dann in eine Binärzahl umgewandelt wird. Beachte, dass die Funktionen einen String, also eine Zeichenkette, ausgibt.

print(bin(60))

Sollte bei euch im Terminal: 0b111100 ausgeben. Die ersten beiden Zeichen "0b" geben an, dass es sich bei diesem Wert um einen binären String handelt. Das ist für unsere Binäruhr nicht so wichtig, deswegen können wir diese, weil es sich ja um einen String handelt, einfach ausschneiden. Auch dafür haben wir natürlich eine Funktion auf Lager.

print(bin(60)[2:])

Nun wird einfach nur noch 111100 ausgegeben. Die 2 in den eckigen Klammern sagt der Funktion, dass sie die ersten beiden Zeichen einfach weg lassen soll.

Bevor du den Programmcode schreibst, der deiner Uhr das eigenständige Arbeiten ermöglicht, ist es bestimmt keine schlechte Idee, zunächst die die Grundlagen für eine funktionierende Uhr zu legen, die Uhr selbst.

Insgesamt benötigst du 11 LEDs. 6 für die Minuten und 5 für die Stunden. Warum 6 LEDs für die Minuten? Es gibt Maximal 60 Minuten pro Stunde und 60 ist als Binärzahl: 111100, daher die 6 LEDs. Da es aber nur 24 Stunden 11000 gibt, können wir uns da einfach die sechste LED sparen und brauchen nur 5 LEDs. Also ran ans Breadboeard und schnell die folgende Schaltung zusammengesteckt.

279.png
Anschlüsse am Pi LEDs
GPIO 17 LED 1 (Rot)
GPIO 27 LED 2 (Rot)
GPIO 22 LED 3 (Rot)
GPIO 10 LED 4 (Rot)
GPIO 9 LED 5 (Rot)
GPIO 5 LED 1 (Grün)
GPIO 6 LED 2 (Grün)
GPIO 13 LED 3 (Grün)
GPIO 19 LED 4 (Grün)
GPIO 26 LED 5 (Grün)
GPIO 21 LED 6 (Grün)

Die LEDs sind von oben nach unten nummeriert. Bitte achte darauf, die kurzen Beine der LEDs über das Breadboard immer mit dem Ground (GND) deines Raspberry Pi zu verbinden. Sonst geht deine Uhr schneller kaputt also du: "Oh nein, ich habe die LEDs falsch herum angeschlossen!" sagen kannst.

import RPi.GPIO as gpio
import time
from datetime import datetime

gpio.setmode(gpio.BCM)

ledsStunde = [17, 27, 22, 10, 9]
ledsMinute = [5, 6, 13, 19, 26, 21]

def start():
    for i in range (5):
        gpio.setup(ledsStunde[i], gpio.OUT)
    for j in range(6):
        gpio.setup(ledsMinute[j], gpio.OUT)

def aktualisiereStunde(stunde):
    binaerStunde = bin(stunde)[2:][::-1]
    for i in range(5):
        gpio.output(ledsStunde[i], gpio.LOW)
    for i in range(len(binaerStunde)):
        if binaerStunde[i] == "1":
            gpio.output(ledsStunde[i], gpio.HIGH)
def aktualisiereMinute(minute):
    binaerMinute = bin(minute)[2:][::-1]
    for j in range(6):
        gpio.output(ledsMinute[j], gpio.LOW)
    for j in range(len(binaerMinute)):
        if binaerMinute[j] == "1":
            gpio.output(ledsMinute[j], gpio.HIGH)
start()
try:
    while True:
        aktualisiereStunde(datetime.now().hour)
        aktualisiereMinute(datetime.now().minute)
        time.sleep(60)
except KeyboardInterrupt:
    gpio.cleanup()

Schritt für Schritt

In den ersten 3 Zeilen importieren wir wieder die benötigten Bibliotheken. Auch die datetime Bibliothek. In Zeile 7 und 8 legen wir alle LEDs für unsere Uhr in eine Liste.

In Zeile 10 lernen wir zum ersten Mal etwas Neues kennen. Wir fangen an und erstellen unsere eigenen Funktion. Vor allem bei längeren Programmen haben wir das Problem, dass es einige Komponenten gibt, die immer und immer wieder benutzt werden. Für vieles gibt schon fertige Funktionen wie die bin()-, str() oder die int()-Funktion. Es wird aber Zeit, dass wir uns auch eigene Funktionen erstellen können. Das ist einfach. Mit def nameDerFunktion(): sagen wir Python, dass alles, was danach eingerückt ist, zu der erstellten Funktion gehört. Danach kann diese Funktion auch jederzeit mit nameDerFunktion() aufgerufen werden. Gut das wir das jetzt geklärt haben! In Zeile 11, also der ersten Zeile der Funktion, rufen wir eine for Schleife aus. Eine Schleife ist ein Funktionsblock, der solange ausgeführt wird, wie eine Bedingung erfüllt wird. Bei der for Schleife können wir aber auch noch einen Wert übergeben. In diesem Beispiel benutzen wir die for Schleife in Kombination mit der Funktion range(). Diese liefert uns eine definierte Anzahl von Werten zurück. range(5) würde alles von 0 bis 5 zurückgeben. Das heißt mit for j in range(5): wird das Innere der Schleife fünfmal aufgerufen. Beim ersten Mal hat i den Wert 1 und beim letzten Mal den Wert 5. Das eignet sich perfekt, um einmal die Liste mit allen LEDs durchzugehen und ihnen dann in Zeile 12 und 14 zu sagen, wie sich die verbundenen GPIO Pins verhalten sollen. Anstatt mühselig elfmal das Gleiche zu schreiben, müssen wir das nur einmal pro Liste der LEDs machen. Das heißt mit der Funktion start() gehen wir sicher, dass der Raspberry Pi weiß, wie sich die GPIO Pins verhalten sollen.

In Zeile 16 gibt es unsere zweite Funktion, die mit def aktualisiereStunde(stunde):. Im Gegensatz zur ersten Funktion muss bei dem Aufruf dieser Funktion noch ein Wert übergeben werden. Dieser Wert bekommt die interne Variable stunde und kann dann innerhalb der gesamten Funktion aufgerufen und verwendet werden. So kann jeder Stunde auch ein anderer Wert angezeigt werden.

In Zeile 17 wird zuerst der Stundenwert, den wir als Dezimalzahl bekommen haben, in eine Binärzahl umgewandelt und in der Variablen binaerStunde gespeichert. Mit [::-1] spiegeln wir den Wert des Textes, denn bei der Ausgabe der Binärzahl müssen wir auch von Links anfangen zu lesen. Dann benutzen wir die bekannte for schleife und laufen alle LED-Werte durch, um diese erst einmal auszuschalten. In der Zweiten for Schleife gehen wir dann den binären String durch. Wenn die Zahl eine 3 ist, wollen wir natürlich auch, dass die erste und zweite LED, von links, leuchtet. Deswegen schalten wir erst einmal jede LED aus. In Zeile 20 kontrollieren wir dann mit einer if-Abfrage, ob sich an dieser Position in der Binärzahl eine 1 befindet. Wenn das der Fall ist, schaltet sich die LED wieder an.

In Zeile 23 wiederholt man das Gleiche mit der Funktion aktualisiereMinute(minute). Zuerst wird die minute in eine Binärzahl umgewandelt. In Zeile 25 läuft wieder einmal die for Schleife durch alle Werte. Zuerst wird die LED ausgeschaltet und wenn sich an ihrer Position in der Binärzahl eine 1 befindet, leuchtet sie wieder auf.

Bis jetzt ist in unserem Programm nicht wirklich etwas passiert, denn keine Funktion wurde aufgerufen. Aber das wird sich jetzt auch ändern. In Zeile 30 wird die start() Funktion aufgerufen und damit die GPIO Pins konfiguriert. In Zeile 31 start die try Schleife. Diese Schleife läuft solange, bis das eingetreten ist, was in Zeile 36 bei dem except: (engl. für Ausnahme) steht. In unserem Falle steht dort KeyboardInterrupt. Das heißt es wird solange alles ausgefüllt, was in der try: Schleife steht, bis das Programm über das Terminal abgebrochen wird. Das kannst du machen, indem du Strg/Cmd + C drückst. Wenn du das gemacht hast, wird in Zeile 37 gpio.cleanup() ausgeführt und alle Pinnbelegungen werden wieder aufgeräumt.

Aber jetzt zum interessanten Teil. In Zeile 32 läuft eine While-Schleife und wiederholt einfach nur die Funktionen. Zuerst wird die Funktion aktualisiereStunde(datetime.now().hour) ausgeführt. Als Wert übergeben wir die aktuelle Stunde. In der nächsten Zeile passiert genau das Gleiche mit den Minuten. Danach sagen wir dem Programm in Zeile 35 mit time.sleep(60), dass es eine Minute lang Pause machen darf, desn in den nächsten 60 Sekunden wird sich die Binäruhr nicht verändern. Und was das umrechnen von Binärzahlen in Dezimalzahlen betrifft: Übung macht den Meister!

Die Zeit erklärt

Auch wenn es hilfreich ist zu wissen, wie Integers zu Binärzahlen in Python umgewandelt werden können, fehlt uns noch eine wichtige Komponente für unser Pythonprogramm und zwar die Zeit. Bei der Uhrzeit wird es ein wenig komplizierter und dafür müssen wir erst das Paket datetime mit in das Programm einbinden.

from datetime import datetime
stunde = datetime.now().hour
binaerStunde = bin(stunde)[2:]
print(binaerStunde)

In der ersten Zeile importieren wir die datetime Bibliothek. Auf Deutsch wäre das mit Datum und Uhrzeit zu übersetzen. Diese gibt uns die Möglichkeit mit Python auf die lokale Uhrzeit zuzugreifen.

Da dein Pi in Großbritannien auf die Welt gekommen ist, denkt er voreingestellt immer noch in dieser Zeitzone und deswegen kann es sein, dass du alles richtig gemacht hast, aber die Einstellung der Zeitzonen noch geändert werden muss. Das kannst du so prüfen.

date

Im Codetrainer findest du eine Anleitung wie du diese Einstellung verändern kannst.

Doch diese Bibliothek kann sehr viel, doch wir brauchen nur den gleichnamigen Teil datetime Mit datetime.now() bekommen wir den jetzigen Zeitpunkt und können uns dann die Werte heraussuchen, die wir gerade brauchen. Neben .hout und .minute gibt es auch noch .month für den aktuellen Monat, .year für das aktuelle Jahr und .second für die aktuelle Sekunde.

Noch Fragen oder Feedback?

Bevor du eine Frage stellen kannst musst du dich zuerst Anmelden oder Regestrieren!