Random-Zahlen vergleichen?

Hallo Community.

Ich bin neu hier im Forum, aber habe schon ein bisschen Erfahrung was Arduino angeht. Ein völliger Profi bin ich aber nicht, deswegen bitte ich um einfach verständliche Antworten oder um Geduld wenn ich "dumme" Fragen auf eure Antworten stelle :D Danke

Also zu meinem Problem: Ich habe an meinem Arduino Uno sieben LED´s angeschlossen auf den Kanälen 3 bis 9. Diese möchte ich auf Zufallsprinzip leuchten lassen. Dabei sollen aber minimal 2 und maximal 5 LED´s leuchten. Welche das sind möchte ich auch dem Zufall überlassen. Dazu habe ich schon einmal folgendes Programm geschrieben:

long randomNumber;
long wuerfelzahl;

void setup()
{
  
  Serial.begin(9600);
  Serial.println("Start einer neuer Sequenz");
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  
  randomSeed(analogRead(0));
}

void loop()
{
  wuerfelzahl = random(2,6);
  delay(1000);
  Serial.print("Es wird ");
  Serial.print(wuerfelzahl);
  Serial.println(" mal gewürfelt");
  
  for(int i = 0; i < wuerfelzahl; i++)
  {
    randomNumber = random(3,10);
    Serial.println(randomNumber);
  }
    //digitalWrite(zufallszahl,HIGH);
  delay(5000);
}

Mein Problem ist, dass selbstverständlich auch manchmal gleiche Zahlen gewürfelt werden können. Wenn also zwei mal gewürfelt wird und beides ist eine 4 geht logischerweise im Endeffekt nur die LED auf Pin 4 an. Dann wäre allerdings nicht mehr mein Wunsch erfüllt, dass zwischen 2 und 5 LED´s leuchten sollen. Lösen könnte man das, wenn ich abfragen könnte ob zwei der Zufallszahlen gleich sind aber wie mache ich das? Oder ist es vielleicht auch anders lösbar?

Eine Antwort oder ein Lösungsansatz wäre sehr nett. Danke :)

MFG

Hallo,

ein Ansatz wäre den aktuellen Wert sich zu merken, die nächste Zahl generieren und dann alt und neu vergleichen. Dann erfolgt eine Entscheidung (if) was zu tun ist. Beim Eintritt in die Entscheidung setzt man meistens alt gleich neu, dann kann der nächste Vergleich wieder mit der vorhergehenden Zahl und der dann neuen erfolgen.

Ja, daran habe ich auch gedacht. Aber wie unterscheide ich meine bereits bekannte Zahl mit der neuen Zufallszahl? Ich wollte dann die Variable "bekannteNummer" gleich randomNumber setzen. Aber dann kommt ja eine neue randomNumber. Wie drücke ich dann aus, dass Arduino diese nicht gleich bekannteNummer setzt sonder damit vergleicht, ohne dass ich ihm dass fünf mal sagen muss. Also so dass ich die Schleife behalten kann?

Hallo,

if(alterWert == neuerWert) { // oder != wenn NICHT
  //hier kommt der Code rein wenn
}

Lese dir alles über if durch.

lg dony

Hi.

Das ich eine if-Abfrage machen muss, war mir klar und ich weiß auch wie die funktionieren ;) Vielleicht stehe ich auch auf dem Schlauch, aber mir ist unklar wie ich den alten Wert vom neuen Unterscheide?

Einfach zwei Variablen statt eine

Wo muss ich jetzt eine zweite einfügen?

for(int i = 0; i < wuerfelzahl; i++)
  {
    randomNumber = random(3,10);
    Serial.println(randomNumber);
    randomNumber = alterWert;
    
    if(alterWert == neuerWert)
    {
      //erneut Würfeln
      for(int i = 0; i < wuerfelzahl; i++)
      {
        randomNumber = random(3,10);
        Serial.println(randomNumber);
      }
  }

Sorry, Du hast zwar geschrieben das Du kein Anfänger bist, deshalb hat es mich ein bischen gewundert. ;) Bei einer Frage wie man zwei Werte Vergleicht, kommt halt 'if'. So sollte es funktionieren, allerdings musst du das lange delay() verlagern, sonst bleibt es 5Sekunden dunkel.

for(int i = 0; i < wuerfelzahl; i++)
  {
    randomNumber = random(3,10); // Zahl speichern
    Serial.println(randomNumber);
    
    
    if(alterWert != randomNumber) //mit alten wert vergleichen
    {
      //erneut Würfeln
      for(int i = 0; i < wuerfelzahl; i++)
      {
        randomNumber = random(3,10);
        Serial.println(randomNumber);
      }
      alterWert = randomNumber; // erst nach der if abfrage den alten wert ändern

Ich würde

randomNumber = random(3,10); // Zahl speichern

die die loop schmeissen, damit es ewig weiterläuft, den da das Arduino keine eigene RTC hat, gibt es keine Referenz für random() und Du bekommst immer die selbe Zahlenfolge. Man kann sich auch damit behelfen, einen freien Analogen Eingang zu lesen, und diese Zahl als Referenz verwenden, damit es wirklicher Zufall ist.

lg dony

dony: Man kann sich auch damit behelfen, einen freien Analogen Eingang zu lesen, und diese Zahl als Referenz verwenden, damit es wirklicher Zufall ist.

Echter Zufall ist das damit noch nicht. Es ist sicherlich besser als es nicht zu machen, aber die Streuung der analogen Eingänge ist nicht besonders hoch. Wenn man Taster in der Anwendung hat kann man einfach den Zeitpunkt des ersten Tastendrucks wählen

Ja, oben habe ich auch ne RandomSeed gemacht mit Ausgang 0. Auf die Sache mit den Tastern komme ich zurück, denn die kommen noch dazu. Nur muss ich erstmal den Teil jetzt kapieren xD.

Ja, Serenifly, damit hast Du natürlich Recht!
Genau, schau mal das es läuft. Du verwendest (zumindest derweil) noch keine millis() deshalb ist es im Moment auch egal wo random() steht.

Du kannst Dir mal diesen Thread anschauen. Da geht es auch um eine ‘Zufall’ LED, die mit IR Ein/Ausgeschaltet wird.

lg dony

Tipp:

/**
 *  minimal 2 und maximal 5 Bit gesetzt
 */

 byte bitCount(const byte value)
 {
  byte count = 0;
  for(byte schiebemaske=1;schiebemaske;schiebemaske<<=1) count += bool(schiebemaske & value);
  return count;
 }

void printArray()
{
  byte j = 0;
  Serial.println("// alle moeglichen, der Regel entsprechenden Muster");
  Serial.println("const byte muster[] PROGMEM = {");
  for(byte i = 0; i<=0x7f;i++)
  {
    byte count = bitCount(i);
    if(count > 5) continue;
    if(count < 2) continue;
    if(0==(j%8)) Serial.print("                 ");
    Serial.print("0b");Serial.print(i,BIN);Serial.print(",");
    if(7==(j%8)) Serial.println();
    j++;
  }
  Serial.println("             };");
}




void setup() 
{
  Serial.begin(9600);
  Serial.println("Start");
  printArray();
}

void loop() 
{

}

Danke für deine Mühe dieses Programm zu schreiben, aber leider verstehe ich nicht den kleinsten Teil davon. Ich versuche es lieber auf längerem aber dafür mir verständlichem Weg. Bei dem Programm wüsste ich aber noch nicht mal wo ich anfangen soll zu fragen. Sorry :/

Ich würde da ganz anders rangehen.

  1. Zufahlszahl ermitteln, zwischen 2 und 5, das ist dann die Anzahl der Leds für diese Runde. Byte anzahl
  2. Zufahlszahl ermitteln, zwischen 3 und 9
  3. Prüfen ob Ausgang gesetzt
  4. wenn gesetzt, weiter mit 2.
  5. wenn nicht gesetzt, setzen und Zähler inkrementieren.
  6. Wenn Zähler==Anzahl fertig
  7. wenn nicht, weiter mit 2.

Hi

Wenn wir <8 LEDs haben - Das schreit doch förmlich danach, als Bit in einem Byte gespeichert zu werden!

Per Zufall wird 'die nächste LED' ausgewürfelt, also eine Zahl 0...6 Dann schaue ich in meinem Speicher-Byte nach, ob dieses Bit derzeit gesetzt ist. Ja -> Bit löschen, Bitsumme -- Nein -> Bit setzen, Bitsumme ++

Wenn jetzt meine Bitsumme (= die Anzahl gesetzter Bits oder eben leuchtender LEDs) <2 ist oder >5 ist, wird erneut gewürfelt. Das passiert so schnell, daß der Anwender das 'doppelt würfeln' nicht mitbekommt.

Wenn die LEDs noch brauchbare Würfelzahlen darstellen sollen, dann eben 0...5 würfeln und diese Zahlen entsprechend auf die 7 LEDs anzeigen (bei allen Ungeraden ist die mittlere LED an, bei !=1 ist die 'zwei' an, bei >=4 ist die 2.te Zweiergruppe 'vier' an, bei 6 die waagerechte Zweiergruppe)

MfG

postmaster-ino: Wenn wir <8 LEDs haben - Das schreit doch förmlich danach, als Bit in einem Byte gespeichert zu werden!

Bei 6 Posts auf der Uhr jemanden was von Bits zu erzählen, er wird dir nicht folgen können. Bool vielleicht schon. Aber dafür braucht man nicht mal bool, da man die Information direkt auf den Ausgangspin schreiben kann. Das ist zwar auch ein Bit in einem Register, aber das wird von der IDE schön verdeckt und für den User komfortabel aufbereitet

combie: Tipp:

Also ich würde den Code gerne verstehen aber etwas leuchtet mir nicht ein, ich hab das mal kommentiert, vielleicht ist es völliger Quatsch was ich da geschrieben habe. Die Frage ist auch in den Kommentaren aber warum wird das so geschrieben:

if(0==(j%8))
byte bitCount(const byte value) // Byte Funktion, der Zähler bis 128 wird mitgegeben
 {
  byte count = 0; // Counter wird auf 0 gesetzt
  for(byte schiebemaske=1;schiebemaske;schiebemaske<<=1) // Bit zuweisung, Bitweise nach links schieben (8 mal)
    count += bool(schiebemaske & value); // counter wird nur erhöht wenn schiebemaske = 1² und 1³ (1,2,4,8,16) usw. damit der Counter 8mal durchläuft
  return count; // und zurückgeworfen
 }

void printArray()
{
  byte j = 0; // j definieren
  Serial.println("// alle moeglichen, der Regel entsprechenden Muster");  // ohne Worte-> zur Funktion
  Serial.println("const byte muster[] PROGMEM = {");
  for(byte i = 0; i<=0x7f;i++) // schleife läuft 128 mal (8 Bits)
  {
    byte count = bitCount(i); // Zähler wird durch bitCount() festgelegt.
    if(count > 5) continue;  // Überspringen damit j nicht erhöht wird
    if(count < 2) continue;
    if(0==(j%8)) Serial.print("                 "); // Wenn der Register voll is, Wenn j AND 8 = 0 Das j%8 verstehe ich noch nicht, ja & ist AND und ich weiß das es  ist 0 dann 0; && = Wenn 0=1 und 1=0 Dann: 1
    Serial.print("0b");Serial.print(i,BIN);Serial.print(","); //SP: for (i) counter in binär ausgeben
    if(7==(j%8)) Serial.println(""); // Wenn 8 Bits (1 Byte) erreicht wurden, aber was bedeutet 0==(j%8) oder 7==(j%8)
    j++; // j um eines erhöhen
  }
  Serial.println("             };");
}

Ich habe schon mal von der Methode gehört, aber mir ist auch noch nicht klar wie der Zufall zustande kommt, naja so halbwegs schon, Code technisch aber nicht. Aber ich glaube das kann ich selber herausfinden.

Wäre echt Toll, wenn ihr mir zumindest sagen könnt ob das völliger Quatsch ist und was das mit den & (AND) auf sich hat. Danke!

lg dony edit: Vielleicht auch besser nicht, ist ja nicht mein Thread und dem TO wird es wahrscheinlich nicht helfen.

Das ist kein AND. % ist eine Modulo-Division. Also der Rest der Division. Das ist jedesmal 0 wenn der Wert durch 8 teilbar ist

if(0==(j%8))

Prüft ob eine (neue) Zeile begonnen werden muss.

if(7==(j%8))

Nach 8 Elementen wird ein Zeilenumbruch gemacht.

Ein Zufall ist da noch nicht drin.

Es erzeugt ein Array mit allen Möglichkeiten/Mustern, welche mit 2 bis 5 aus 7 darstellbar sind. Später könnte darauf, über einen Index, zugegriffen werden. (Das kommt in Folge II der Show)

Es ist ein Code Generator welcher eine LookUpTable generiert.. Die vollständige Permutation/Menge der erlaubten Kombinationen.

Serenifly: Das ist kein AND...

Danke, alles klar. Macht eh Sinn, da hab ich wohl zu genau hingeschaut. ;)

@combie: Danke für die Erklärung, jetzt hab ichs verstanden. :-) Das mit dem Zufall noch nicht so ganz, aber ich verstehe auf was Du hinaus willst.

lg dony