Difference between revisions of "AVR Embedded Tutorial - Random/de"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed template loop; syntax highlighting; modded categories ro German; added language category)
 
(6 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{Translate}}
+
{{LanguageBar}}
  
 
=Zufallsgenerator=
 
=Zufallsgenerator=
  
 
==Vorwort==
 
==Vorwort==
 +
 
Ein Zufallsgenerator ist auf einem AVR gar nicht so einfach.
 
Ein Zufallsgenerator ist auf einem AVR gar nicht so einfach.
 
Ein '''Random(...)''' aus der Unit '''System''' geht leider '''nicht'''.
 
Ein '''Random(...)''' aus der Unit '''System''' geht leider '''nicht'''.
Line 11: Line 12:
  
 
Für die Kommunikation über UART siehe hier:
 
Für die Kommunikation über UART siehe hier:
 +
 
* [[AVR Embedded Tutorial - UART/de|UART]]
 
* [[AVR Embedded Tutorial - UART/de|UART]]
 +
 +
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.
 +
 +
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.
 +
 +
Wen man einen '''float''' als Zufallszahl will, dann wird es schon sehr kompliziert. Dafür habe ich (noch) keine Lösung gefunden.
  
 
==Ein einfacher Würfel==
 
==Ein einfacher Würfel==
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
var
 
var
Line 50: Line 59:
 
   until 1 = 2;
 
   until 1 = 2;
  
end.</syntaxhighlight>
+
end.
 +
</syntaxhighlight>
  
 
==Mehrere Würfel==
 
==Mehrere Würfel==
 +
 
===Schlechte Lösung===
 
===Schlechte Lösung===
 +
 
Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen:
 
Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen:
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
     Str(Random + 1: 4, s);    // Die Zufallszahl abholen.
 
     Str(Random + 1: 4, s);    // Die Zufallszahl abholen.
Line 61: Line 74:
 
     ...  
 
     ...  
 
</syntaxhighlight>
 
</syntaxhighlight>
Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist die unbrauchbar.
+
 
 +
Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist dies '''unbrauchbar''' !
  
 
===Ideale Lösung===
 
===Ideale Lösung===
 +
 
Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar.
 
Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar.
  
Line 71: Line 86:
  
 
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.
 
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.
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
// Globale Variablen.
 
// Globale Variablen.
Line 80: Line 96:
 
   procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
 
   procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
  
   // Lokale Variblen.
+
   // Lokale Variablen.
 
   const
 
   const
 
     RandomCount = 6; // Anzahl Würfelaugen
 
     RandomCount = 6; // Anzahl Würfelaugen
Line 129: Line 145:
  
 
== Siehe auch ==
 
== Siehe auch ==
* Übersichtseite [[AVR Embedded Tutorial/de]]
 
  
[[Category:Embedded]]
+
* Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
[[Category:AVR]]
+
 
[[Category:Arduino]]
+
Autor: [[User:Mathias|Mathias]]
 +
 
 +
[[Category:AVR/de]]
 +
[[Category:Arduino/de]]
 +
[[Category:Embedded/de]]
 +
{{AutoCategory}}

Latest revision as of 12:53, 24 January 2020

Deutsch (de) English (en)

Zufallsgenerator

Vorwort

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.

Der Bereich der Zufallszahl muss von Anfang an bekannt sein, bei einem klassischen Würfel ist dies 6.

Für die Kommunikation über UART siehe hier:

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.

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.

Wen man einen float als Zufallszahl will, dann wird es schon sehr kompliziert. Dafür habe ich (noch) keine Lösung gefunden.

Ein einfacher Würfel

var
  Random: byte; // Gibt die Zufallszahl zurück.

  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
  const
    RandomCount = 6; // Anzahl Würfelaugen
  begin
    Inc(Random);
    if Random >= RandomCount then begin
      Random := 0;
    end;
  end;

var
  s: ShortString;

begin
  // Timer 0
  TCCR0A := %00;               // Normaler Timer
  TCCR0B := %001;              // Clock = CPU
  TIMSK0 := (1 shl TOIE0);     // Enable Timer0 Interrupt.
  
  // UART
  UARTInit;                    // UART inizialisieren.

  // Interrupts einschalten.
  asm sei end;                 

  // Hauptschleife
  repeat
    UARTReadChar;              // Simuliert einen Tastendruck. 
    Str(Random + 1: 4, s);     // Die Zufallszahl abholen.
    UARTSendString(s);         // Zufallszahl ausgeben. 
  until 1 = 2;

end.

Mehrere Würfel

Schlechte Lösung

Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen:

    Str(Random + 1: 4, s);     // Die Zufallszahl abholen.
    UARTSendString(s);         // Zufallszahl ausgeben. 
    Str(Random + 1: 4, s);     // Ist abhängig vom ersten Wurf.
    ...

Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist dies unbrauchbar !

Ideale Lösung

Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar.

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.

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.

// Globale Variablen.
const
  anzWuerfel = 15;
var
  Random: array[0..anzWuerfel - 1] of byte;

  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;

  // Lokale Variablen.
  const
    RandomCount = 6; // Anzahl Würfelaugen
  var
    i: integer;
    rnd: array [0..anzWuerfel - 1] of byte;

  begin
    for i := 0 to anzWuerfel - 1 do begin
      Inc(rnd[i]);
      if rnd[i] > i then begin
        rnd[i] := 0;
        Inc(Random[i]);
        if Random[i] >= RandomCount then begin
          Random[i] := 0;
        end;   
      end;
    end;
  end;

var
  s: ShortString;
  i: integer;

begin
  // Timer 0
  TCCR0A := %00;           // Normaler Timer
  TCCR0B := %011;          // Clock = CPU / 16.
  TIMSK0 := (1 shl TOIE0); // Enable Timer0 Interrupt.

  // UART
  UARTInit;

  // Interrupts einschalten.
  asm SEI end;              

  // Hauptschleife
  repeat
    UARTReadChar;
    for i := 0 to anzWuerfel - 1 do begin
      Str(Random[i] + 1: 4, s);   // Jeder Würfel hat eine eigene Zufallszahl.
      UARTSendString(s);
    end;
    UARTSendString(#13#10);
  until 1 = 2;
end.

Siehe auch

Autor: Mathias