Probleme mt random()

» home «

Verschalten Sie 2x ARDUINO UNO für eine Zweidrathkommunikation mit den RX und TX Leitungen (in Vorbereitung auf BC417 und HC-06). Die beiden Geraete koennen dann Befehle hin und her senden.

Nutzt Ihr Projekt (ARDUINO Nano) die Erzeugung zufälliger Werte, dann stoßen Sie früher oder später auf den Befehl random() in der Arduino-Bibliothek. Dieser Befehl sorgt dafür, das ein zufälliger Wert (zwischen min und max) erzeugt wird. Die folgende Codezeile erzeugt einen zufälligen Wert der zwischen 1 und 100 liegt - nehmen wir mal 77 an.

Serial.println(random(1, 100));

Schalten Sie den Arduino aus und erneut ein, erzeugt der Generator allerdings wiederum die zufällige 77 - Sie bemerken bereits jetzt, das mit diesem Befehl etwas nicht stimmt - es ist immer die gleiche Zufallszahl. Bedingt ist dieser Effekt durch die implementierte Hardware die keinen echten Zufallsgenerator besitzt, denn Zufallsgeneratoren werden beispielsweise im Computerbereich mit Echtzeituhren oder Umdrehungswerten des Lüfters gekoppelt, um zufällige Werte generieren zu können - all dies hat der ARDUINO Nano nicht. Die Folge, es entsteht immer der selbe Wert der zwar zufällig irgendwo zwischen 1-100 liegt aber fortan unverändert bleibt.

randomSeed()

Es gäbe allerdings Alternativen, zunächst den Befehl randomSeed() der in der Lage ist zufällige Werte auszugeben, jedoch sind dies keine echten Zufallswerte. Der Befehl randomSeed() bedient sich einer fertigen Liste die zufällig angeordnete feste Zahlen beinhaltet und liest diese Schritt für Schritt aus, so entsteht der Eindruck zufälliger Werte. Dieser Befehl lieftert also ebenfalls keine echten Zufallszahlen.

analogRead()

Eine weitere Alternative wäre analogRead() der den analogen, freien Eingang (z.B.) A0 liest und den Wert zwischen 0...1024 ausgibt. Und tatsächlich erzeugt analogRead() echte zufällige Werte anhand dieses Verfahrens, jedoch hat auch diese Methode ein Problem. Die scheinbar zufälligen Werte an einem freien Analog-Pin werden aufgrund physikalischer Bedingungen erzeugt die in der unmittelbaren Umgebung des Pins herrschen, beispielsweise haben elektomagnetische Felder die im Raum stehen großen Einflus auf den Analogpin aber auch die simple Anwesenheit des Menschen kann dazu führen elektostatische Bedingungen in der Nähe zu verändern und folglich das Ergebnis zu verfälschen.

Wollten Sie analogRead() zur Erzeugung eines booleans ala True/False nutzen könnten Sie dies eventuell so machen:

if (analogRead(0) > 512) {
  return true;
} else {
  return false;
}

Pseudocode der zu 50% true und zu 50% false erzeugt

Zwar ist 512 exakt die Hälfte der Auflösung des Analaogpins mit maximal 1024, jedoch pendeln die gelesenen Werte eher um einen Bereich herum, der stark von den pyhsikalischen Bedingungen der Umgebung geprägt ist. In einem eigenen Versuch habe ich herausgefunden, das der Wert stark im Bereich 200-400 pendelte aber nie 0 oder 1024 angenommen hat. Eine echte Zufallsverteilung ist dies also nicht, eine Anpassung ist also nötig.

rnd = analogRead(0)
if (rnd%2 == 0) {
  return true;
} else {
  return false;
}

Pseudocode der der die Teilbarkeit nutzt um true oder fals zu erzeugen

Die obige Implementierung ist besser geeignet, da es ihr vollkommen egal ist ob der Wert in einem festen Bereich pendelt oder nicht. Das Coding nutzt den Modulo2 und ergibt 0 oder 1 wenn der Wert durch 2 teilbar ist. Denn Sie können durchaus unterstellen, das der Wert zwar in einem engen Rahmen pendeln wird abber dennoch gerade oder ungerade Zahlen in einer natürlichen Verteilung aufweisen wird.

Arduinos Empfehlung

Das ARDUINO Projekt selbst empfiehlt allerdings auch eine eigene Lösung, die aus einer Kombination aus randomSeed() und analogRead() besteht.

long randNumber;

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0));
}

void loop() {
  randNumber = random(300);
  Serial.println(randNumber);
  delay(50);
}

Zwar sind die wenigen Zeilen nicht sehr schwer zu verstehen, jedoch wird vielen Anwendern nicht klar, wie randomSeed(analogRead(0)); wohl mit randNumber = random(300); in Verbindung steht? Denn eine gemeinsame Variable nutzen sie nicht und tauschen auch keine Return-Variable aus. Der Witz liegt in der Hardwareimplementierung. in setup() wird der Zufallsgenerator mit einer Zufallsliste (Seed) initialisiert und im loop() nutzt random() eben genau diesen zuvor initialisierten Zufallsgeneraturs des Chips.

Der Zufallsgenerator eines großen Computers ist einfach zu verwenden, demgegenüber muss man ein wenig Hardwarekenntnis beim ARDUINO mitbringen, um ihn ähnlich wie am Computer nutzen zu können.

Oliver Lohse   •  13.Jun.2020

Navigation


home
Omega 2
ESP32 NodeMCU
Arduino
Raspberry Pi
Python
PHP

Es geht um den heißem Scheiß über den alle reden - IoT (das Internet der Dinge). Doch zunächst der rechtliche Teil auf dieser rein privat betriebenen Webseite.

Die Webseite verwendet keine Cookies oder sonstigen Tracking-Tools, um das Leserverhalten zu speichern.

LM7805 Minimalschaltung


Im Bereich der klassischen digitalen (5V) Schaltungs-Elektronik ist der LM7805 einfach nicht wegzudenken. Dieser Beitrag zeigt den minimalen Aufbau einer Schaltung für die 5V Stromversorgung Ihrer Projekte.

Serial Monitor mit LCD


Es gibt viele Beispiel Sketche zum lesen des RX und TX Ports am ARDUINO UNO, doch viele bereiten nicht den korrekten und vollen String auf. Hier ein übererbeitetes Sketch mit Ausgabe an einem 2x16 Display.


© by O.Lohse • Impressumhome