Go Down

Topic: Hilfe bei dynamischer Pinauswahl und Zufall (Read 596 times) previous topic - next topic

franky27

Hallo zusammen, bin seit gestern Besitzer eines Unos und bin begeistert am lernen. Beim expermimentieren mit zufälligen aktivieren von Pins, habe ich jetzt folgende Frage:
Nehmen wir an ich habe 4 Leds an 4 pins. Diese jetzt "pseudo" zufällig leuchten zu lassen mit der random Funktion war der erste Schritt. Jetzt möchte ich realisieren, dass ich durch 4 Schalter auswählen kann welche LEDs ich benutzen möchte. Die Random funktion soll jetzt nur zwischen den gewählten LEDs laufen und die nicht gewählten nicht beachten. Also ich wähle zB LED 1 und LED 4 aus (zB Pin 13 und Pin 10) und nur zwischen diesen beiden wird fortlaufend eine zufällig eingeschaltet. Schalte ich später den Schalter für LED 3 dazu, soll eben zwischen diesen 3 eine zufällig leuchten. Mein problem liegt jetzt eben in der Logik. Ich habe momentan eine Funktion, welche den Status der Schalter abfragt und somit die Pins definiert die benutzt werden sollen. Aber die Random Funktion verlangt ja eine (min, max-1) übergabe, wie kann ich mein Vorhaben jetzt realisieren? Habe anfangs an ein array gedacht, welches eben eine 0 und 1 map für den Status der Pins generiert, aber ich weiss nicht wie ich random sage - hey nur zufallszahl zwischen den pins mit 1er Einträgen.. Kann mir da vielleicht jemand weiterhelfen?
Viele Grüße
franky

mkl0815

Der einfachste, wenn auch nicht eleganteste Weg ist sicher, zu prüfen ob die zufällig ausgewählte LED aktiviert ist, oder nicht.
Du ermittelst also weiter Zufallszahlen zwischen 1 und 4. In einem Array merkst Du Dir aber zusätzlich, welche der 4 LEDs aktiv ist.
Wenn eine Zufallszahl X ermittelt ist, fragst Du per "if(...)" ob die gewählte LED aktiv ist, wenn ja, wird sie umgeschaltet, wenn nicht, wird sie ignoriert und eine neue Zufallszahl ermittelt. Der Arduino ist auf jeden Fall schnell genug, die "Aussetzer" bei den nicht verwendeten Zufallszahlen zu "verkraften", selbst wenn nur eine LED übrig ist.
Ein Eleganter Weg wäre vermutlich etwas komplizierter.

Du hast 2 Arrays, beide mit je 4 Elementen. Das erste bildet die Schalter ab und jedes Element 1 bis 4 entspricht einem Schalter (und damit dem entsprechenden LED-Zustand aktiv/inaktiv)

Bei jedem erkannten Schaltvorgang an Schalter 1 bis 4 wird nun das zweite Array dynamisch befüllt.
Dafür zählst Du eine Index-Variable von 0 bis 3 durch und prüfst im ersten Array, ob die jeweilige LED aktiv sein soll.
Zusätzlich hast Du eine zweite Zählvariable (Anzahl der aktiven LEDs), die am Anfang "0" ist.
Den Index von jedem Schalter den Du prüfst, der aktiv ist, trägst Du in das zweite Array ein und erhöhst dabei die zweite Zählvariable um eins. Am Ende hast Du dann im zweiten Array die Indizes der aktiven LEDs und in der Zählvariable die Anzahl dieser aktiven LEDs. Nun mußt Du nur eine Zufallszahl zwischen 1 und dem Wert der Zählvariable bestimmen und mit diesem Wert die Nummer einer aktiven LED aus dem zweiten Array (led_a) ermitteln. Diese kannst Du dann schalten.

Nehmen wir nun an, Dein Schalter-Array sieht so aus: [1,0,0,1]
LED-Index = 0
ledaktiv = 0

Schalter 1 ist aktiv, daher wird er an der ersten Stelle im zweiten Array eingetragen (led_a: [1,0,0,0]) und Zähler erhöhen (ledaktiv=1)
LED-Index = 1 (nächsten Schalter prüfen)
Schalter 2 ist nicht aktiv, daher wird er "ignoriert"
LED-Index = 2 (nächsten Schalter prüfen)
Schalter 3 ist nicht aktiv, daher wird er "ignoriert"
Schalter 4 ist aktiv, daher wird er an der zweiten Stelle im zweiten Array eingetragen (led_a: [1,4,0,0]) und Zähler erhöhen (ledaktiv=2) ACHTUNG!! Hier wird an der zweiten Stelle der Index des aktiven Schalters eingetragen, daher die 4.

Würde Dein Schalter Array so aussehen: [1,1,0,1] würde Dein zweites Array nach dem Prüfen so aussehen led_a: [1,2,4] und ledaktiv hätte den Wert 3.

Um nun zufällig einen Wert auszuwählen, ermittelst Du einen Zufallswert von 1 bis "ledaktiv" und verwendest den als Index für das zweite Array (Achtung 1 abziehen, da in Arrays von 0 an gezählt wird).
z = random(1,ledaktiv);
led = led_a[z];

Im Grunde erzeugst Du Dir immer wenn sich bei den aktivierten LEDs etwas ändert eine neue Liste von nur den aktivierten LEDs aus denen Du dann wieder zufällig eine auswählst.

Eine wichtig Sache musst Du natürlich auch beachten, wenn eine LED deaktivert wird, sollte sie zusätzlich explizit ausgeschaltet werden, da sie ja durchaus zufälligerweise an sein kann und das dann bleiben würde, da sie ja nicht weiter beachtet wird.

Ich hoffe das war einigermassen verständlich.

Mario.

jurs


Aber die Random Funktion verlangt ja eine (min, max-1) übergabe, wie kann ich mein Vorhaben jetzt realisieren?


Durchzählen, wie viele LEDs aktiv in der Auswahl sind und für das Blinken in Frage kommen. Zufallszahl x aus der ermittelten Anzahl bilden. Und dann wieder durchzählen und die x-te aktive LED einschalten, alle anderen aus.

Code: [Select]


// Alle LED Pins:
byte allLEDpins[]={3,4,6,7,8,9,10};

// An welchen LED Pins soll geblinkt werden:
boolean activeLEDs[sizeof(allLEDpins)]={true,false,true,false,true,false,true};


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for (int i=0;i<sizeof(allLEDpins);i++)
    pinMode(allLEDpins[i],OUTPUT);
}

void ZufallsLED()
{
  byte led,anzahl=0;
  // Erstmal feststellen wie viele LEDs aktiv in der Auswahl sind:
  for (int i=0;i<sizeof(allLEDpins);i++)
    if (activeLEDs[i]==true) anzahl++;
  // Zufallszahl zwischen null und anzahl bilden 
  led=random(0,anzahl);
  // in "led" steht nun, die wievielte aktive LED blinken soll
  anzahl=0;
  // Und nun nur unter den aktiven LEDs feststellen, welche ein sein soll
  for (int i=0;i<sizeof(allLEDpins);i++)
  {
    if (led==anzahl && activeLEDs[i]==true) // Treffer!
    {
      digitalWrite(allLEDpins[i],HIGH);
      Serial.print("Blinken an Pin: ");Serial.println(allLEDpins[i]);
    }
    else
    {
      // alle anderen LEDs aus
      digitalWrite(allLEDpins[i],LOW);
    }
    if (activeLEDs[i]==true) anzahl++;
  } 
}

void loop() {
  // put your main code here, to run repeatedly:
  ZufallsLED();
  delay(1000);
}


Ob eine LED zufällig mitblinken oder dauernd aus sein soll ergibt sich daraus, ob sie im Array "activeLEDs" auf true oder false gesetzt ist.

michael_x

Quote
Ein Eleganter Weg wäre vermutlich etwas komplizierter.

Ein schöner Widerspruch in sich. Wenn es eine einfache und eine komplizierte Lösung gibt, ist die einfache immer die "elegante", finde ich.

Und selbst wenn es verschiedene Optimierungsrichtungen gibt, ist meist klein besser als schnell.

Solange "würfeln" bis ein passender Wert kommt, ist eine gute (die beste) Methode, finde ich.

Man sollte eventuell drauf achten, dass die Liste der passenden Werte (jurs' konstantes activeLED array) sich aktualisiert beim wiederholten Würfeln, um den Sonderfall, wenn es gar keinen passenden Wert gibt, gleich mit zu erschlagen.

Schön, dass "endlos warten bis sich etwas ändert" ein normaler Betriebszustand eines µC ist.

franky27

Danke Euch allen für die Hilfe, habe es nun wie geraten mit Hilfe eines `Status`arrays gelöst und es funktioniert alles bestens. Toll wie schnell und ausführlich Ihr geholfen habt!
Gruß
franky

Go Up