Struktur gesucht, aber (noch) nicht gefunden :(

Hallo miteinander,

ganz kurz zu mir: Ich habe einen riesen Fehler gemacht. Habe mal ziemlich erfolgreich mit Arduino und Co. gearbeitet, und fand mich ziemlich fit (ging seinerzeit bis hin zu meinem RFID-Türöffner mit Programmier- und Lernmodus etc., der heute sogar noch an meiner Haustür hängt, Ja, ich habe meiner Programmierkenntnis echt vertraut :) nd das Ding tuts sogar noch. ). Dann habe ich einen bemerkenswerten Fehler begangen: mit der Programmiererei eine ziiiiiemlich lange Pause gemacht. :(

So, nun sitze ich hier in meiner Bastelbude mit einer echt geilen Idee, genügend Spielgeld, etwas mehr Zeit wie sonst, ABER: ich krieg´s einfach nicht mehr hin. (und damit meine ich jetzt nicht "Blink" ;) )

Zu meiner Idee: Für die Hobby-Disco meines 10 jährigen Sohnemanns soll ein siebenköpfiger Moving-Head (Licht-Show) entstehen. Mit je einem Pan- und einem Tilt-Servo pro "Kanal", richtig fetten Power-LEDs, vorprogrammierten Lauflichtvarianten, sowie einem aktivierbaren Musik-Licht-Modus für Frequenz-Teilung der Musik (mithilfe des MSGEQ7), also sowas ähnliches wie die gute alte Lichtorgel :)

Gesteuert wird das ganze selbstverständlich über eine Infrarot-Fernbedienung. Programm, Geschwindigkeit, etc.

Einzelne Komponenten, wie Servos in langsamer oder schneller Geschwindigkeit laufen lassen (mit Hilfe der VarSpeedServo.lib) oder IR-Signale auslesen klappt nach wie vor. An switch/case/break arbeite ich schon wieder. Klappt hoffentlich bald. :slightly_smiling_face:

Beim definieren von verschiedenen Lauf-Mustern für die sieben LEDs hakt es schon eher. Früher habe ich solche Späße mal auf einem LCD-Display gemacht, würde ich heute nie mehr hinkriegen :( Möchte gerne diese Laufmuster in verschiedene Stringketten (hießen die so?) schreiben, und über die IR-Fernbedienung abrufen und laufen lassen, bis ein anderer IR-Befehl kommt. Servospeed und Lightspeed wären dann auch per IR zu steuern. (Quasi stellt man das Ding auf´n Schrank und jut is'.)

Dazu natürlich auch dann verschiedene Bewegungsmuster für die Pan und Tilt Servos. Die einfach nur über random-Werte rumzappeln lassen reicht mir irgendwie nicht. (das habe ich beispielsweise allerdings noch hinbekommen :grin: :grin: )

Ordentliche Stromversorgung ist da, und über die Tatsache dass das nur mindestens mit einem Mega geht bin ich mir aufgrund der Servo-Anzahl (14 Stück :smiling_imp: ) schon ziemlich bewusst.

Jetzt das Problem. Das muss alles verschachtelt bzw. ordentlich in Funktionen aufgeteilt werden. Kann natürlich meine Servos laufen lassen, aber dann läßt sich der IR-Empfang nichts sagen weil die angesteuerte Position noch nicht erreicht ist. :confused: Und an ein Lauflicht ist da ja auch noch nicht zu denken, weil der blöde Sketch ja immer noch da "hängt"

Wie ging das noch mal? Über millis() habe ich zwar noch mal nachgedacht, aber das war es doch nicht.

Da muss also jetzt ziemlich viel "parallel" laufen. Gibt es da Tips oder Kniffe, die mir das Leben etwas vereinfachen könnten? Hier sind doch bestimmt noch reichlich erfahrene Leutz, die mir mal wieder in meine frühere heile Welt zurückhelfen könnten. :disappointed_relieved:

Würde mich wahnsinnig freuen.

Danke schon mal für alles was jetzt kommt! Schönen Abend! Grüße, KuTTi

So pauschal kann ich Dir nur empfehlen, den Code für die einzelnen Ausgänge (Licht, Servos) in Unterprogramme zu packen, die dann der Reihe nach in loop() aufgerufen werden.

Dein Ansatz mit millis() war schon der richtige.

Wenn mehrere Sachen "parallel" laufen sollen, solltest (musst) du auf jegliche Delays verzichten. Und da bleiben dir dann die millis() ;)

Schau dir nochmal das Beispiel von BlinkWithoutDelay an. Das sollte dir schon mal weiter helfen.

Grüsse Peter

wie verwirklichst du die Wartezeit der Servos nach den einzelnen Schritten?

Zerlege Dein komplexes Problem erstmal in viele kleine Teilprobleme. Z.B. Mechanik, Servokommunikation, LED Ansteuerung, LED Software, Soundreaktivität, IR Steuerung, usw. Dann eins nach dem anderen lösen, mit der vorherigen Problemlösung kombinieren und ggf. entstehende neue Probleme lösen.

Wenn viel "parallel" passieren soll, geht das nur durch konsequenten Verzicht auf alle Delays.

Mit LED Effekten habe ich ziemlich viel Erfahrung, deshalb möchte ich hierzu

Beim definieren von verschiedenen Lauf-Mustern für die sieben LEDs hakt es schon eher. Früher habe ich solche Späße mal auf einem LCD-Display gemacht, würde ich heute nie mehr hinkriegen :( Möchte gerne diese Laufmuster in verschiedene Stringketten (hießen die so?) schreiben, und über die IR-Fernbedienung abrufen und laufen lassen, bis ein anderer IR-Befehl kommt.

anmerken: Ein wie auch immer organisiertes abspeichern und späteres abrufen von kompletten Animationen hat immer eins von 2 Problemen: Entweder

  • die Animation ist sehr "grob" also große Unterschiede zwischen den Frames = eine hüpfende und tetrisartige Animation, oder

  • der Speicherbedarf ist exorbitant hoch.

Lösung: die Animationen werden in Echtzeit berechnet mit so vielen Zwischenschritten, wie nur irgendwie möglich. Du speicherst also keine Wertetabellen, sondern beschreibst den gewünschten Funktionsverlauf mit Formeln. Da kann man sehr komplexe Sachen bauen, selbst wenn man erstmal nur 3 Sinuswellen mit unharmonischen Frequenzen kombiniert.

Kannst ja zum Ideen bekommen mal anschauen, was ich mit LEDs gemacht habe. Alles in Echtzeit auf dem Mikrocontroller berechnet.

Ob am Ende mit den berechneten Werten eine Helligkeit oder eine Farbe oder ein Tilt-/Panwinkel gesteuert wird, ist erstmal egal. Da fängt dann die Kreativität an, wie man Sachen attraktiv kombiniert.

Soundreaktive MSGEQ7 Animationen sind bei meinen Videos auch dabei. Dieser Chip ist immer noch "state of the art", wenn es um schnelle externe Spektralanalyse geht.

Ich würde einen TEENSY oder mindestens einen Arduino Due nehmen, damit ich mit RAM und Rechenpower nicht sofort am Limit bin.

Gruß,

Helmuth

Nachtrag: Hier werden die RGB Werte von 1024 LEDs - also 3072 8 Bit Werte in Echtzeit berechnet.

Ich beschreibe alles mit Formeln welche durch circa 50 verschiedene Parameter gesteuert werden. Ob man diese Parameter dann mit fixen Eingabewerten, oder auch wieder mit Funktionen steuert (z.B. Winkelfunktionen oder Rauschfunktionen), oder von Audioinput abhängig macht, oder zufällig festlegt, ist nur von der Phantasie begrenzt.

Im Ergebnis sind es immer neue komplexe Lichteffekte und ab einem gewissen Punkt, kann man da ewig zuschauen, wie sich die Animation selbst steuert, wenn man Abhängigkeiten logisch geschickt verknüpft hat.

Nachtrag 2:

Lauf-Mustern für die sieben LEDs

Wenn wir über europäische (Tanz)Musik sprechen, machen Vielfache von 4 oder 8 Sinn, um harmonische Animationen im Takt der Musik zu erzeugen.

Bei westafrikanischer Trommelei im 7/13 Takt mag das anders sein.

Wow, ich bin ja begeistert, was da jetzt schon an Antworten gekommen ist - Das muss ich mir dann am Wochenende mal genauer durchlesen. Vielen Dank schon mal!!

Könnte ja doch noch was werden mit meinem Projekt! Danke!

Hallo zusammen,

nach ziemlich langer Krankheit kann ich mich endlich mal wieder um meine Disco kümmern. Allen, die hierzu ihre Hilfe bereits angeboten haben, schon mal vielen Dank!

Nun bin ich schon eine Ecke weiter. Meine LEDs fahren schon ihre ersten Muster, die ich auch mit meiner IR-Fernbedienung nach Belieben zünden kann. :slight_smile: Auch die Geschwindigkeit meiner Licht-Effekte läßt sich per IR steuern. Alles soweit kein Akt. Nun aber kurz zum Ablauf:

Ich definiere bytes mit meinen Lauflicht-Mustern: (nur ein Beispiel von allen)

byte Muster2[] ={
  B100001,
  B010010,
  B001100,
  B111111,
  B100001,
  B001100,
  B010010,
  B100001,
  B010010,
  B101101};

… warte innerhalb meines loop() auf entsprechendes IR-Signal:

if (irrecv.decode(&results) == true )
  {
    if (millis() - last > 250)
    {
      last = millis();
      irrecv.resume();
    }
  }

… und entscheide, was aufgerufen wird:

switch(results.value)
{
 case 16738455: // STOP! Alles aus!
        for (int i = 0; i<6; i++)  // Alle LEDs ab!
        {digitalWrite(ledpin[i], LOW);}
        panservo[0].detach() ;  // alle Servos ab! 
        panservo[1].detach() ;
        prog =0;
      break;
 case 16724175:
        prog=2;
        break;
 case 16718055:
        prog=3;
        break;

... usw.

wobei die Werte 167…etc. die empfangenen IR-Signale sind.
die Variable “prog” bleibt ohne neues IR-Signal gleich und nun geht es innerhalb der loop() immer brav weiter mit dem entsprechenden Aufruf der Unterroutine:

  if (prog==2){light(Muster2);}
  if (prog==3){light(Muster3);}
  if (prog==4){light(Muster4);}
  if (prog==5){light(Muster5);}
  if (prog==6){light(Muster6);}  
  if (prog==7){light(Muster7);}


void light(byte * prog)
{
  
  for (int row = 0; row<10;row++)
  {
    unsigned long start=millis();
    
    while (start + pause > millis()) 
    {

      for (int column = 0; column <8; column++)
      {
      //  int cPos = panservo[0].read();
      //  Serial.println(cPos);
        boolean pixel = bitRead(prog[row],column);
        {
          if (pixel ==1) {
            digitalWrite(ledpin[column], HIGH);
          }
          else 
          {
            digitalWrite(ledpin[column], LOW);
          }
        }
      }
    }
    start = millis();
  }

}

Was ich natürlich jetzt erst merke, dass ich mich selbst blockiere :frowning:
Denn nun wollte ich meine 6 PAN- und die 6 TILT-Servos einbauen und “tanzen” lassen. :smiley: Klappt aber gar nicht, weil mein void light(…) erst nach den kompletten 10 Reihen vom übergebenen byte erst zur loop() zurückkehrt, und jegliche Versuche, ein Servo (auch langsam mit Hilfe von millis())) laufen zu lassen, sowas von in die Hose geht. :confused:

Ich wollte dazu mal Eure Meinung hören, aber ich fürchte, ich bin da schon komplett auf dem Holzweg, richtig?

Wie schon im Topic angeführt, ich fürchte bei mir scheitert´s einfach wieder nur an der Struktur, richtig?

:confused:

Ich habe den Sketch mal angehängt, aber bitte beachten: Er ist noch in der Entstehung, also Zimmer ist noch nicht aufgeräumt, Mami. Später, versprochen! :blush:

LED_Muster_mit_IR_und_Bytes_case_.ino (3.36 KB)

Da parallele Abläufe hardwaremaßig nicht unterstützt werden, müssen sie sequentialisiert werden. Du mußt also festlegen, wann der nächste Vorgang ausgeführt werden soll, und dann diese Liste abarbeiten.

Wobei Listen garnicht implementiert werden müssen. Wenn alle quasi-parallelen Abläufe in eigene Unterprogramme gepackt werden, und alle diese Unterprogramme der Reihe nach in loop() aufgerufen werden, dann funktioniert das schon. Jedes Unterprogramm schaut dann nach, ob schon etwas zu tun ist, und macht das dann auch oder kehrt sofort zurück.

Was mir aufgefallen ist, dass das light(Muster"x") zwar in einem Unterprogramm läuft, aber der Sketch trotzdem "pausiert". Anfangs der loop() habe ich mit Serial.print("Schritt"); mal getestet, wie oft die loop() oben wieder anfängt. Erschreckenderweise kommt das "Schritt" immer erst, nachdem ein Laufmuster komplett durch ist. :(

Das hatte mich wie gesagt ziemlich gewundert.

Dreh Deine Logik um ;-)

Wenn in light() die Wartezeit noch nicht abgelaufen ist, dann spring aus dem Unterprogramm gleich wieder raus, statt andere Abläufe durch Warten zu blockieren.

  if (prog==2){light(Muster2);}
  if (prog==3){light(Muster3);}
  if (prog==4){light(Muster4);}
  if (prog==5){light(Muster5);}
  if (prog==6){light(Muster6);}  
  if (prog==7){light(Muster7);}

Sowas schreit gerade dazu danach aus den Mustern ein zwei-dimensionales Array zu machen :)

Zum Thema Blinken gibt es hier jede Menge Anregungen: http://blog.blinkenlight.net/experiments/basic-effects/pov-reloaded/

Und wie man Dinge mit Hilfe von Koroutinen pseudoparallelisiert trete ich hier breit: http://blog.blinkenlight.net/goto-considered-helpful/