LED Uhr, Schrittmotor und Expander Chip Code

LED Uhr, Schrittmotor und Expander Chip Code Titelbild

LEDs einsetzen.

In dem Kit sind alle LEDs enthalten die du brauchst und Ersatz, falls mal eine ausfällt oder kaputt geht. Auf dem Aufkleber ist der Platz für die LEDs durch schwarze Punkte markiert. Drücke die LEDs durch die Pappe, achte darauf, dass das kurze Bein zu Mitte zeigt. Drücke die Beine der LED dann nach innen und außen, aber so, dass sich die Beine nicht berühren. Wir empfehlen dir die Jumperkabel an die LEDs zu löten! Du kannst sie aber auch stecken.

Damit es übersichtlich bleibt, haben wir dir ein zweites Breadboard eingepackt. Verbinde die GPA und GPB Pins des I/O Expander Chips mit dem zweiten Breadboard.

GPB-1 wird oben in das zweite Breadboard in Reihe eins gesteckt. GPB-2 in 2 und so weiter. Diese Verbindungen steuern unsere LEDs. Zum Testen kannst du auch einfach LEDs in das Breadboard stecken. Oder du verbaust direkt die LEDs in der Uhr, das geht natürlich auch.

Stundenanzeige programmieren

Wir wollen die aktuelle Stunde über die LEDs anzeigen. Um 1 Uhr soll eine LED leuchten und um 10 Uhr 10 LEDs. Dafür brauchen wir die aktuelle Uhrzeit und den Hexadezimalwert der GPA und GPB Pins.

Die Uhrzeit
Die Uhrzeit bekommen wir aus der Bibliothek time. Diese binden wir wie gewohnt am Anfang unseres Programms ein. Dann können wir die Uhrzeit auslesen und in eine Variable speichern.

import time
now=time.strftime("%H")
print (now)

Die aktuelle Uhrzeit bekommen wir normalerweise als Timestamp. Mit diesem können die Wenigsten etwas anfangen. Es ist eine sehr lange Zahl, die die Zeit in Millisekunden seit 1970 ausgibt. Jetzt wäre es nach time 1496752816. Hierbei hilft uns Python und gibt uns die Möglichkeit, einen leserlichen String aus dem Timestamp zu generieren. Wir können uns sogar aussuchen, welche Daten wir haben wollen. strftime(“%A %d.%.m%Y %H:%M”) gibt beispielsweise Folgendes aus: Tuesday 06.06.2017 14:44

Es gibt sehr viele Datum und Uhrzeit relevante Daten, die wir uns so ausgeben lassen können. Eine Liste findest du hier: https://docs.python.org/3/library/time.html

Wir brauchen die Stunde. Diese können wir als %H im 24 Stunden Format abfragen oder mit %I im 12 Stunden Format. Beide Werte sind für uns nicht optimal. Bei %I wird eine Führende 0 angehängt. zum Beispiel 03 und im 24 Stunden Format müssen wir 12 Stunden abziehen falls es nach 12 Uhr ist. Eine Führende 0 können wir mit replace ersetzen, wie das geht, steht oben beschrieben, oder wir wandeln diesen String in einen Integer um. Das machen wir wie gewohnt mit der int() Funktion.

now=int(time.strftime("%I"))

Jetzt haben wir die aktuelle Stunde als Zahl. Diese Zahl soll festlegen, wie viele LEDs leuchten sollen. Die Stunden 1-8 liegen auf GPB 1-8 und 9-12 auf GPA 1-4. Da wir in einem GP Block nur acht Pins sind und wir zwölf brachen, schalten wir GPA und GPB immer zusammen. Wir tun erstmal so, als ob wir 16 GPIO haben, die wir alle gleichzeitig definieren. Dafür rufen wir uns in Erinnerung, was einen String von einem Integer unterscheidet. Ein String ist eine Folge von Zeichen aller Art, während ein Integer eine ganze Zahl ist. Einer der Vorteile von Strings ist, dass man Dinge anhängen kann.

a = str(“Raspberry ”)
b= str(“Pi”)
print (a + b)

Print gibt dann a + b aus, Raspberry Pi . Das geht auch mit Zahlen, solange diese in einem String gespeichert sind. Kommen wir zurück zu unseren LEDs. Wenn die Uhrzeit 4 Uhr ist, wollen wir vier LEDs leuchten lassen. Wir brauchen also einen String mit dem Inhalt 0000000000001111. Eine Möglichkeit wäre eine lange Liste mit if Anfragen.

if now=int(time.strftime("%I")) == “4”
 leds=”0000000000001111”

Das funktioniert, ist aber nicht gerade schön. Einfacher ist es, für jede Stunde eine 1 zu unserem String hinzuzufügen.

import time
stunde = int(time.strftime("%I"))
leds = ""
zaehler = 0
while zaehler < stunde :
    leds = (leds + "1")
    zaehler = (zaehler + 1)
    print (leds)

In Zeile 1 importieren wir time für die Uhrzeit. Zeile 2 speichert die aktuelle Stunde als stunde als Integer. Dadurch verschwindet eine möglich existierende führende Null. Zeile 3 definiert die Variable leds. Zeile 4 setzt unsere Zählvariable zaehler auf 0. Zeile 5 startet eine while-Schleife. Solange zaehler < stunde:, (Zähler ist kleiner als die aktuelle Stunde), werden die folgenden eingerückten Zeilen ausgeführt. Zeile 6 fügt der Variable leds eine 1 hinzu. Zeile 7 erhöht den Wert von der variable zaehler um 1. Diese beiden Zeilen laufen immer wieder durch. Erst wenn zahler denselben Wert hat wie stunde hört es auf. In Jedem Durchlauf wird unser String leds um eine 1 erweitert.

1
11
111 usw.

Der String leds enthält jetzt 1. bis 12. mal 1 Jetzt brauchen wir die restlichen Stellen nur noch mit 0 zu füllen. Dafür gibt es verschiedene Möglichkeiten, wir haben uns für zfill() entschieden. zfill() füllt einen String mit 0 auf bis zu der angegebenen Länge. Unser String, leds soll 16 Zeichen lang sein, wir benutzen also:

leds = leds.zfill(16)

Jetzt haben wir unseren String mit allen Informationen, die wir brauchen. Diesen teilen wir jetzt auf. Die ersten acht Stellen definieren den Zustand der GPA Pins die letzten acht Stellen den der GPB Pins.

gpb = leds[8:]
gba = leds[:8]

Das [8:] definiert, wie viele Stellen des Strings wir übernehmen oder ausgeben wollen. print (leds[8:]) gibt den leds ab der achten Stelle aus, leds[:8]gibt alles bis zu acht Stelle aus.

Jetzt haben wir zwei binäre Strings.

gpa = “00001111”
gpb = “11111111”

Diese Werte wollen wir an unseren I/O Expander Chip übergeben. Dafür brauchen wir die binären Werte als hexadezimal. Wir haben bereits gelernt wie man das machen kann.

gpa = “00001111”
print (hex(int(gpa,2)))

Wir können den Wert aber auch als dezimal übergeben. Von binär zu dezimal hilft uns wieder die int Funktion.

gpa = int(gpa,2) ergibt 15. Diese 15 können wir anstatt des Hexadezimalwertes 0x0f verwenden. Der Vorteil ist, dass wir uns nicht um führende Nullen kümmern brauchen.

gpb = int(gpb,2)
gpa = int(gpa,2)

Jetzt haben wir es fast geschafft. Die errechneten Werte übergeben wir nun an unseren Raspberry Pi.

bus.write_byte_data(0x20, 0x15, gpa)
bus.write_byte_data(0x20, 0x15, gpb)

Bevor wir das jetzt in unser System einbauen, hier nochmal das komplette Programm:

import smbus
import time

bus = smbus.SMBus(1)
bus.write_byte_data(0x20, 0x01, 0x00)
bus.write_byte_data(0x20, 0x00, 0x00)

stunde = int(time.strftime("%I"))
leds = ""
zaehler = 0
while zaehler < stunde :
        leds = (leds + "1")
        zaehler = (zaehler + 1)

leds = leds.zfill(16)
gpb = leds[8:]
gpa = leds[:8]

gpa = int(gpa,2)
gpb = int(gpb,2)

bus.write_byte_data(0x20, 0x15, gpa)
bus.write_byte_data(0x20, 0x15, gpb)

Super, wenn du dieses Programm ausführst, fangen deine LEDs an zu leuchten. Die LEDs für die Stundenanzeige ändert sich nur einmal in der Stunde. Wir wollen natürlich nicht jede Stunde manuell die LEDs aktualisieren. Deswegen greifen wir auf einen Cronjob zurück, der jede Stunde ausgeführt wird. Öffne den Crontab mit

crontab -e

und füge am Ende folgendes ein:

0 * * * * python3 /home/pi/stunden.py

Jetzt läuft unser Script automatisch in Minute 0 zu jeder Stunde.

Schrittmotor als Minutenzeiger

Für unsere Uhr brauchen wir nicht nur die Stunden, sondern auch einen Minutenzeiger. Deinen Motor kannst du schon manuell ansteuern. Jetzt wollen wir ihn benutzen, um die Minuten mit dem Zeiger darzustellen. Wir erinnern uns, dass der Motor 512 Schritte braucht für eine ganze Umdrehung. Eine Umdrehung sind 360 Grad oder 60 Minuten. Die 360 Grade helfen uns in diesem Fall leider nicht weiter. Wir wissen aber, dass wir 60 Minuten anzeigen wollen. Wir können also unsere Schritte in Minuten aufteilen. 512 Schritte geteilt durch 60 Minuten. 512 / 60 sind 8,533. Wir müssten also jede Minute 8,533 Schritte machen. Leider kann der Motor keine halben oder drittel Schritte. Wir können aber andersherum rechnen. 60 Minuten sind 3600 Sekunden. 3600 / 512 sind 7,03125 Sekunden. Alle 7,03125 Sekunden einen Schritt machen wäre möglich. Wir haben das ausprobiert. Es ergeben sich zwei Probleme. Zum einen nervt es unglaublich, wenn der Zeiger sich so unregelmäßig bewegt. Anscheinend sind wir doch sehr gewöhnt an Uhren, die sich gleichmäßiger bewegen. Ein ganz anderes Problem ist die Auslastung des Pi. Der Pi ist keine Uhr, sondern ein Computer. Wenn man ihn für mehr benutzt als die Uhrzeit, dann kann es unter großer Last dazu kommen, dass er Befehle nicht sofort, sondern leicht verzögert ausführt. So kann es passieren, dass sich zwei Kommandos, die den Zeiger bewegen sollen, überschreiben und blockieren. Wir gehen also zurück zu unser ersten Idee und bewegen den Zeiger jede Minute um 8,5333 Schritte. Der Motor kann keinen halben Schritt machen, wir müssen also runden. Wir machen also acht oder neun Schritte. Wenn wir jede Minute einen halben Schritt weg lassen geht unsere Uhr nach wenigen Stunden super falsch. Wir müssen den halben Schritt also aufheben und dann nachholen.

Keine Angst, wir machen es uns ganz einfach. Jede gerade Minute machen wir 8 Schritte und jede ungerade Minute machen wir 9 Schritte. 30x8 Schritte sind 240 und 30x9 Schritte sind 270, macht zusammen 510 Schritte auf eine Stunde. Uns fehlen also noch zwei Schritte für eine volle Umdrehung. Diese zwie Schritte holen wir einfach zu vollen Stunde nach und machen sie extra.

In Python sieht das so aus:

import os
import time

minute=time.strftime("%M")

if int(minute) & 1:
 os.system("python motor.py 9")
else:
 os.system("python motor.py 8")

if int(minute) == 0:
 os.system("python motor.py 2")

Erstelle dieses Programm im selben Ordner, in dem du die motor.py heruntergeladen hast.

Zeile 1 importiert die Bibliothek os , diese ermöglicht es uns, mit Python Befehle in der Konsole auszuführen. Die Funktionen für Zeit in Zeile 4 haben wir bereits erklärt. %M enthält die aktuelle Minute. Zeile 7 startet eine if-Abfrage und schaut, ob die minute ungerade ist. Falls das so ist, rufen wir das motor.py Programm auf und sagen ihm, dass wir neun Schritte gehen wollen. Falls die Minute eine gerade Zahl ist, bewegen wir uns nur acht Schritte. In der letzten if-Schleife fragen wir ab, ob die Minute 0 ist. Dann machen wir noch zwei Schritte extra mit dem Motor.

Genauso wie die Stunden, wollen wir dieses Programm automatisch ausführen lassen. Dafür benutzen wir wieder einen Cronjob. Öffne die Cronjob-Verwaltung mit dem Befehl: crontab -e und füge am Ende folgendes ein:

* * * * * python3 /home/pi/minute.py

Jetzt haben wir es fast geschafft. Mit der motor.py kannst du die Uhrzeit stellen. Bewege den Zeiger einfach um ein paar Schritte bis er die richtige Uhrzeit anzeigt. Deine Uhr läuft jetzt automatisch und sollte ungefähr richtig gehen.

Herzlichen Glückwunsch

Du hast deine eigene Uhr gebaut! Auf dem Weg haben wir viel über Python und den Umgang mit Zahlen, Werten und Variablen gelernt. Du weißt jetzt was dezimal, binär und hexadezimal ist. Außerdem kannst du einen Schrittmotor ansteuern und nutzen. Durch den I/O Expander Chip stehen dir zusätzliche GPIO Ports zur Verfügung. Wie man diese benutzt, hast du ebenfalls gelernt.

Wir hoffen, du hattest viel Spaß mit dem Jugend Programmiert Kit - LED UHR. Für Fragen und Anregungen kannst du uns jederzeit kontaktieren. Viele Grüße Dein Coding World Team

Noch Fragen oder Feedback?

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