bessere Zufallszahlen erzeugen

Hallo,

für einen elektronischen Würfel mit Arduino, was sonst ;), braucht man natürlich Zufallszahlen.
Nun habe ich mitbekommen das random() alleine immer wieder die gleiche Zahlenfolge erzeugt nach µC Reset.
Das kann man mit randomSeed() ändern. Ändert den Startwert für random(). Soweit ist mir das klar.

Was mir nicht klar ist, ist es sinnvoll vor jeden random() Aufruf immer ein randomSeed() zu starten oder reicht es randomSeed() einmal bei Sketchstart im setup aufzurufen und dann random() im Loop einfach machen lassen? Was bringt mehr Zufälle?

Gegenwärtige Idee wäre die Dauer des Tastendrucks zum würfeln auswerten, randomSeed() übergeben und dann mit random() eine Würfelaugenzahl erzeugen. Oder die Tastendruckdauer in [ms] noch mit irgendwas multiplizieren vor Übergabe an randomSeed()?

Es ist jetzt zwar keine direkte Antwort auf deine Frage.
Aber eine Anregung bzw eine Idee:

Benutz doch einen Analog-IN Eingang ohne Pulldown Widerstand.
Lass einfach einen Draht als Antenne fungieren. Die Störungen
sind doch ziemlich Random :wink: ?

Hallo,

pendelt sich der analoge Wert nicht in einem engen Bereich ein wo er dann rumzappelt, wenn er offen?

Ein unbeschalteter analoger Eingang ist gut für des Startwert des Zufallsgenerator.
Die Random-Funktion mußte wenn sie richtig programmiert ist zwar eine vom Anfangswert abhängige Zahlenfolge liefern. Diese sollte aber statistisch auf den ganzen Datenraum verteilt und die nächsten Zahlen nicht vom jetzigen oder zukünftigen Zahlen abhängen also nicht vorhersagbar sein.

Die Tastaturdruckdauer kann als Zufallszahl herangezogen werden wenn man zB den Modulo 10 nimmt. Die Taste muß aber über Interrupt eingelesen werden da durch Polling nur bestimmte Werte möglich sind weil die Schleife einfach eine gewisse Zeit braucht um abgearbeitet zu werden und darum nur vielfache dieses Wertes möglich sind.

Alternativ kannst Du auch eine modulo-Wert des micros() Werts bei Tastendruck verwenden, da der Tastendruck bei beliebigen Zeitpunkten erfolgt und sicher nicht auf die µS genau gemacht werden kann. Auch hier Interruptabfrage der Taste.

Grüße Uwe

Hallo,

also ist es sinnvoll vor jeden ramdom() immer wieder ein randomSeed() voranzustellen?

Dann werde ich mal die Tastendruckdauer mit Interrupt ermitteln und vielleicht einen offen Analogeingang noch dazu nehmen und miteinander multiplizieren. µs statt ms ist auch besser. Sind dann nicht wegen Interruptnutzung irgendwelche Pins nicht mehr nutzbar? Da war doch irgendwas.

Danke Euch für guten Hinweise.

Nochwas nebenbei. Warum zeigt das Forum bei nicht eingeloggt sein falsche Beitragserstellzeiten an? Fiel mir schon mehrfach auf. Uwe's Post soll zum Bsp. 14:34 Uhr erstellt wurden sein. Kann aber nicht sein. « Reply #3 on: Today at 02:34:38 PM » Logge ich mich ein, stimmt der Zeitstempel wieder. Könnte man vielleicht mal dem Forenadmin mitteilen zur Korrektur.

hi,

welche zeit ist denn die korrekte? Deine oder die von freund rufus aus kalkutta?

in Deinem profil stellst Du Deine zeitzone ein, dann wird das umgerechnet, wenn Du eingeloggt bist.

gruß stefan

Doc_Arduino:
Nochwas nebenbei. Warum zeigt das Forum bei nicht eingeloggt sein falsche Beitragserstellzeiten an? Fiel mir schon mehrfach auf. Uwe's Post soll zum Bsp. 14:34 Uhr erstellt wurden sein. Kann aber nicht sein. « Reply #3 on: Today at 02:34:38 PM » Logge ich mich ein, stimmt der Zeitstempel wieder. Könnte man vielleicht mal dem Forenadmin mitteilen zur Korrektur.

Das ist die Zeit des Servers; aber frag mich nicht wo der Server sich befindet.
Ohne login weiß der Server nicht wo Du zuhause bist.
Grüße Uwe

Hallo,

wenn ich eingeloggt bin ist es die richtige Zeit. Sonst die falsche Zeit.

Edit beim tippen. Ach'so. Serverzeiten sind verschieden und werden beim Login wie Eisebaer schreibt korrigiert. Alles klar.

Ich überlege gerade wegen dem Interupt. Der Taster prellt ja. Dann würde ja der Interupt oder beide (je ein für gedrückt und nicht mehr gedrückt) während des prellens mir meine Drückzeit zu nichte machen. Kann man das entprellen mit der Bounce.h und Interrupt kombinieren oder gewinnt der Interrupt immer? Eigentlich ja, wird ja vorrangig behandelt. Ich bin da gerade in einer Endlosschleife im Kleinhirn ... :roll_eyes:

Nein, Bounce.h und Interrupt kann man nicht kombinieren. Das Prellen und mehrfache einlesen der micro()Zeit ist in diesem Fall nicht schlimm.

In der Interruptroutine liest Du micros() in eine globale Variable und setzt ein Flag das der Taster gedrückt wurde.

Im loop() kontrollierst Du das Flag und bei gesetztem Flag (kannst Du zum Entprellen eine 5mS Pause machen) verarbeitest Du die Micros-Zeit zu einer Zufallszahl, gibst sie an das Display aus und löscht das Flag. In diesem Fall ist eine mehrmaliges Update der Zeit-Variable wegen Prellen nicht schlimm.

Grüße Uwe.

Hallo,

ich glaube ich hab's noch nicht verstanden, also die Methode. Laut meiner Überlegung brauche ich 2 Interrupts. Einen wenn ich auf den Taster drücke. High nach Low. Und einen 2. Interrupt wenn ich den Taster los lasse. Low nach High Pegelwechsel. Ich nutze den internen PullUp am Eingang.
Wenn der Taster aber prellt. Dann springt doch der µC mehrfach zwischen beiden Interrupts hin und her und am Ende müßte ich nur die letzte Prellzeit erhalten. ??? :roll_eyes:

Selbst wenn ich einmal kurz drücke und dann nochmal kurz drücken muß und dazwischen die Zeit messen möchte. Ich bekomme das prellen nicht aus dem Kopf und damit das hin und her springen.

Du mußt nicht die Dauer des Tastendruck nehmen sondern die Zeit ab Einschalten des Arduino. Auch diese Zeit ist zufällig.
Grüße Uwe

Hallo,

das ist mir schon klar das ich die laufende Zeit jeweils abfragen muß und daraus die Differenz bilde.

Mir ist nur nicht klar wie das mit den entprellen funktionieren soll. Der Interrupt reagiert doch zum Bsp. auf ein LOW Signal. Der andere auf ein HIGH. Jetzt speicher ich den aktuellen µs Zähler. Jetzt lass ich den Taster los und speicher wieder den aktuellen µs Zeitzähler und bilde die Differenz. Das Problem was ich sehe ist. Wenn der Taster prellt spielen die Interrupts untereinander Ping Pong und messe nur die letzte Prellzeit. Verstehst Du mein Problem bzw. mein Denkfehler? Helf mir raus. :~

Das Pin angepaßte Bsp. aus meinem Buch (o'reillys Erik Bartmann) funktioniert auch nicht. LED 23 blinkt. Aber die tasterLED 8 reagiert nicht auf Tastendruck. Bleibt aus. Der Taster selbst funktioniert aber. Muß am Sketch liegen.

int ledPin = 23;                     // LED 
int tasterLED =  8;                  // Taster-LED 
int tasterPin = 12;                  // Taster 

int interruptNumber = 0;             // Interrupt-Nummer 
volatile int statusLED = LOW;        // LED-Status 
 
void setup(){ 

  pinMode(ledPin, OUTPUT);  
  pinMode(tasterLED, OUTPUT); 
  pinMode(tasterPin, INPUT); 
  digitalWrite(tasterPin, HIGH);       // internen PullUp Widerstand aktiviert

  attachInterrupt(interruptNumber, interruptroutine, FALLING); 
} 
 
void loop(){ 
  for(int i = 0; i < 5; i++){ 
     digitalWrite(ledPin, HIGH);  
     delay(500); 
     digitalWrite(ledPin, LOW); 
     delay(500); 
  } 
} 
 
void interruptroutine(){ 
  statusLED = statusLED^1; 
  digitalWrite(tasterLED, statusLED); 
}

Doc_Arduino:
Hallo,

das ist mir schon klar das ich die laufende Zeit jeweils abfragen muß und daraus die Differenz bilde.

Nein, keine Differenz.
Die Zeit zwischen Einschalten und Tastendruck ist gleich zufällig wie Dauer des Tastendrucks.
Grüße Uwe

Hallo,

okay, Sketch kann nicht funktionieren, ich muß natürlich den Taster auch an den Pin mit dem gewählten Interrupt anschließen und nicht woanders. Kann ich dann trotzdem den internen Pullup verwenden? An Pin2 = INT.0 Traue mich das noch nicht so zu flashen.

Wegen der Zeitmessung mach ich morgen weiter. Bin da im Moment scheinbar total neben der Spur ... :expressionless:

Hallo,

so, habe mir das nochmal überlegt wie Du das meinen könntest.

Ich nehme die Zeit ab µC einschalten bis ersten Tastendruck. Die Zeit nehme ich für randomSeed(). Richtig?
Später lasse ich nur noch random() laufen solange die Taste gedrückt ist?

Meintest Du das so?

Du denkst kompliziert.
Schon modulo 6 von micros() ist eine gute Zufallszahl für einen Würfel, weil der Moment des Tastendrucks unmöglich genau auf die µS sein kann.

Wenn Du aber micros() bei Tastendruck nimmst, die dann in randomSeed() nutzt um den Startwert zu definieren und dann mit random() die Zufallszahl holst weiß ich nicht ob, die Zufälligkeit der Zufallszahl verbessert wird.

Grüße Uwe

Hallo,

ach Du meinst ganz ohne randomSeed und random, nur Tastendruckzeitpunkt und modulo 6 ?

ja, ist eine Möglicheit wenn Du nur einen Würfel brauchst.

Bei 2 Würfeln entweder modulo 12 und daraus 2 Zufallszahlen machen oder über randomSeed und 2 mal random.

Uwe

Hallo,

okay, hab das getestet. Leider hat das nicht viel mit Zufall zu tun. Meistens kommt immer nur 0, 2 oder 4 raus. Muß wohl doch random verwenden?

int TASTER = 2;
volatile unsigned long ZEITPUNKT;
int Wuerfel;


void setup()
{
  Serial.begin(9600);
   
  pinMode(TASTER, INPUT); 
  digitalWrite(TASTER, HIGH);       // internen PullUp Widerstand aktiviert
  
  attachInterrupt(0, qwertzu, FALLING);   // INT.0 = Pin.2 (TASTER)
}

void loop()
{
  Wuerfel = ZEITPUNKT % 6;
  Serial.print(ZEITPUNKT);
  Serial.print("  ");
  Serial.println(Wuerfel);
}

void qwertzu()
{
  ZEITPUNKT = micros();
}

Dann wird millis also nicht kontinuirlich sondern in 2-er Schritten erhöht???
Dann mach modulo 12 und dividiere durch 2 oder modulo 60 und durch 10 dividieren.
Grüße Uwe