Die elektronische Sanduhr


Abbildung 1: Sanduhr ohne Gehäuse, Zeit ablaufend



Kinder können mit Zeitangaben nicht viel anfangen. Ein beliebtes Spiel besteht darin, dass abendliche Zubettgehen unendlich lang herauszuzögern. Eine gute Möglichkeit Kindern das Verrinnen der Zeit zu verdeutlichen besteht darin, eine Sanduhr zu verwenden, um den Ablauf einer vorher festgelegten Zeitspanne plastisch vor Augen zu haben. Alle Sanduhren, die der Autor auftreiben konnte, erlaubten allerdings nicht, wie gewünscht, Zeitspannen in der Größenordnung von 30 Minuten abzumessen. An dieser Stelle kam der Gedanke auf, eine elektronische Sanduhr aufzubauen, die es erlaubt beliebig einstellbare Zeitspannen elektronisch verrinnen zu lassen.

Die Anforderungen

Die elektronische Sanduhr sollte, wie eine reale Sanduhr den Ablauf einer Zeitspanne durch das Rinnen von „Zeitpartikeln“ aus einem oberen in einen unteren Behälter darstellen. Der Start der Zeitspanne wird dadurch definiert, dass sich alle Zeitpartikel im oberen Behälter befinden, der Ablauf dadurch, dass alle Zeitpartikel im unteren Behälter angekommen sind. Die Anzahl der gleichzeitig angezeigten Zeitpartikel soll zu jedem Moment gleich sein. Die Zeitspanne soll sich zwischen 1 und 99 Minuten einstellen lassen. Wie eine richtige Sanduhr soll sich die Laufrichtung der Zeitpartikel durch simples Drehen der Sanduhr umkehren lassen. Nur in aufrecht stehendem Zustand sollen sich die „Zeitpartikel“ bewegen, in liegendem Zustand soll der weitere Ablauf der rinnenden Zeit stoppen. Wenn die voreingestellte Zeitdauer abgelaufen ist und sich alle „Zeitpartikel“ im unteren Behälter befinden, soll ein akustischer Alarm erfolgen. Die Sanduhr soll durch Batterien versorgt werden. Der Controller soll über eine RS-232-Schnittstelle in der Applikation flashbar sein.

Das Hardwarekonzept

Die Zeitpartikel werden durch LED's symbolisiert. Zum Einsatz kommen 4 LED-Matrizen des Typs TC20-11RT (siehe [1]) von Kingbright mit insgesamt 140 LED's wobei jede Anzeige aus 7 Zeilen und 5 Spalten besteht. Die Ansteuerung jeder LED-Matrix erfolgt über einen mehrfach 7-Segment-LED-Displaytreiber MAX7221CNG (siehe [2]). Da dieser IC 7 Segmente ansteuern kann, passt das ideal zu den 7 Zeilen der LED-Matrix. Weiterhin kann er 7 Einzeldigits ansteuern, was für die 5 Spalten ausreicht. Theoretisch hätte man die 2 freien Ausgänge auch noch nutzen können, aber jede der 4 LED-Matrizen sollte bei gleicher Ansteuerung das gleiche Bild liefern. Die MAX7221CNG werden über eine SPI-Schnittstelle vom Microcontroller angesteuert, alle 4 MAX7221CNG sind bezüglich ihrer SPI-Schnittstelle hintereinander verschaltet, um mit einem Minimum an Ansteuerungsleitungen am Microcontroller auszukommen.

Die Einstellung der Zeitspanne erfolgt über den 2bit-Encoder SW1 der einen zusätzlichen Drückschalter besitzt, der zum Bestätigen der Eingaben dient. Die Schalter sind über die Pull-Up-Widerstände R1, R2, und R3 nach VCC gezogen.

Die Lageermittlung der Sanduhr erfolgt über einen 3achsigen Beschleunigungssensor von ADXL330KCPZ-RL von Analog Devices, der über 3 Analogausgänge 0 bis 5 V verfügt. Diese sind an 3 ADC-Eingänge des Controllers angeschlossen. Der Beschleunigungssensor ist in einem Modul von Pollin (Beschleunigungssensor-Modul Best. Nr.: 810143) zusammen mit einem Längsregler integriert. Das Modul wird auf den 5poligen Pinheader JP1 aufgesteckt.

Zur Pegelwandlung der seriellen, asynchronen Schnittstelle des Microcontrollers dient ein MAX232 (IC6) von dem nur 2 der 4 integrierten Kanäle verwendet werden.

Als Microcontroller wird ein Renesas R8C13 (siehe [3]) verwendet. Dieser wird allerdings in Form des Elektorboards (Bestellbezeichnung EVBR8C13 bei Reichelt) eingesetzt, auf dem sich schon der Quarz und eine Minimalbeschaltung befinden. Das Elektorboard wird über einen 32poligen DIL-Sockel (IC5) kontaktiert. An Randbeschaltung befindet sich auf dem Board noch der Resettaster S1 und der Umschalter zwischen Download- und Run-Mode S2. Zur Versorgung der LED-Treiber und des Microcontrollers kommt ein Längsregler 7805 zum Einsatz.

Die Schaltung der MAX7221 erfolgt nach MAXIM-Datenblatt. Mit den Widerständen R5, R7, R8 und R9 erfolgt eine Stromeinstellung der LED-Treiberströme. Bei der Sanduhr wurden Widerstände mit einem Wert von 56 kOhm eingesetzt.

An JP3 kann ein Treiber für einen Buzzer angeschlossen werden, der dann den Ablauf der Sanduhr auch akustisch signalisiert.

Abbildung 2 zeigt die komplette Schaltung der Sanduhr.


Abbildung 2: Schaltung der Sanduhrplatine




Für die komplette HW wurde eine Platine in Eagle entworfen. Aufgrund der Limitierung der Freewareversion auf Platinen der Größe 80 mm x 100 mm ist der Aufbau etwas gedrängt und es gibt auch 2 Bestückseiten.

Unter folgendem Link findet sich ein ZIP-Archiv mit den Eagle-Daten der Sanduhr (Link).

Die folgenden Abbildungen zeigen das Platinenlayout auf der Top- und Bottomseite.


Sanduhr_Artikel_html_m738b8f6b.jpg Sanduhr_Artikel_html_m5986a690.jpg
Abbildung 3: Platinenlayout Top Seite Abbildung 4: Platinenlayout Bottom Seite


Die folgenden Abbildungen zeigen die Bestückungspläne von oben und unten :

Sanduhr_Artikel_html_m1d1d83da.png Sanduhr_Artikel_html_m387ead62.png
Abbildung 5: Bestückplan Top Abbildung 6: Bestückplan Bottom


Anmerkung Layoutfehler: Nachdem die Platine hergestellt und bestückt war, zeigte sich ein Fehler in der Schaltung. Die Reihe 4 aller LED-Matrizen war nicht mit einem Treiberausgang des MAX7221 verbunden. Deswegen wurde wie jetzt in der Schaltung zu sehen, der SEGG-Ausgang des Treibers mit dem Pin 5 der LED-Matrix verbunden. Das ist im Layout nicht berücksichtigt und die Verbindung wurde per Draht nachträglich verbunden.

HW-Verbesserungsmöglichkeiten : Der Einsatz des Linearreglers 7805 ist bei einem batteriebetriebenen Gerät nicht günstig. Bedingt durch den hohen Spannungsdrop von 4 V über dem Linearregler – die Sanduhr wird durch ein Paket von 6 Mignonzellen versorgt – ergibt sich über ihm bei einer maximalen Stromaufnahme von 150 mA ein hoher Verlust. Aus diesem Grund wurde der 7805 durch einen pinkompatiblen Schaltregler AIMTEC AMSR-7805-NZ (Datenblatt siehe [4]) ersetzt. Durch diesen Baustein halbierte sich die Stromaufnahme nahezu auf nur noch 80 mA bei 9 V Versorgungsspannung.

Mechanischer Aufbau

Als Gehäuse wurde ein durchsichtiges, rot eingefärbtes Gehäuse von Hammond (Bestnr.: 522577 bei Conrad) verwendet. Die Platine konnte nur über 2 Bohrungen, in die nach hinten ragende Schrauben eingesetzt wurden, befestigt werden. Um den Einbau relativ simpel hinzubekommen, wurde die Platine in den tiefen Gehäuseteil mit Hilfe einer Adapterplatte eingesetzt. Aus diesem Grund ist auch der vorgesehene Gehäusedeckel nicht mehr die Frontseite, sondern der rückwärtige Gehäusedeckel. Die Adapterplatte wurde aus Sperrholz mit aufgeklebten Leisten hergestellt, um die Befestigungsschrauben seitlich eindrehen zu können und keine Schraubenköpfe auf der Frontseite zu haben. Problematisch bei diesem Einbau waren die mittleren Schraubdome die den Gehäusedeckel festhielten. Da die Platine mit den aufgesteckten LED-Matrix-Displays zu breit war, mussten diese Dome entfernt werden. Leider war das nicht komplett von hinten möglich, sondern sie mussten von vorn ausgebohrt werden (verbleibende Öffnungen (5) in Abbildung 8).

In den rückwärtigen Deckel des Gehäuses wurde ein Batteriehalter für 6 Mignonzellen eingeklebt.


Abbildung 7: Gehäuse von hinten, geöffnet


Zusätzlich wurden in das Gehäuse noch ein Ein/Aus-Schalter ((1) in Abbildung 8), eine 6.3mm-Klinkenbuchse für ein externes Netzteil, sowie der Buzzertreiber integriert. Der Verdrahtungsplan dieser Komponenten findet sich in der folgenden Abbildung 9. Der Buzzertreiber wurde über doppelseitiges Klebeband in die Gehäuseseitenwand geklebt. Die Öffnung des Piezosummers wurde freigespart und in der Gehäusewand befindet sich auch eine seitliche Schallaustrittsöffnung ((2) in Abbildung 8).

Auf der Vorderseite schaut der Umschalter S2 zwischen Boot- und Run-Mode heraus und es befindet sich die Betätigungsöffnung ((4) in Abbildung 8) für den internen Resettaster. Außerdem befindet sich noch der Encoder zur Zeiteinstellung ((6) in Abbildung 8) vorn.



Abbildung 8: Sanduhr komplett in der Frontansicht




Abbildung 9: Schaltung der externen Bauteile der Sanduhr




Tabelle 1: Stückliste der Sanduhr



Die SW-Architektur



Abbildung 10: Genutzte Controllerressourcen



Die SW wurde komplett in C geschrieben. Als Entwicklungsumgebung kam die HEW von Renesas zum Einsatz, die auch in Elektor 12.2005 vorgestellt und per CD verteilt wurde. Getrennt nach Funktionsblöcken wurde die SW über Quelldateien für ADC's, externe Interrupts, HW-Timer und Displaytreiber verteilt. Aufgrund der Komplexität der Displayansteuerung über die einzelnen Kommandos der seriellen SPI-Schnittstelle wurde der Treiber in eine hardwarenahe (max7221.c) und eine hardwarefernere Schicht (led_disp_drv.c) in 2 Quellkodedateien getrennt. Für eine leichtere Lesbarkeit des Codes wurden alle Definitionen im Quellcode symbolisch angelegt.


analogue_inputs.c

Lesen der Analogeingänge (Beschleunigungssensor)

external_interrupts.c

Interruptserviceroutine für die Encoderbetätigung EXTINT2

globals.c

Global benutzte Funktionen wie Zeitdifferenzberechnung, absoluter Betrag, Controllerinit

led_disp_drv.c

Der Treiber der die einzelnen LED-Matrix-Bilder generiert und die Konstantendefinitionen enthält

main_su.c

Das Mainfile der Sanduhr

max7221.c

Der hardwarenahe SPI-Treiber für 4 MAX7221

sw_vers.c

Ein automatisch generiertes File mit dem aktuellen Builddatum, was zur Versionsanzeige dient

timer_irq.c

Die TimerX-Interrupt-Routine, hier wird der Encoder abgefragt, die 1s-LED getoggelt, die LED-Matrix aktualisiert, die ADC-Konversion gestartet, die UART1-Ausgabe getriggert

uart1_functions.c

Debuginterface über UART1 zum Ausgeben interner Variablen

globals.h

Globale Defines

led_disp_drv.h

Funktionsprototypen

max7221.h

Defines für den hardwarenahen Treiber z.B. Kommandos

sfr_r813.h

Special Function Register Definition des R8/C13, Bestandteil der HEW

sect30.inc

Linker-File, Grundgerüst aus HEW, Interruptvektortabelle ergänzt um ISR-Calls

sfr_r813.inc

Special Function Register Definition des R8/C13, Bestandteil der HEW


Das Auslesen des Encoders erfolgt in der 1ms-Timerroutine und wurde analog [5] programmiert. Der Taster des Encoders löst an EXTINT2 einen Interrupt aus. Die Interruptserviceroutine befindet sich in external_interrupts.c, dort wird der Tastendruck entprellt und ein Flag zur Tasterbetätigung gesetzt.


In analogue_inputs.c befindet sich das Auslesen der ADC's und die Initialisierungsroutine für die ADC's. Da die Leseroutine im Timerinterrupt alle 100 ms aufgerufen wird, war es nötig, geschwindigkeitsoptimiert und ohne Polling zu programmieren. Hierzu wird in jeweils 2 Schritten zuerst die AD-Wandlung gestartet und erst 100ms später überprüft, ob das Wandlungsergebnis bereits vorliegt. Da sich herausstellte, dass für die Positionserfassung von Normalposition, Kopfüberposition und den Positionen dazwischen die X-Achse des Beschleunigungssensors völlig ausreicht, wurde nur noch der AD-Kanal der X-Achse eingelesen.


In max7221.c befinden sich die Low-Level-Ansteuerroutinen für den MAX7221. Zum einen gibt es eine Funktion um ein SPI-Telegramm bestehend aus 16bit an einen MAX7221 zu senden und zum anderen werden 4 dieser Funktionen hintereinander aufgerufen, um alle vier hintereinandergeschalteten MAX7221 ansteuern zu können. Außerdem befindet sich hier die Initialisierungsroutine, um UART0 für den SPI-Betrieb zu konfigurieren.


In uart1_functions.c befindet sich die Initialisierungsroutine für UART1, um ihn auf 9600 Baud, 1 Start-, 1 Stopbit und keine Parität zu konfigurieren. Außerdem befindet sich hier die Funktion, um den gelesenen AD-Wert in X-Richtung und die ermittelte Position seriell auszugeben. Diese Funktion wird von der Timer-ISR alle 1 s aufgerufen. Die ganze Funktion der seriellen Schnittstelle wird über das globale Compilerdefine UART1_DEBUGGING ein- und ausgeschaltet. Sie dient nur der Werteevaluierung der Beschleunigungssensordaten und dem allgemeinen SW-Debugging während der Entwicklung und wurde in der finalen SW-Version deaktiviert.


Die anzuzeigenden LED-Bilder sind als Konstantenarrays in der Datei led_disp_drv.c definiert. Wie in den Anforderungen vorgegeben soll der Zeitablauf durch 60 unterschiedliche Bilder der rinnenden „Zeitpartikel“ dargestellt werden, wobei Bild 0 60 leuchtenden LED's in der oberen Hälfte der LED-Matrix und Bild 60 60 leuchtenden LED's in der unteren Hälfte der LED-Matrix entspricht. Die Definition was obere und was untere Hälfte bedeutet wird anhand der Normalposition der Sanduhr (aufrecht) definiert. Für die Kopfüberposition vertauscht sich die Definition von oben und unten und die Definition von Start und Ende. Anfangs wurde vom Autor die Idee verfolgt für Normal- und Kopfüberposition nur einen Satz von 60 Bildern zu verwenden und lediglich die Anzeigereihenfolge der Bilder umzukehren. Das funktioniert für Start und Ende ganz hervorragend, aber zwischendurch gibt es Bilder, wo beim Drehen der Sanduhr „Zeitpartikel“ am oberen Behälterrand kleben und nicht wie richtiger Sand auf den Behälterboden fallen. Exemplarisch kann man das in den folgenden Abbildungen am Beispiel des Bildes 14 sehen, wo in der mittleren Abbildung nach der 180°-Drehung der Sanduhr, die „Zeitpartikel“ am oberen Behälterrand kleben bleiben (siehe die folgenden drei Abbildungen).

Abbildung 11: Bild14, Normalposition Abbildung 12: Bild 14, Normalposition, Sanduhr gedreht Abbildung 13: Bild 14, Kopfüberposition, Sanduhr gedreht

Eine intensivere Beschäftigung mit dem Problem führte zu der Erkenntnis, dass man eigentlich vielfache Bilderdefinition brauchen würde, weil sich das Aussehen der noch abzulaufenden Bilder komplett verändert, abhängig von dem aktuellen Bild von dem aus man die Sanduhr dreht. Da dieses Konzept nicht applizierbar ist, wurde nur ein kompletter Satz für die Kopfüberposition programmiert, der nun zumindest das Problem löst, dass „Zeitpartikel“ am oberen Behälterrand kleben. Die Bilder für die Kopfüberposition sind aufeinanderfolgend aufgebaut und sie folgen den gleichen Regeln wie die der Normalposition, sie sind aber optisch leicht unterschiedlich zu den äquivalenten Bildern der Normalposition, um das Herunterfallen beim Drehen besser darzustellen.

Zusätzlich gibt es noch das Mainfile, was die Initialisierungsfunktionen aufruft und anschließend in die endlos abgearbeitete Main Loop springt, die die Haupt-Statemachine realisiert und die angezeigten Inhalte steuert. Die durchlaufenen States, samt Übergangsbedingungen sind in der folgenden Abbildung dargestellt. Die Stati und die tx benannten Übergangsbedingungen sind so auch im Quellkode zu finden.


Abbildung 14: States Main State Machine




Über folgenden Link kann die aktuellste Firmware (Version : 0129) der Sanduhr inklusive der Quellkodes als HEW-Umgebung heruntergeladen werden (Link).

Der Entwurf der Anzeigebilder

Wie oben bereits beschrieben mussten jeweils 2 komplette Bildersätze aus 60 Einzelbildern für die ablaufenden „Zeitpartikel“ in Normal- und Kopfüberposition definiert werden. Außerdem mussten noch 2 Zeichensätze für die Anzeige der Ziffern in Normal- und Kopfüberposition erstellt werden. Dies war nur möglich über den Einsatz eines Entwurfswerkzeuges. Verwendet wurde ein OpenOffice-Tabellendokument. Herzu wurden alle 140 LED's der LED-Matrizen als Punkte über den Font Wingdings dargestellt. Über eine 0/1-Information für jede dieser „LED's“ konnte dann über bedingte Formatierung die Farbe des Fonts zwischen hellgrau (LED aus) und rot (LED ein) automatisch umgeschaltet werden. Die zwischenliegenden Spalten B,D,F,H;J,L,N,P und R mit den 0/1-Steuerdaten wurden ausgeblendet, um das Erscheinungsbild der Matrix zu erhalten. Die Steuerung der LED-Matrix erfolgt über die Dezimalkodes zwischen 0 und 127 in den Zeilen 4 und 23. Bedingt durch den Verdrahtungsfehler im PCB-Layout (siehe Kasten „Anmerkung Layoutfehler“) konnte für die reale Ansteuerung der LED-Matrizen aber nicht dieser Kode verwendet werden, sondern es war nötig einen Bitshift ab Bit3 zu beachten und außerdem entspricht das niedrigwertigste Bit0 Reihe 4 der LED-Matrix. Diese Korrektur wird in den Zeilen 3 und 24 berechnet und dargestellt. Um zu überprüfen, ob die Gesamtzahl der eingeschalteten LED's immer 60 beträgt wurde diese getrennt für die obere und die untere Matrixhälfte berechnet und in den Zellen C2 und Q2 angezeigt. Auf diese Art und Weise wurden zum einen 60 Bilder für die Normalposition, 60 Bilder für die Kopfüberposition, 10 Ziffern für die Normalposition und 10 Ziffern für die Kopfüberposition entwickelt. Zur visuellen Beurteilung der ablaufenden „Zeitpartikel“ wurden Screenshots aus dem OpenOffice-Tabellendokument als Grafiken in eine OpenOffice-Präsentation Seite für Seite eingefügt und der Folienübergang in der Präsentation mit 1 s automatisiert konfiguriert. Hierdurch konnte man sich bereits im Vorfeld ein sehr gutes Bild vom entworfenen Ablauf der „Zeitpartikel“ machen, ohne dass man sie in den Sanduhrcontroller flashen musste. Nachdem das komplette Design stand wurden die Werte aus den Zeilen 3 und 24 in mehrere Arrays programmiert. Im folgenden Bild ein Screenshot des Entwurfswerkzeuges in OpenOffice Tabellenkalkulation.


Abbildung 15: Entwurfswerkzeug



Die Bedienung

Wenn man die Sanduhr einschaltet, erscheint zuerst für 3 s die SW-Version. Danach wechselt die Anzeige in den Zeiteinstellungsmodus. Steht die Sanduhr während eingeschaltet wird kopfüber, so wird die Version und nach 3 s auch die Uhrablaufdauer kopfstehend angezeigt. Im Zeiteinstellungsmodus kann man durch Rechtsdrehen des Encoders die Zeitspanne im Einerinkrement bis 99 vergrößern. Bei Linksdrehung wird die Zeit jeweils um 1 kleiner. Bei Rechtsdrehung über 99 springt der Wert auf 0, bei Linksdrehung unter 0 springt der Wert auf 99. Ist die gewünschte Zeitdauer eingestellt startet man den Ablauf der Sanduhr durch Drücken des Encoders. Die Sanduhr wechselt in die Anzeige der rinnenden Zeitpartikel. Dreht man die Sanduhr während dieser Zeit um 90° nach links oder rechts wird ein waagerechter Balken angezeigt und der Ablauf der Zeit stoppt. Dreht man die Uhr um weitere 90° dann ändert sich die Ablaufrichtung der Zeitpartikel (Normalposition ==> Kopfüberposition) und auch die noch zu verrinnende Zeit läuft rückwärts. Wenn also die eingestellte Zeit 99 min beträgt und man dreht die Sanduhr nach 1 min auf den Kopf, dann läuft sie noch 1 min bevor sie den Ablauf signalisiert. Beim Ablauf der Uhr befinden sich alle Zeitpartikel in der jeweils unteren Hälfte der LED-Matrix und der Buzzer erzeugt einen intermittierenden 2.3 kHz-Ton. Dieser Modus wird beendet, indem man den Encoder einmal drückt. Die Uhr wechselt danach wieder in den Modus zur Zeiteinstellung. In den folgenden Abbildungen finden sich alle Anzeigemöglichkeiten in den verschiedenen Betriebsmodi.


Versionsanzeige, aufrecht



Versionsanzeige, aufrecht



Zeiteinstellung, aufrecht



Zeiteinstellung, kopfüber



Laufende, rinnende Zeit, aufrecht



Laufende, rinnende Zeit, kopfüber



Uhr abgelaufen, aufrecht



Uhr waagerecht






Quellen

1: Fa. Kingbright : Datenblatt TC20-11RT

2: Fa. Maxim : Datenblatt MAX7221

3: Fa. Renesas : Datenblatt R8C13

4: Fa. AIMEC : Datenblatt AMSR 7805

5: P. Danegger : Drehgeber auslesen in C