Von einer endlichen Zahl Musikstücke möchte ich eines zufällig auswählen und wiedergeben. Dazu verwende ich random(). Da die Funktion nach einer zufälligen Zeit durch Drücken einer Fernbedienung aufgerufen wird, hatte ich eine mehr oder minder zufällige Zufallszahl erwartet. Leider werden immer die selben Zahlen erzeugt:
Das im setup() zu machen ist relativ witzlos, weil es da immer in derselben Millisekunde nach dem Programstart abläuft, und dann wird ja auch immer derselbe Startwert initialisiert. Richtig wäre: Beim Drücken einer Taste den Startwert initialisieren.
Oder wenn die Schaltung eine RTC hat, könntest Du die RTC-Uhrzeit zum Initialisieren verwenden.
Schau dir mal wie Pseudo-Zufallsgeneratoren funktionieren. Das ist ganz normal. Wenn der gleiche Seed verwendet wird, wird die gleiche Reihe erzeugt. Das gibt es z.B. auch bei Computerspielen, vor allem bei rundenbasierenden Taktik-Spielen wie die XCOM Serie oder ähnliches. Wenn man immer genau das gleiche macht, machen die Gegner auch das gleiche, weil die Zahlen gleich sind. Da gibt es dann manchmal eine Option namens "save scumming" um beim Neuladen einen neuen Seed für den PRNG zu erzeugen.
Bessere Zufallsgeneratoren verwenden den Jitter zwischen einem Hardware-Timer und dem Watchdog-Timer (der einen eigenen RC-Oszillator hat) um richtige Zufallszahlen zu erzeugen. Nachteil ist dass es sehr langsam ist, dann der Watchdog nur alle paar ms ein Bit liefern kann. Man kann das aber auch nur einmal machen, um dann diese Zufallszahl als Seed für die Arduino random() Funktion zu liefern. Das wird hier gezeigt:
Da gibt es aber auch eine vollständige Library dafür (mit der oben genannten Einschränkung):
Ein Analog-Eingang streut übrigens bei weitem nicht genug um da wirklich vernünftige Zahlen zu erzeugen. Da gibt es erschreckende Diagramme über die statische Verteilung.
Hallo Uwe,
danke für Deine Erklärung, aber ich hatte das Thema schon als gelöst gekennzeichnet, da die Musiktitel jetzt hinreichend zufällig ausgewählt werden. Bitte spare Deine Kraft, denn ich habe noch einen defekten UNO zu reparieren!
Ein Analog-Eingang streut übrigens bei weitem nicht genug um da wirklich vernünftige Zahlen zu erzeugen. Da gibt es erschreckende Diagramme über die statische Verteilung.
Halbleiter rauschen gerne, was man normalerweise nicht haben will.
Wenn man hier eine Diode als Rauschgenerator nutzt und am Analog-Eingang anlegt könnte man das Optimieren ?
Keine Ahnung. Lässt sich vielleicht machen, aber ich habe das noch nicht getestet und auch keine Erfahrung damit.
Und dass ein offener CMOS Eingang einen willkürlichen Wert annimmt stimmt zwar und man ließt immer wieder mal dass Leute Unsinn erhalten wenn sie versuchen offene Eingänge zu messen, aber die Variation ist auf dem AVR wohl nicht so hoch wie man denkt. Das wird auch schaltungstechnische Gründe haben. Auf anderen Mikrocontrollern geht das wohl eher.
Wie gesagt, kann man sich durch den Watchdog Timer einen zufälligen Seed holen. Und das ganz ohne externe Hardware. Wenn man aber sowieso was mit Tastern macht, dann wird die Zeit des ersten Tastendrucks einfacher sein.
LiedNummer = random(anzahlLieder + 1); // Zufallsnummer erzeugen zwischen 1 bis anzahlLieder
ist falsch weil dabei auch 0 herauskommen kann.
Ich würde einfach ausnutzen, daß die Aufrufzeit zufällig ist. Die Kombination aus Random Seed und Random tut das letztendlich auch genau so. D.h. entweder so
void loop() {
if (zustandEingang == HIGH && digitalRead(eingangPin) == LOW) {
LiedNummer = (millis() % anzahlLieder) + 1; // +1 weglassen falls von 0 anfangend gezählt werden soll
Serial.print("LiedNummer = "); Serial.println(LiedNummer); // Debug-Ausgabe
}
zustandEingang = digitalRead(eingangPin);
delay(10);
}
LiedNummer = random(anzahlLieder) + 1; // Zufallsnummer erzeugen zwischen 1 bis anzahlLieder
Da der Max-Wert "exclusive" ist, sollte es so gehen.
Danke für diesen und alle anderen Hinweise! Während ich das schreibe, höre ich zufällig ausgewählte Musik.
Ich hoffe, der Beschenkte freut sich dann auch! Wenn man lange an einer Sache programmiert und gebastelt hat, mag man es nicht mehr gerne aus der Hand geben. Geht sicher nicht nur mir so.