Pfad:
Home =>
AVR Überblick =>
Anwendungen => Würfel ATmega16
This page in English:
Taumelnder Würfel mit einem ATmega16
Taumelnder Doppelwürfel mit einem ATmega16 und zwei Siebensegmentanzeigen.
Würfelt echte Zufallszahlen auf Tastendruck. Zwei Jumper erlauben es, a)
nur einen einzigen Würfel sichtbar zu machen und b) das Taumeln abzustellen
(wenn es dich nervös macht. Die Anzeige geht nach 16 Sekunden in das
stromsparende Aus, lässt sich aber durch erneutes Würfeln wieder
aufwecken. Und für den mathematischen Forscher werden alle Tastendrücke
und die dabei gewürfelten Zahlen gezählt (bis 65535), können
aus dem EEPROM ausgelesen und rechnerisch analysiert werden. Damit kommt der
Forscher dem Zufall auf die Spur. Dadurch, dass die Zähler im EEPROM aufbewahrt
werden, überstehen sie das Abschalten des Würfels und können
dauerhaft zählen, bis sie erst durch einen Reset durch Programmieren des
EEPROM-Segments wieder auf Null gesetzt werden. Dafür gibt es einen ISP-Anschluss
auf der Platine für den Anschluss des Programmiergeräts.
Überblick
- Hardware
- Aufbau
- Betrieb
- Software
- Fuse-Einstellungen
Das hier ist die nötige Hardware. Der ATmega16 hat viele überschüssige
Portpins, die in der Schaltung nicht verwendet werden. Die Ports A und C treiben
die Siebensegmentanzeigen, einschließlich der Dezimalpunkte. Der INT0-Eingang
ist mit dem Taster verbunden, mit dem das Würfeln ausgelöst wird. Dieser
Eingang und die beiden Eingänge der Jumper an Port B wird intern über die
Software mit Pull-Up-Widerständen auf die Betriebsspannung gezogen. Die
Betriebsspannung kommt entweder über drei Batterien à 1,5 V =
4,5 V oder über vier Akkus à 1,2 V = 4,8 V zustande.
Es können AA oder AAA Batterien/Akkus verwendet werden. Auch ein externes
Netzteil mit 3 bis 5 V kann angeschlossen werden, es sollte bis zu 100 mA
Gleichstrom liefern.
Der Leuchtdiodenstrom ist mit ca. 7 mA batteriefreundlich ausgelegt. Falls
die Schaltung mit niedrigerer Spannung, z. B. mit 3 V, betrieben werden
soll oder wenn hellere Anzeigen gewünscht sind, können auch kleinere
Widerstände eingesetzt werden, z. B. solche mit 270 oder 220 Ω.
Höhere Ströme reduzieren allerdings die Batterielebensdauer. Bitte beachten,
dass die Dezimalpunkte bei gleicher Helligkeit niedrigere Ströme benötigen.
Das ISP6-Interface ist empfehlenswert. Nicht nur kann darüber die Software
auf den ATmega16 übertragen werden, auch der EEPROM-Inhalt mit den sieben
16-Bit-Zählern kann darüber ausgelesen werden.
Die Hardware kann auf einem Breadboard zusammengesteckt werden, auf einer
Lochrasterplatine zusammengelötet werden oder auf einer gedruckten
Platine gelötet werden.
Dies hier ist so ein einseitiges Layout für eine gedruckte Platine und der
zugehörige Bestückungsplan.
Damit sieht die ganze Schaltung so aus.
Zuerst wird die Betriebsspannung eingeschaltet. Während der ersten Phase
werden alle Segmente und alle Dezimalpunkte schnell ein- und ausgeschaltet.
Falls diese Lampentestphase abgeschaltet werden soll, sind die entsprechenden
Befehle aus dem Quellcode zu entfernen, entweder mit dem Studio-Editor oder mit
irgendeinem Editor der nackte ASCII-Texte erzeugt, neu zu assemblieren (entweder
mit dem Studio-Assembler oder mit
meinem gavrasm
oder mit irgendeinem anderen AVR-Assembler, der die ".if"-Direktive
beherrscht. Dann den erzeugten Hexcode in das Flash-Memory des ATtiny16 brennen
und die Fuses korrekt setzen (siehe hier).
Danach kann das Würfeln mit dem angeschlossenen Taster beginnen. Das Taumeln
des gewürfelten Wertes umfasst fünf Stufen, nach Vorgabe der Software
über gleiche Zeiträume verteilt. Wer will, kann kürzere Zeiten
oder von schnellen zu langsameren Zeiten übergehende Einstellungen wählen,
indem er die entsprechenden Konstanten im Kopf der Software umschreibt, erneut
assembliert und die geänderte Software in den Chip schreibt.
Das sind die zwei Jumper. Sie können jederzeit gesetzt oder entfernt werden, das
geänderte Verhalten wird sofort aktiv.
Wenn nur einer der beiden Würfel angezeigt werden soll, wird Jumper 1 auf der
linken Seite geschlossen. Wenn das Taumeln unterbunden werden soll, wird Jumper 2
rechts geschlossen.
Wenn der Taster für 16 Sekunden lang nicht betätigt wird, wird die Anzeige
dunkel und nur der Dezimalpunkt der zweiten Anzeige ist an. Jeder Tastendruck
unterbricht den Schlaf und ein neues Würfelergebnis wird sofort angezeigt.
Die kommentierte Assembler-Quelldati ist hier verfügbar.
Sie kann mit jedem einfachen Editor, wie z. B. Notepad unter Windows oder
KWrite unter Linux bearbeitet werden.
Als Zufallsgenerator wird der Timer TC0 eingesetzt. Er läuft mit einer Frequenz von
1 MHz von 0 bis 251 und setzt dann wieder zurück (CTC-Modus). 252 wurde als
Teiler gewählt, weil es durch Sechs teilbar ist und für eine Gleichverteilung
aller Würfelzahlen sorgt. Wenn die Taste betätigt wird, wird der
Zählerstand abgelesen und durch Sechs geteilt. Der verbleibende ganzzahlige Rest
(Modulo) ergibt die gewürfelte Zahl. Das Divisionsergebnis (0 bis 6) wird dazu
verwendet, um aus einer Tabelle einen Verschiebewert zu holen. Beim Taumeln wird dieser
Verschiebwert zur gewürfelten Zahl dazugezählt, um die nächste angezeigte
Zahl zu erhalten.
Der gesamte Ablauf erfolgt mittels Interrupts. Jeder Würfelzyklus beginnt mit
einem INT0-Interrupt von der Taste. Der Compare Match Port A des Timers TC1, der die
Taumelintervalle liefert, wird dann auf die erste Zahl gesetzt, alle diese Intervalle
sind als Konstanten definiert. Außerdem wird der Dezimalpunkt der linken Anzeige
angeschaltet. Er wird erst dann wieder abgeschaltet, wenn der Zyklus beendet ist. Solange
dieser Punkt an ist, werden keine weiteren INT0-Zyklen gestartet (das unterdrückt
Schalterprellen). Der Timer TC1 wird im normalen Zählmodus mit einem Vorteiler von
256 gestartet und der Überlauf- und Compare-Match-Interrupt eingeschaltet.
Der Compare Match A von TC1 zählt ein Register abwärts, das die Anzahl der
Taumelereignisse zählt. Ist Taumeln abgeschaltet, hat dieses Register zu Beginn
den Wert 1, ist es eingeschaltet, dann 5. Wenn das Taumeln eingeschaltet ist, wird
der Verschiebwert zum Würfelergebnis hinzugezählt und auf der Anzeige
ausgegeben. Wenn der Zähler Null erreicht hat, werden die Gesamtzahl und die
beiden Zähler aus dem EEPROM ausgelesen und um Eins erhöht. Dann wird
das LSB des ersten EEPROM-Wertes geschrieben. Die weitere Ausgabe ins EEPROM erfolgt
mit dem EEPRDY-Interrupt.
Dieser Interrupt schreibt das MSB der Gesamtzahl, dann das LSB und MSB der beiden
gewürfelten Zahlen in das EEPROM. Wenn alle Inhalte geschrieben sind ist der
Zyklus beendet und der Dezimalpunkt der ersten Anzeige wird abgeschaltet, was das
erneute Starten des INT0-Zyklus einschaltet.
Zuletzt, wenn kein Tastendruck einen neuen Zyklus startet, läuft der TC1
über (nach 65536 * 256 = 16.777.216 µs = 16,8 Sekunden). Dann
werden beide Anzeigen ausgeschaltet und der Dezimalpunkt der zweiten Anzeige
eingeschaltet.
Um zu ermitteln, ob die gewürfelten Zahlen gleich häufig auftreten, wurde
ein Programm in Pascal geschrieben (der Quellcode ist
hier, er kann mit Free Pascal kompiliert werden. Dazu wird der Inhalt des
EEPROMs in eine Datei namens "dice_m16_v1_read.hex" heruntergeladen und
im gleichen Verzeichnis gespeichert in dem sich die ausführbare Datei befindet.
Nach 500 Würfen ergibt sich nebenstehendes Ergebnis. Die Abweichungen vom
gleichverteilten Sollwert bewegen sich bei wenigen Prozent.
Nach 1000 Würfen ergibt sich folgendes Ergebnis.
Die folgenden Fuses des ATmega16 müssen geändert werden:
- Die JTAG Fuse muss gelöscht werden. Andernfalls bleiben bestimmte Segmente
der Anzeige 2 dunkel.
- Wenn neuer Programmcode in den Flashspeicher geladen werden soll, wird
normalerweise der EEPROM-Inhalt gelöscht. Mit der EESAVE-Flag kann das
Löschen des EEPROMs unterdrückt werden, der Inhalt bleibt auch beim
Programmieren erhalten. Durch Schreiben des EEP-Segments kann der Inhalt dennoch
gezielt gelöscht werden.
- Es muss sichergestellt werden, dass der interne RC-Oszillator mit 1 Mz
läuft.
©2017 by http://www.avr-asm-tutorial.net