Sign in Join
Wiki copytemporary

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

OldNewLine
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

Back to history