Ein Countdown ist nicht nur in der Raumfahrt sinnvoll. Mit einem Raspberry Pi und etwas Elektronik zählen Sie die Zeit bis zu einem beliebigen Ereignis optisch eindrucksvoll herunter.
Im Leben gibt es immer wieder Ereignisse, bei denen wir es kaum abwarten können, bis sie endlich eintreten. Ein Countdown-Zähler kann dabei helfen, diese Wartezeit zu verkürzen und die Vorfreude zu steigern – wer zu Zeiten der Wehrpflicht als “Ausscheider” jeden Tag feierlich sein Maßband um einen Zentimeter gekürzt hat, der weiß, was gemeint ist. Solche schnöden analogen Methoden lassen sich im 21. Jahrhundert freilich durch eine schicke digitale Lösung auf Basis eines Raspberry Pi ersetzen.
Damit sich der Countdown auch von Weitem noch gut ablesen lässt, kommt zur Anzeige der restlichen Tage bis zum Ereignis eine große 7-Segment-Anzeige des Typs Kingbright SC08-11SRWA [1] mit einer Höhe von 20,32 Millimeter zum Einsatz. Deren LEDs verwenden eine gemeinsame Kathode (Common Cathode), was die Anzeige zu einem Display Driver MAX7221 kompatibel macht.
Diese Kombination erfordert den Einsatz eines Lötkolbens. Zwar gibt es fertig aufgebaute Module mit dem MAX7221, jedoch nur mit erheblich kleineren Anzeigen und (meist) 8-stelliger Anzeige, passend zu den Fähigkeiten des MAX7221. Für unseren Countdown sollten schon 4 Stellen genügen: Damit lassen sich 9999 Tage abbilden, also über 27 Jahre. Wollen Sie tatsächlich länger herunterzählen, spendieren Sie dem Aufbau einfach noch ein zusätzliches Segment.
Display Driver MAX7221
Beim Display Driver MAX7221 steuert ein externer Widerstand den Strom für die LEDs. Wir wählen hier 33 kOhm, was einen Strom von etwas weniger als 20 Milliampere für ein Segment der Anzeige ergibt. Ansonsten benötigt der MAX7221 keine externe Beschaltung. Das Ansteuern des MAX7221 erfolgt über die SPI-Schnittstelle. Intern speichert das Display die zur Anzeige vorgesehenen Informationen in einem 8 mal 8 Bit großen RAM.
Die Tabelle “MAX7221: Registerbelegung” gibt einen Überblick über die Register des Chips und deren Funktion; das Datenblatt [2] des MAX7221 liefert weiterführende Informationen. Das Adressieren des MAX7221 erfolgt über die SPI-Schnittstelle. Dazu eignen sich viele Mikrocontroller – wir konzentrieren uns auf den Raspberry Pi.
MAX7221: Registerbelegung
|
Register |
Funktion |
Beschreibung |
|
|---|---|---|---|
|
|
No-Op |
Funktionslos. Dient bei mehreren SPI-Bausteinen an einem Bus dazu, gezielt nur einen Baustein anzusprechen. Alle anderen erhalten ein No-Op. |
|
|
|
Digit0 |
Stelle 0 der Anzeige |
|
|
|
Digit1 |
Stelle 1 der Anzeige |
|
|
|
Digit2 |
Stelle 2 der Anzeige |
|
|
|
Digit3 |
Stelle 3 der Anzeige |
|
|
|
Digit4 |
Stelle 4 der Anzeige |
|
|
|
Digit5 |
Stelle 5 der Anzeige |
|
|
|
Digit6 |
Stelle 6 der Anzeige |
|
|
|
Digit7 |
Stelle 7 der Anzeige |
|
|
|
Decode Mode |
Jedes Bit entspricht einer Stelle der Anzeige (Bit 0 = Stelle 0 etc.). Ist es gesetzt, arbeitet die Stelle als Segmentanzeige; die unteren 4 Bit der Digit-Register werden dann als BCD-Zahl interpretiert. Ist es gelöscht, lässt sich jedes Segment der Stelle als einzelne LED ansteuern. |
|
|
|
Intensity |
|
Die unteren 4 Bit des Registers steuern die Helligkeit der LEDs. |
|
|
Scan Limit |
Die unteren 3 Bit des Registers steuern, welche Stellen der Anzeige verwendet werden ( |
|
|
|
Shutdown |
Bit 0 = 1: Normalmodus, alle Anzeigen und Funktionen aktiv. Bit 0 = 0: Schlafmodus, alle Anzeigen aus, keine Reaktion auf Kommandos. |
|
|
|
Display Test |
Bringt alle LEDs zum Leuchten. |
Schaltplan
Im Schaltplan (Abbildung 1) unseres Countdown-Zählers stellt der MAX7221 das zentrale Bauteil dar. Mit den vier 7-Segment-Anzeigen verbunden, benötigt er mit dem Widerstand R1 nur ein externes Bauteil. Die komplette Schaltung arbeitet mit einer Betriebsspannung von 3,3 Volt. Die liefert ein Spannungsregler des Typs LD1117v33 von STMicroelectronics, der einen Eingangsspannungsbereich von 4,3 bis 15 Volt erlaubt.
Das macht den Aufbau recht unabhängig bei der Wahl der Spannungsquelle (USB-Netzteil, Autobatterie etc.). Zwei Kondensatoren dienen dazu, Schwankungen in der Eingangsspannung zu puffern, und wirken dem Schwingen des Spannungsreglers entgegen. Ein Pfostenstecker verbindet die Anschlüsse der SPI-Schnittstelle mit dem Raspberry Pi. Abbildung 2 zeigt den vollständigen Aufbau, eine Liste aller Komponenten finden Sie in der Tabelle “Bauteile”.
Bauteile
|
Anzahl |
Name |
Bezugsquelle |
Preis/Stück |
|---|---|---|---|
|
4 |
SC08-11SRWA |
reichelt.de |
1,15 Euro |
|
1 |
MAX7221CNG |
reichelt.de |
5,99 Euro |
|
1 |
PCB Prototype 8×12 |
aliexpress.com |
ca. 1 Euro |
|
div. |
Kleinteile |
Bastelkiste |
2 Euro |
|
In Summe etwa 20 Euro |
|||
Programm
Der Versuchsaufbau setzt auf einen RasPi 1 mit aktuellem Raspbian-Image auf, die hier beschriebenen Schritte funktionieren aber auch mit jedem anderen Raspberry-Pi-Modell.
Als Erstes aktivieren Sie mithilfe des Programms raspi-config über 5 Interfacing Options | P4 SPI die SPI-Schnittstelle. Nach dem nächsten Reboot findet sich im Geräteverzeichnis /dev/spidev0.0 des Raspberry Pi das SPI-Device, das sich wie ein zeichenorientiertes Gerät unter Unix verwenden lässt.
Das Listing 1 zeigt das Beispielprogramm counter.c, das zunächst einmal alle verwendeten Bibliotheken lädt und die nötigen Variablen definiert. Die Funktion write_register() kapselt die C-Funktion write() und sortiert die Parameter entsprechend zurecht. Die Funktion main() baut die Verbindung zum SPI-Gerät auf und setzt danach die Geschwindigkeit der SPI-Schnittstelle. Danach initialisiert sie den MAX7221 so, dass er die Stellen 0 bis 3 im Decoder-Modus verwendet und die Helligkeit auf das Maximum stellt.
Listing 1
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <inttypes.h>
#include <stdio.h>
#include <time.h>
static const char *device = "/dev/spidev0.0";
static uint32_t speed = 500000;
int handle, diff;
time_t ts_now, ts_target;
struct tm target;
void write_register(int handle, uint8_t regi, uint8_t value) {
uint8_t tx[] = { regi, value };
write(handle,tx,2);
}
int main() {
if ((handle = open(device, O_RDWR)) < 0) {
perror("SPI Device Error");
return 1;
}
if (ioctl(handle, SPI_IOC_RD_MAX_SPEED_HZ, &speed)<0) {
perror("SPI Speed Error");
return 1;
}
// MAX7221-Setup
write_register(handle,0x0C,0x01);
write_register(handle,0x09,0xFF);
write_register(handle,0x0F,0x00);
write_register(handle,0x0B,0x03);
write_register(handle,0x0A,0x0F);
ts_now = time(NULL);
target.tm_mday=1;
target.tm_mon=4; // Monat-1 (Jan=0)
target.tm_year=119; // Jahr-1900
target.tm_sec=59;
target.tm_min=59;
target.tm_hour=23;
ts_target=mktime(&target);
diff=(ts_target-ts_now)/(60*60*24);
write_register(handle,0x04,(diff%10000)/1000);
write_register(handle,0x03,(diff%1000)/100);
write_register(handle,0x02,(diff%100)/10);
write_register(handle,0x01,(diff%10));
}
Mithilfe der Datumsstruktur target erzeugen wir den Timestamp des Zieldatums. Die Struktur besitzt einige eigentümliche Eigenschaften, die viel Ärger verursachen können, wenn man sie nicht kennt: Die Tage zählt sie ab 1, die Monate ab 0, und beim Jahr muss man 1900 abziehen. Die Werte für die Tageszeit lassen sich eins zu eins in die Struktur schreiben, hier gibt es keine Sonderregelungen.
Die restlichen Programmzeilen errechnen die Differenz zwischen dem aktuellen und dem Zieldatum und schreiben die Werte dann in die entsprechenden Speicherstellen des MAX7221. Sie müssen das Programm nur einmal am Tag starten, damit es den aktuellen Anzeigewert errechnet und an den Display Driver übergibt. Das Starten des Programms übertragen Sie sinnigerweise einem Cronjob (siehe Kasten “Cron”).








