Pfad: Home => AVR-DE => Anwendungen => Zufall tn13 > Zufallszahlen anzeigen   This page in english: Flag EN Logo
Zufallsfarben 250*250 AVR-Anwendungen

Zufallszahlen mit ATtiny13
Anwendung und Software für Zufallszahlen in Assembler

Zufallszahlen mit ATtiny13

Berechnung Rauschgenerator Analyse

2 Zufallszahlen anzeigen

Natürlich ist das reine Simulieren nicht so arg prickelnd, es muss auch etwas Farbe in die Würfelei. Hier werden auf einer RGB-LED Zahlen zwischen 0 und 255*255*255 = 16.711.680 verschiedene Farben angezeigt. Das Ein- und Ausschalten der drei LEDs erfolgt mit drei Pulsweiten-Generatoren, die in einem ATtiny13(A) werkeln.

2.1 Hardware

Zufalls-Farbanzeige mit ATtiny13 Die RGB-LEDs sind an den Portausgängen PB0 (rot), PB1 (grün) und PB2 (blau) angeschlossen. Der Strom durch die LEDs wird von drei Widerständen kontrolliert, deren Größe an die unterschiedlichen Durchlassspannungen der LEDs angepasst sind. Sie sind für einen Strom von ca. 20 mA pro LED ausgelegt.

Die eingezeichneten Widerstandswerte erwiesen sich bei einer zweiten Liefercharge RGB-LEDs als zu klein. Sie mussten auf 100 Ω, 47 Ω und 56 Ω vergrössert werden, um bei ca. 20 mA zu landen. Am Besten vorher ausprobieren: Die Spannungen an den Portausgängen dabei entweder
  1. mit zwei Schottkydioden nachbilden, oder
  2. die Spannung auf 4,6 V einstellen, oder
  3. die Spannung aus drei AA- oder AAA-Batterien beziehen.
Wer keine RGB-LEDs mit gemeinsamer Anode, sondern welche mit gemeinsamer Kathode verwenden will, kann das ganz leicht ändern: Zur Einstellung der Geschwindigkeit, mit der die nächste Farbe angezeigt wird, ist am Eingang ADC3 ein Poti von 10 kΩ angeschlossen. Der Vorwiderstand von 33 kΩ setzt die Einstellspannung von 5 V auf 1,1 V herab, da der AD-Wandler per Software auf die intern erzeugte Referenzspannung eingestellt ist.

An den Eingang ADC2 kann ein Rauschgenerator angeschlossen werden. Dieser sollte maximal 1 Vpp Rauschspannung liefern. Der Eingang sollte, wenn kein Rauschgenerator angeschlossen ist, auf GND (Null Volt) gezogen werden.

Die Schaltung hat noch einen ISP6-Stecker, mit dem der ATtiny13 programmiert werden kann und aus dem auch die 5V-Versorgung bezogen werden kann.

Zufallsanzeige und Rauschgenerator auf dem Steckbrett So sieht die Schaltung mit der RGB-LED, dem ATtiny13 und dem Rauschgenerator (siehe Rauschgenerator) auf dem Steckbrett aus.

Zwei kurze Videos, mit schneller Einstellung hier und mit langsamer Einstellung hier. Falls der Browser die Videos nicht direkt abspielt, die Videos herunterladen und mit dem Lieblings-Videoabspieler des Betriebssystems öffnen.

2.2 Programm des ATtiny13

Dies hier beschreibt, wie das Programm funktioniert. Wer es einfach nur downloaden möchte, findet es in Assemblerformat hier, im Browser angezeigt gibt es das hier.

2.2.1 Einstellungen im Programm

Um möglichst viele Anwendungsfälle abzudecken, ist das Programm sehr vielfältig einstellbar. Dazu müssen im Kopf der Assemblerdatei ein paar Zeilen geändert werden. Mit den drei Schaltern swCalcOnly, swNoiseOnly und swMixed lässt sich die Zufallsquelle auswählen, nur eine der drei Möglichkeiten darf mit 1 eingeschaltet sein. swMixed erzeugt 15 Zufallszahlen per Rechnung und setzt dann die beiden Seeds aus dem externen Rauschgenerator.

In der Sektion Adjustable Const weiter unten im Quellcode kann man noch ein paar Hardware-Einstellungen vornehmen. So bestimmt cLedLong die Verzögerungszeit bis zur nächsten Zufallszahl. PwmFreq stellt die Frequenz des PWM-Generators für die LED-Anzeige ein. Die Untergrenze sind 19 Hz, die Obergrenze 146 Hz.

2.2.2 Pulsweitensteuerung

PWM-Ablauf Vergleichen Um die Pulsweitensignale für die LEDs zu erzeugen, arbeitet der Timer TC0 im CTC-Modus: nach 64 Takten des ATtiny13 (bei der Default-Taktfrequenz von 1,2 MHz) setzt der Zähler zurück auf Null und unterbricht mit dem Compare-A-Interrupt die Programmausführung. Das ist alle 64 / 1,2 = 53,3 µs der Fall. Mit jedem dieser Unterbrechungen wird geprüft, ob der Rot-Wert in rRed, der Grün-Wert in rGreen und der Blau-Wert in rBlue erreicht ist: die entsprechenden Bits werden dann ausgeschaltet, die LED leuchtet nur so viele Zyklenschritte lang, wie es der Vergleichswert angibt. Nach 256 Schritten = 256 * 53,3 µs = 13,65 ms, beginnt der PWM-Zyklus wieder von vorne, was eine Wiederholfrequenz von 73,24 Hz ergibt.

Damit das Schalten der LEDs immer zum gleichen Zeitpunkt erfolgt, egal wie lange Vergleiche und Neustart benötigen, wird der Zustand der LEDs in einem Arbeitsregister rWork immer zu Beginn der CTC-ISR ausgegeben. In diesem Register erfolgt auch das Löschen der Farbbits, wenn Gleichheit mit rPwm erreicht ist.

In der Interrupt-Service-Routine des Interrupts zählt ein Register rPwm nach oben, von 0 bis 255. Ist rPwm nicht Null, erfolgt der Vergleich von rPwm mit den zufallsgenerierten Vergleichswerten von rot in rRed, von grün in rGreen und vo blau in rlue. Ist der Vergleichswert erreicht, wird das entsprechende Bit im Register rWork rot, grün bzw. blau ausgeschaltet.

PWM-Ablauf Neustart Ist beim Erhöhen von rPwm dieser auf Null übergelaufen, beginnt ein neuer PWM-Zyklus. Ein 16-Bit-Zähler in rCntH:rCntL = R25:R24 wird abwärts gezählt. Der Startwert dieses Zählers gibt an, mit welcher Geschwindigkeit eine neue Farbe eingestellt wird. Er wird durch Multiplikation des Potentiometerwertes mit einer Konstanten ermittelt. Solange dieser Zähler nicht Null ist, wird ein weiterer PWM-Zyklus gestartet, indem das Arbeitsregister rWork mit dem Startregister rStart überschrieben wird.

Ist der 16-Bit-Zähler Null geworden, entscheidet die Voreinstellung, ob neue Zufallszahlen nur aus der berechneten Reihe verwendet werden (Option swCalcOnly) oder ob ausschließlich die vom externen Rauschgenerator erzeugten Zahlen genommen werden (Option swNoiseOnly) oder ob beides gemischt wird. Beide Programmteile laufen auf die gleiche Routine zu: die Bildung von rStart. Im Register rStart werden die drei Farbbits auf Eins gesetzt, wenn der Farbwert größer als Null ist. Ist das nicht der Fall, wird die LED zu Beginn des PWM-Zyklusses gar nicht erst eingeschaltet (da sie sonst niemals auch wieder ausgeschaltet werden würde, denn rPwm = 0 wird beim Farbvergleich gar nicht geprüft.

Nach Erstellung von rStart wird das Arbeitsregister rWork mit dem Inhalt von rStart überschrieben, was auch bei jedem Neustart des PWM-Zyklusses so passiert. Nach Wiederherstellen von SREG ist die ISR mit RETI zu Ende. Die eigentliche Ausgabe von rWork an die LED-Pins erfolgt zu Beginn des nachfolgenden CTC-Interrupts.

Da jede Einzelstufe des PWM-Zyklusses nach 64 / 1,2 MHz = 53,33 µs erfolgt und 256 dieser Stufen aufeinander folgen, dauert ein ganzer PWM-Zyklus 13,65 ms. Das entspricht einer Wiederholfrequenz von 73,24 Hz und ist schnell genug für das menschliche Auge.

Es ist daher auch sicherzustellen, dass keine der ISR-Verzweigungen länger als 64 Takte dauert. Wie an den Taktzyklen im Fließdiagramm zu erkennen, ist dies auch nicht der Fall.

2.2.3 Zufallszahlen

Sind alle Ausgabezyklen durchlaufen und rCntH:rCntL wird Null, dann werden nach dem in Kapitel 1 beschriebenen Algorithmus (oder auch nach dem in Kapitel 3 beschriebenen Rauschgenerator) drei neue Zufallszahlen generiert und letztlich in die Register rRed, rGreen und rBlue geschrieben. Da die Entscheidung, ob berechnete oder mit dem Rauschgenerator erzeugte Zufallszahlen angezeigt werden, schon beim Assemblieren erfolgt, benötigt diese Entscheidung keinen Prozessortakt.

2.2.4 ADC-Wandlung und -auswertung

Der AD-Wandler muss zwei Signale messen:
  1. die Einstellung des Geschwindigkeitspotenziometers, und
  2. eintreffende Signale am Rauschgenerator-Eingang.
Er wird dazu beim Init der Hardware einmalig gestartet. Dazu wird die MUX auf ADC3 eingestellt und die interne Referenzspannung von 1,1 V eingeschaltet. Die Einstellung auf 1,1 V stellt sicher, dass auch schwache Rauschsignale zu einer Aussteuerung des ADC führen. Verwendet man einen Sinusgenerator, wie er in Kapitel 4 beschrieben ist, muss man entweder Die weitere AD-Wandlung erfolgt interruptgesteuert. Immer, wenn ein Messwert vorliegt, wird dazu die Flagge bAdc gesetzt. Die dazugehörende ISR ist daher sehr kurz und stört die PWM-Ausgabe nicht. Die Auswertung der Flagge erfolgt nämlich außerhalb der ISR.

Welcher der beiden AD-Werte vorliegt, geht aus dem Zustand des MUX-Portregisters hervor, das zu Beginn gelesen wird.

2.2.5 Die Geschwindigkeitseinstellung

Wurde das Potenziometer gemessen, dann wird der 10-Bit-ADC-Wert invertiert (höhere Spannungen = schnellere Ausgabe = kürzere PWM-Zyklen-Zählung). Die Invertierung erfolgt, indem der AD-Wandler-Wert von 0x0400 abgezogen wird.

Um unabhängig von dem eingestellten Timing (clock, CTC-Teiler, etc.) zu werden, wird der invertierte Wert dann mit einer Konstanten multipliziert. Die Konstante cMultiplier gibt an, mit welchem Wert der invertierte AD-Wert zu multiplizieren ist, um bei einem invertierten AD-Wandler-Wert von 1023 (linker Anschlag des Potis, ADC = 0) die Anzahl an PWM-Wiederhol-Zyklen so einzustellen, dass die in der Einstellkonstanten cLedLong vorgegebene Zeit erreicht wird.

.equ cLedLong = 100 ; Longest delay in tens of ms

Die Multiplikationskonstante cMultiplier
 
.equ cMultiplier = (((cLedLong*clock/(cCtcCmpA+1))+512)/1024)/100

ergibt sich bei einer Sekunde zu 18 (1023 * 18 = 18.414, bei 10 Sekunden zu 183 und bei 100 Sekunden zu 1.831. Diese Konstante enthält den Faktor 256, so dass nach dem Multiplizieren das unterste Byte gestrichen werden muss.

Die Multiplikation des invertierten AD-Wertes (10 Bits) mit diesem Wert (maximal 16 Bits) erfordert ziemlich viele Register. Der invertierte AD-Wert wird in die vier Register R3:R2:R1:R0 geschrieben (die oberen beiden Register sind zu Beginn der Multiplikation Null). In das Registerpaar XH:XL kommt zu Beginn der 16-Bit-Multiplikatorwert.

Die Register ZH:ZL:YH:YL nehmen das 32-Bit-Ergebnis auf. Die obersten acht Bit in ZH müssen dabei Null sein. Sind sie das nicht, wird das Ergebnis auf 0xFFFF eingestellt. Die untersten 8 Bits in YL werden zum Aufrunden des Ergebnisses in ZL:YH verwendet. Damit das Ergebnis nicht Null werden kann, wird noch eine Eins addiert.

Die Multiplikation von 1024 mit 18 liefert 18.432, geteilt durch 256 ergibt 72 und 72 PWM-Zyklen zu je 13,65 ms dauert 0,983 Sekunden. Maximal können auf diese Weise 65.535 * 0,01365 = 894 Sekunden = 14,9 Minuten eingestellt werden.

2.2.6 Zufallszahlen vom Rauschgenerator

War die MUX auf der ADC2-Position und ist das Ergebnis weder Null noch Vollausschlag, dann wird das unterste Bit des AD-Wandlers in die Carry-Flagge geschoben und von rechts her in die Register rRnd3:rRnd2:rRnd1 eingerollt. Da der AD-Wandler mit einem Vorteiler von 128 arbeitet, für die Wandlung 14 Takte benötigt und zwei Kanäle im Wechsel gemessen werden, liegt alle 128 * 14 * 2 / 1.200.000 = 3 ms ein neues Bit vor. Alle 24 Bits eines Sets benötigen 72 ms. Das ist auch bei schnellem Wechsel der Zahlen ausreichend schnell, zumal der Inhalt bei unvollständigem Linksrotieren aller 24 Bits ja ohnehin schon genug Zufall ist.

Ist die Option swMixed gewählt, wird noch zusätzlich geprüft, ob der Zähler rRndC auf Null ist. Dieser wird bei jeder Neuberechnung einer Zufallszahl in der PWM-Interrupt-Routine abwärts gezählt. Hat er Null erreicht, werden die beiden Zufallszahlen aus dem Rauschgenerator als neue Basiszahlen genommen. Der Zähler wird dann auf 15 (Einstellung mit cRndCount) gesetzt. Die 15 wurde deshalb gewählt, weil die Zykluslänge von beliebigen Startkombinationen immer länger als 25 ist (siehe Kapitel 1).

Bei Beendigung beider Zweige wird der AD-Wandler mit dem jeweils anderen Kanal neu gestartet.

Der Schlafanteil des Programms liegt bei bei allen hier dargestellten Default-Einstellungen bei ca. 65%, bedingt durch die häufigen PWM-Schritt-Unterbrechungen. Erhöhung der PWM-Frequenz senkt den Schlafanteil stark ab, was bei Batteriebetrieb eine wichtige Rolle spielt. Allerdings ist der Stromanteil der RGB-LED ohnehin viel h&aouml;her (max. 60 mA), sodass der Prozessorstrom nicht so arg viel beiträgt (max. 2 mA).

Seitenanfang Hauptseite Berechnung Rauschgenerator Analyse


Lob, Tadel, Fehlermeldungen, Genöle und Geschimpfe oder Spam bitte über das Kommentarformular an mich.

©2020 by http://www.avr-asm-tutorial.net