Zufalls-Befehl garnicht Zufällig !?

Hey, ich hab gerade mal mit dem Random-Befehl rumgespielt dabei ist folgender Sketch entstanden:

#include <FastLED.h>

    #define NUM_LEDS    320
    #define DATA_PIN    1
    #define LED_TYPE    WS2812
    #define COLOR_ORDER GRB
    
    #define x random (1,300)
    #define y random (0,319)
    #define z random (0,127)
    #define R random (0,255)
    #define G random (0,255)
    #define B random (0,255)
    
    CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  }
void loop () {
  leds[y] = CRGB (G,R,B);
  FastLED.show(z);
  delay(x);
}

Zufällige Zeit, Zufällige Farbe, Zufällige Position und Zufällige Helligkeit.

Das ganze auf einem Teensy3.2 und WS2812 RGBLED´s, dabei ist mir aufgefallen das der Ablauf jedes mal genau der Selbe ist egal wie oft ich den Sketch neu aufspiele oder den Teensy ab und wieder anschließe immer der exakt gleiche Ablauf.

Ist das normal oder woran liegt das und kann man das irgendwie ändern oder umschreiben damit wirklich alles zufällig ist und jedes mal etwas anderes passiert ?

Gruß Flo, danke schonmal.

randomSeed

Die Wiederholung ist normal.
Eigentlich jeder (pseudo) Zufallsgenerator hat einen Seed / Startwert.

Den solltest du vorher setzen.
z.B. bieten sich die millis() beim ersten Tastendruck an.
Oder das verwerten des Rauschens an einem ADC

#include <FastLED.h>

    #define NUM_LEDS    320
    #define DATA_PIN    1
    #define LED_TYPE    WS2812
    #define COLOR_ORDER GRB

    long randNumber;
    
    #define x random (1,300)
    #define y random (0,319)
    #define z random (0,127)
    #define R random (0,255)
    #define G random (0,255)
    #define B random (0,255)
    
    CRGB leds[NUM_LEDS];

void setup() {
  Serial.begin(9600);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  randomSeed(analogRead(0));
  }
void loop () {
  leds[y] = CRGB (G,R,B);
  FastLED.show(z);
  randNumber = random(300);
  Serial.println(randNumber);
  delay(x);
}

ich habs jetzt mal versucht.. jetzt ist der startwert also jedesmal ein anderer ? D.h. die werte in den Random befehlen oben werden aber weiterhin eingehalten ? und was bewirkt die 300 bei :

randNumber = random(300); ?

Hallo,

https://www.arduino.cc/en/Reference/Random

Warum schreibst du

#define y random (0,319)

statt

#define y random (NUM_LEDS)

?

random() produziert bei gegebenen Startwert (randomSeed())immer die selbe Folge an Zahlen die untereinande ziemlich zufällig auf die Zahlenmenge zwischen min und maximalwert verteilt sind.

Zu C64-Zeiten nahm man Random um T einfach und nicht besonders sicher Texte zu chifrieren weil die Abfolge zufällig aber wiederholbar ist.

Um wirklich zufällige Werte zu erhalten die jedesmal anders sind braucht es einen zufälligen Startwert. Ein unbeschalteter Analogeingng liefert zufällige Werte. Noch zufälligere Werte erhält man, wenn man Zeiten die mit einer Tastatureingabe zusammenhängen wie zb Länge eines Tastendruckes, Abstand zweier Tastendrücke, Moment eines Tastendruckes ecc.

Grüße Uwe

uwefed:
Ein unbeschalteter Analogeingng liefert zufällige Werte.

Für Blinken und Spiele reicht es, aber für sicherheitsrelevante Sachen streut ein Eingang bei weitem nicht genug.

Hallo,

ich bin der Meinung das random() immer die gleiche Reihenfolge an Zahlen erzeugt, die zufällig aussehen soll. RandomSeed() verschiebt nur den Startwert (Einstiegspunkt) eben dieser Reihenfolge, meiner Meinung nach. Das heißt, an der Reihenfolge an sich ändert sich erstmal nichts.

Wer auf einem Linuxrechner sein Unwesen treibt, der hat schon einen sehr sehr starken Zufallsgenerator im Kernel eingebaut. Der wird sogar als echter Zufallsgenerator bezeichnet, weil seine theoretische Entropie sehr sehr gut ist.
Alles darüber hinaus geht nur noch mit Lavalampen und Kamerarauschen zu toppen.

RandomSeed() verschiebt nur den Startwert (Einstiegspunkt) eben dieser Reihenfolge

Aber das ist doch schonmal was.

Du hast also max. 232 verschiedene Pseudo-Randomwerte und ebensoviele Folgen. Das reicht für die meisten Arduino-relevanten Anwendungen.

Dieser Thread ("Immer die gleiche Folge") ist doch schon längst beantwortet.
Dass man mit randomSeed(analogRead(0)) nur 210 (1024) verschiedene Folgen generieren kann, und selbst die wohl nicht gleichverteilt auftreten, dürfte klar sein , aber sogar trotzdem ausreichen.

Hallo,

naja, es kommt darauf an welchen Zahlenbereich man nutzt. Ich hatte mal einen Würfel mit random programmiert. Ob der Zufall dafür reicht ist Ansichtssache. Erkennt man die Zahlenfolge weis man welche Zahl als nächstes kommt. Es erfordert mehr Aufwand um selbst dafür mehr an Zufall reinzubringen.

Doc_Arduino:
Hallo,

naja, es kommt darauf an welchen Zahlenbereich man nutzt. Ich hatte mal einen Würfel mit random programmiert. Ob der Zufall dafür reicht ist Ansichtssache. Erkennt man die Zahlenfolge weis man welche Zahl als nächstes kommt. Es erfordert mehr Aufwand um selbst dafür mehr an Zufall reinzubringen.

Nicht wenn Du als Startwert jedesmal entweder die Zeit in millis() oder micros() seit dem letzten Tastendruck oder die Länge des Tastendrucks hernimmst.

Es müßte sogar Modulo 6 der Zeit in millis() oder micros() seit dem letzten Tastendruck oder die Länge des Tastendrucks genügen um eine zufällige Zahlenfolge von 1 bis 6 zu erhalten.
Grüße Uwe

Könnte nicht das "randomSeed(...)" bei jedem Durchlauf der Loop aufgerufen werden. Solange es vom Timing her hinkommt selbstverständlich.

staivoup:
Könnte nicht das "randomSeed(...)" bei jedem Durchlauf der Loop aufgerufen werden. Solange es vom Timing her hinkommt selbstverständlich.

Klar...
Aber wo willst du den "zufälligen" Seed in einem deterministischen Kontext finden?

staivoup:
Könnte nicht das "randomSeed(...)" bei jedem Durchlauf der Loop aufgerufen werden. Solange es vom Timing her hinkommt selbstverständlich.

Ja, aber als Startwert brauchst Du einen nicht sich wiederholenden Wert. Woher bekommt Du den?

Random() gibt eine Zahlenfolge die statistisch gleichmäßig auf den Wertebereich aufgeteilt ist. Das ist aber eine Folge die sich bei gegebenen Startwert wiedeholt. Damit Du nicht jedesmal die Gleiche Abfolge hast mußt Du mit verschiedenen Startwerten beginnen.

Wenn Du mit einem nicht so zufälligen Startwert (mit wenig Streuung oder mit wenigen verschiedenen Werten) beginnst so hat random() auch wenig Streung.

Grüße Uwe

Hmm... also setzt "randomSeed" immer das "random" auf einen Startwert. Ich dachte es wäre eine Art Delta, hätte ich mal die Seite lesen sollen.

Ich kenne von früher Zufallsgeneratoren als Steckkarte für den Rechner die einen konstanten Rauschstrom ausgeben. Wie könnte sowas mit Hausmitteln für Arduino gemacht werden? Ohne Interaktion mit Taster oder vom PC mit Seralinput und so. Das normale Analograuschen ist vermutlich nach Glockenkurve normalverteilt.

Die Position eines speziellen Atoms messen? Was natürlich die Messung verfälscht. Oder gibt es da schon kleine Devices?

Der Due hat eine Hardware-Zufallsgenerator. Sowas muss im Prozessor integriert sein.

Auf dem AVR ist es die beste Optionen den Jitter zwischen dem Quarz und dem Watchdog Timer (der einen eigenen RC-Oszillator hat) zu verwenden:

Hat aber den Nachteil, dass es recht lange dauert. 500ms für 32 Bit.

Der zweite Link zeigt wie man das ohne Library machen kann um einen echten Zufallswert für randomSeed() zu bekommen

Hier mal meinen Seed Generator. Hat bisher für meine Zwecke gereicht!
Sogar ein Tuning ist möglich: Ein Stückchen Draht als Antenne an A pin klemmen.

long seed(byte pin)
{
 long  result = 0;
  for(int i=0;i<32;i++) 
  {
    int a = analogRead(pin);
    //Serial.println (a);
    result = (result << 1) | (a & 1);
  }
  return result;
}

void setup() 
{
   randomSeed(seed(A0));
}

Ich frag jetzt doch nochmal kurz nach.. wenn ich also RandomSeed verwende wird der Startwert für alle Random-funktionieren auf diesen wert ( z.b. wert vom analog pin ) gesetzt d.h. aber alle Random-Funktionen funktionieren nach wie vor ? also bei:

#define x random (1,300)
(...)
long randNumber0;
(...)
void setup() {
Serial.begin(9600);
randomSeed(analogRead(17));
(...)
}

void Loop () {
Serial.println(randNumber0);
(...)
}

ist x also trotzdem immer ein wert zwische 1 und 300 ?

oder muss ich das dann anders lösen ?

Schau dir im Handbuch an, was die Funktion random() tut.
https://www.arduino.cc/en/Reference/Random

Und wenn sie nicht das tut, was sie laut Handbuch tun soll, dann ist sie kaputt.
Aber sei beruhigt....
Sie tut das, was sie tun soll.