Zufallswiedergabe exklusiv des letzten Titels

Hallo,

mit dieser Funktion versuche ich momentan eine zufällige Auswahl einer abzuspielenden Melodie zu erzeugen. Jedoch möchte ich vermeiden, dass die zuletzt gewählte Melodie erneut abgespielt wird. Dies scheint jedoch nicht zu funktionieren und ich weiss nicht warum.

Es wird zum jetzigen Zeitpunkt auch der zuletzt wiedergegebene Titel abgespielt, obwohl ich dies ja eigentlich durch die while-Schleife zu verhindern versuche.

void sensor_check()  // Sensorabfrage
{               
  static byte piezo_value = 0;            // Momentan vom Klopfsensor ausgelesener Wert
  static byte last_melody = 0;            // Zuletzt gespielte Melodie
  const byte piezo_threshold = 1;         // Schwellwert für den Klopfsensor
  
  piezo_value = analogRead(piezo);        // Sensor auslesen

  if(piezo_value >= piezo_threshold)      // Falls der Schwellwert überschritten wurde..
  {
    while(current_melody == last_melody)  // Solange die per Zufall erzeugte Melodie der zuletzt gespielten Melodie entspricht,
    {
      current_melody = random(1, 3);      // ..zufällig eine der gespeicherten Melodien auswählen
    }
    last_melody = current_melody;         // Für die nächste Zufallsmelodieauswahl festhalten, welche Melodie zuletzt gespielt wurde
  }
}

Wer kann helfen?

Gruß Chris

Die Schleife wird nur ausgeführt wenn die alte und neue Melodie gleich sind. Ansonsten wird sie übersprungen. Ich sehe nicht wo current_melody beim ersten mal herkommt, aber kann es sein, dass am Anfang current und last schon ungleich sind?

Probier mal eine do-while Schleife: http://www.elektronik-bastelkeller.de/C_Ardu_6_4.php Damit wird der Code-Block mindestens einmal ausgeführt

Chris72622: mit dieser Funktion versuche ich momentan eine zufällige Auswahl einer abzuspielenden Melodie zu erzeugen. Jedoch möchte ich vermeiden, dass die zuletzt gewählte Melodie erneut abgespielt wird. Dies scheint jedoch nicht zu funktionieren und ich weiss nicht warum.

Die einfachste Strategie beim Ziehen einer unerwünschten zufälligen Zahl ist es: Einfach solange nochmal ziehen, bis es kein unerwünschtes Ergebnis mehr gibt.

Zum Beispiel als Funktion:

int getRandomMelody(int lastMelody, int totalMelodies)
{
  int randMelody=random(totalMelodies); // Ziehe einmal
  // Ziehe danach weiter, solange Ergebnis unerwünscht 
  while(randMelody==lastMelody) randMelody=random(totalMelodies); 
  return randMelody;
}

Oder mit Deiner Schleife, entsprechend geändert:

  if(piezo_value >= piezo_threshold)      // Falls der Schwellwert überschritten wurde..
  {
    current_melody = random(1, 3);      // ..zufällig eine der gespeicherten Melodien auswählen
    while(current_melody == last_melody)  // Solange die per Zufall erzeugte Melodie der zuletzt gespielten Melodie entspricht,
    {
      current_melody = random(1, 3);      // ..zufällig eine der gespeicherten Melodien auswählen
    }
    last_melody = current_melody;         // Für die nächste Zufallsmelodieauswahl festhalten, welche Melodie zuletzt gespielt wurde
  }

Nachteil dieser Strategie: Man weiß nie, wie oft man neu ziehen muss und demzufolge hat diese Funktion keine klar feststehende Laufzeit. Aber das spielt bei Deinem Anwendungsfall vielleicht keine Rolle.

Was aber vielleicht eine Rolle spielen könnte: Auf digitalen Mikrocontrollern gibt es eigentlich keinen wirklichen Zufall. Wenn Du den Zufallszahlengenerator vor der Verwendung nicht wirklich mit einem zufälligen Startwert initialisierst, wird er Dir bei jedem Programmlauf immer dieselbe Zufallszahlenfolge liefern, also nach jedem Reset dieselbe "zufällige" Reihenfolge der Melodien abgespielt werden.

Hallo,

ich habe es jetzt so gelöst:

if(piezo_value >= piezo_threshold)       // Falls der Schwellwert überschritten wurde..
  {
    current_melody = random(1, 5);         // Zufällig die nächste Melodie ermitteln
    do
    {
      current_melody = random(1, 5);       // Erneut zufällig die nächste Melodie ermitteln,
    } 
    while(current_melody == last_melody);  // sollte die neue Melodie noch immer der zuletzt Gespielten entspricht

Leider ist der zufällige Ablauf jedoch jedoch bei jedem Prozessorstart derselbe, obwohl ich im Setup folgendes stehen hab:

randomSeed(analogRead(A3));       // Den Zufallsgenerator für die Melodieauswahl mit Zufallswert über A3 "füttern"

Kann es sein, dass der Prozessor mit dem "A3" nichts anfangen kann?

Gruß Chris

Damit hast du beide Vorschläge kombiniert. Das geht natürlich, ist aber etwas unsinnig. Durch das do/while wird der Block schon immer mindestens einmal ausgeführt. Das extra random() davor ist also unnötig.

Wenn der Compiler mit A3 nichts anfangen können würde er meckern. Du kannst dir mal in einem Test-Programm ständig den Wert von analogRead(A3) anzeigen lassen.