AVR Embedded Tutorial - Random/de: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: AVR Embedded Tutorial - Random/de
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Zufallsgenerator | |
| 2 | + | ||
| 3 | + | ## Vorwort | |
| 4 | + | ||
| 5 | + | Ein Zufallsgenerator ist auf einem AVR gar nicht so einfach. Ein **Random(...)** aus der Unit **System** geht leider **nicht**. Dieses Tutorial zeigt, wie man wenigstens einen Würfel auf einem AVR programmieren kann. | |
| 6 | + | ||
| 7 | + | Der Bereich der Zufallszahl muss von Anfang an bekannt sein, bei einem klassischen Würfel ist dies 6. | |
| 8 | + | ||
| 9 | + | Für die Kommunikation über UART siehe hier: | |
| 10 | + | ||
| 11 | + | - [[AVR Embedded Tutorial - UART/de|UART]] | |
| 12 | + | ||
| 13 | + | Für einfache Zufallszahlen eignen sich folgende beschriebenen Methoden. Voraussetzung ist, das die Abfrage der Zufallszahlen in unregelmässigen Abständen kommt. Das ist zB. auch bei einem Tastendruck der über GPIO abgefragt wird der Fall. | |
| 14 | + | ||
| 15 | + | Diese Voraussetzung kann man gut beim ersten Beispiel erkennen, wen man im Terminalprogramm eine Taste gedrückt hält, da kann man eine Regelmässigkeit gut erkennen. | |
| 16 | + | ||
| 17 | + | Wen man einen **float** als Zufallszahl will, dann wird es schon sehr kompliziert. Dafür habe ich (noch) keine Lösung gefunden. | |
| 18 | + | ||
| 19 | + | ## Ein einfacher Würfel | |
| 20 | + | ||
| 21 | + | ``` pascal | |
| 22 | + | var | |
| 23 | + | Random: byte; // Gibt die Zufallszahl zurück. | |
| 24 | + | ||
| 25 | + | procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt; | |
| 26 | + | const | |
| 27 | + | RandomCount = 6; // Anzahl Würfelaugen | |
| 28 | + | begin | |
| 29 | + | Inc(Random); | |
| 30 | + | if Random >= RandomCount then begin | |
| 31 | + | Random := 0; | |
| 32 | + | end; | |
| 33 | + | end; | |
| 34 | + | ||
| 35 | + | var | |
| 36 | + | s: ShortString; | |
| 37 | + | ||
| 38 | + | begin | |
| 39 | + | // Timer 0 | |
| 40 | + | TCCR0A := %00; // Normaler Timer | |
| 41 | + | TCCR0B := %001; // Clock = CPU | |
| 42 | + | TIMSK0 := (1 shl TOIE0); // Enable Timer0 Interrupt. | |
| 43 | + | ||
| 44 | + | // UART | |
| 45 | + | UARTInit; // UART inizialisieren. | |
| 46 | + | ||
| 47 | + | // Interrupts einschalten. | |
| 48 | + | asm sei end; | |
| 49 | + | ||
| 50 | + | // Hauptschleife | |
| 51 | + | repeat | |
| 52 | + | UARTReadChar; // Simuliert einen Tastendruck. | |
| 53 | + | Str(Random + 1: 4, s); // Die Zufallszahl abholen. | |
| 54 | + | UARTSendString(s); // Zufallszahl ausgeben. | |
| 55 | + | until 1 = 2; | |
| 56 | + | ||
| 57 | + | end. | |
| 58 | + | ``` | |
| 59 | + | ||
| 60 | + | ## Mehrere Würfel | |
| 61 | + | ||
| 62 | + | ### Schlechte Lösung | |
| 63 | + | ||
| 64 | + | Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen: | |
| 65 | + | ||
| 66 | + | ``` pascal | |
| 67 | + | Str(Random + 1: 4, s); // Die Zufallszahl abholen. | |
| 68 | + | UARTSendString(s); // Zufallszahl ausgeben. | |
| 69 | + | Str(Random + 1: 4, s); // Ist abhängig vom ersten Wurf. | |
| 70 | + | ... | |
| 71 | + | ``` | |
| 72 | + | ||
| 73 | + | Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist dies **unbrauchbar** ! | |
| 74 | + | ||
| 75 | + | ### Ideale Lösung | |
| 76 | + | ||
| 77 | + | Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar. | |
| 78 | + | ||
| 79 | + | Einziges Manko, es ist etwas komplizierter, dafür ist jede Zufallszahl unabhängig von den anderen. Bei diesem Beispiel sind es 15 Würfel. Der Timer musste noch etwas langsamer gestellt werden, als bei dem Beispiel mit nur einem Würfel. | |
| 80 | + | ||
| 81 | + | Der Trick ist, es werden nicht alle Würfel bei jedem Timeraufruf inkrementiert. Der zweite Würfel nur bei jedem zweiten Aufruf, der Dritte nur beim dritten Aufruf, etc. | |
| 82 | + | ||
| 83 | + | ``` pascal | |
| 84 | + | // Globale Variablen. | |
| 85 | + | const | |
| 86 | + | anzWuerfel = 15; | |
| 87 | + | var | |
| 88 | + | Random: array[0..anzWuerfel - 1] of byte; | |
| 89 | + | ||
| 90 | + | procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt; | |
| 91 | + | ||
| 92 | + | // Lokale Variablen. | |
| 93 | + | const | |
| 94 | + | RandomCount = 6; // Anzahl Würfelaugen | |
| 95 | + | var | |
| 96 | + | i: integer; | |
| 97 | + | rnd: array [0..anzWuerfel - 1] of byte; | |
| 98 | + | ||
| 99 | + | begin | |
| 100 | + | for i := 0 to anzWuerfel - 1 do begin | |
| 101 | + | Inc(rnd[i]); | |
| 102 | + | if rnd[i] > i then begin | |
| 103 | + | rnd[i] := 0; | |
| 104 | + | Inc(Random[i]); | |
| 105 | + | if Random[i] >= RandomCount then begin | |
| 106 | + | Random[i] := 0; | |
| 107 | + | end; | |
| 108 | + | end; | |
| 109 | + | end; | |
| 110 | + | end; | |
| 111 | + | ||
| 112 | + | var | |
| 113 | + | s: ShortString; | |
| 114 | + | i: integer; | |
| 115 | + | ||
| 116 | + | begin | |
| 117 | + | // Timer 0 | |
| 118 | + | TCCR0A := %00; // Normaler Timer | |
| 119 | + | TCCR0B := %011; // Clock = CPU / 16. | |
| 120 | + | TIMSK0 := (1 shl TOIE0); // Enable Timer0 Interrupt. | |
| 121 | + | ||
| 122 | + | // UART | |
| 123 | + | UARTInit; | |
| 124 | + | ||
| 125 | + | // Interrupts einschalten. | |
| 126 | + | asm SEI end; | |
| 127 | + | ||
| 128 | + | // Hauptschleife | |
| 129 | + | repeat | |
| 130 | + | UARTReadChar; | |
| 131 | + | for i := 0 to anzWuerfel - 1 do begin | |
| 132 | + | Str(Random[i] + 1: 4, s); // Jeder Würfel hat eine eigene Zufallszahl. | |
| 133 | + | UARTSendString(s); | |
| 134 | + | end; | |
| 135 | + | UARTSendString(#13#10); | |
| 136 | + | until 1 = 2; | |
| 137 | + | end. | |
| 138 | + | ``` | |
| 139 | + | ||
| 140 | + | ## Siehe auch | |
| 141 | + | ||
| 142 | + | - Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]] | |
| 143 | + | ||
| 144 | + | Autor: Mathias | |
| 145 | + | ||
| 146 | + | --- | |
| 147 | + | *From the Free Pascal wiki, page "AVR Embedded Tutorial - Random/de", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 148 | + | Category: AVR/de | |
| 149 | + | Category: Arduino/de | |
| 150 | + | Category: Deutsch | |
| 151 | + | Category: Embedded/de |
