Prozeduren zeitlich unabhängig von einander starten

Hallo, ich möchte einige Prozeduren zeitlich unabhängig von einander starten.

Es sollen LEDs per fade ein und wieder aus geschaltet werden.
Allerdings wird im Quellcode Job_1 erledigt und dann erst Job_2. Nicht parallel wie ich das gerne hätte.
Blink_without_delay ist wohl nicht das was ich brauche. Hat jemand Ratschläge?

void loop() {

 unsigned long currentMillis = millis();


 if (currentMillis - previousMillis >= interval_1) {
    // save the last time you blinked the LED
 //   previousMillis = currentMillis;
   
  job_1(); 
 }
  if (currentMillis - previousMillis >= interval_2) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
   
  job_2(); 
 }
 }

//hier mal der Job_1--------------------------------------------
void job_1(){
   // fade in from min to max in increments of 5 points:
  for (int fadeValue = 5 ; fadeValue <= 255; fadeValue += 1) {
   for (uint8_t j = 0 ; j <= 2 ; j++ ){
       analogWrite(out_LEDs_gruppe_1_1[j], fadeValue);
       
   
    delay(30);
  }
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 5; fadeValue -= 1) {
   for (uint8_t j = 0 ; j <= 2 ; j++ ){
       analogWrite(out_LEDs_gruppe_1_1[j], fadeValue);
       

    delay(30);
  }
  }

}

Mit Prozeduren meinst du sicher die Funktionen.
Das geht schon mit millis, du kannst es aber auch mit "simpleTimer.h" versuchen.
Ich habe damit gute Ergebnisse erzielen können.

Hallo,

nur mal so zum Grundverständnis. :slight_smile:

Theseus erklärt millis()

Danach kannste meinetwegen jede Lib nehmen die dir zu sagt.

Zum Verstehen würde ich erstmal nicht nach passenden Libraries suchen.

Wenn du denkst, du hast "millis()" verstanden, bau das BlinkWithoutDelay StandardBeispiel auf Fade statt Blink um. Ohne for Schleifen.

Dann lerne, BlinkWithoutDelay auf zwei unabhängige Leds zu erweitern. ( Was muss verdoppelt werden? )

Dann wende das auf dein Fade an.

Wenn du unter Prozedur eine Funktion verstehst, die erst aufhört, wenn sie fertig ist:
TOTAL FALSCHER ANSATZ :wink: 8) :stuck_out_tongue:

Wenn loop() zig mal je millisekunde drankommen soll (und das ist eigentlich kein Problem), muss jede darin aufgerufene Funktion sich natürlich auch sofort beenden.

Ablaufsteuerung
Meine Standardantwort zu Ablaufsteuerungen:
Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay,

Blink Without Delay
Der Wachmann

Multitasking Macros
Intervall Macros

dr_jack:
… Hat jemand Ratschläge?

Da der Sketch IMO schlecht lesbar und nicht vollständig ist, habe ich mir verkniffen, einen genauen Blick darauf zu werfen. Allerdings kam der Hinweis auf einen endlichen Automat. Vor ungefähr vier Wochen habe ich mich hierzu ausgelassen und das hier ins Netz gekippt. Vielleicht ist das hilfreich. Wenn ja, lies auch den folgenden Abschnitt.

Gruß

Gregor

Ich finde die "Wachmann"- Erklärung sehr anschaulich und einleuchtend... vielleicht bekommt man es nicht sofort in einen Sketch umgesetzt- wenn man aber nach Lesen des "Wachmann" seinen zeitlichen Verlauf auf ein Blatt skizziert erkennt man schnell wie es laufen soll...

Im Prinzip machst du über millis() deinen zeitlichen Rythmus- und davon abhängig steuerst du dann eben deine Abläufe- also wenn der von dir definierte Intervall abgelaufen ist machst du die LED um eine Stufe heller... natürlich nur bis das max erreicht ist...

Rein theoretisch könnte ich dir eine fertige Lösung geben- da ich auch viele Anwendungen haben wo LEDs gedimmt werden... aber probier es mal erst selbst um es zu verstehen...

Und du bindest den Arduino in den for-Schleifen fest die dann auch noch ein Delay enthalten. Selbst wenn der Rest deines Codes gehen würde sind die for schleifen falsch.
Der millis() Ansatz ist der richtige musst ohne ber auch konsequent nutztenund nicht doch noch das Delay reinpacken.
For Schleifen musst du auch vermeiden.
Hier wird dir keiner fertigen Code liefern, aber schnell geholfen. Ich denke es sind schon einige gute Tips und Ansätze gekommen, jetzt bist du dran.
Gruß
DerDani

Ich liebe für solche Art Nebenläufigkeiten die Lib INTERVAL.h, ein großer Vorteil bei der ist, dass man das Zeitintervall zur Laufzeit ändern kann, wenn man es als globale Variable anlegt. Also z.B. könnte man per Poti die Dimmgeschwindigkeit ändern.

Du solltest aber zuerst lernen, wie es mit millis geht, bevor du solche Komfortlibs benutzt.

Hallo,
egal welcher Prozessor oder Programmiersprache verwendet wird, es ist nicht möglich, dass ein Prozessor zwei Anwendungen gleichzeitig ausführen kann. Selbst, wenn man wie unter Windows üblich, Anwendungen über "Treads" startet, muss ein laufender Tread unterbrochen werden, wenn ein anderer ausgeführt wird.
Gruß MKch

Mkch:
Hallo,
egal welcher Prozessor oder Programmiersprache verwendet wird, es ist nicht möglich, dass ein Prozessor zwei Anwendungen gleichzeitig ausführen kann. Selbst, wenn man wie unter Windows üblich, Anwendungen über "Treads" startet, muss ein laufender Tread unterbrochen werden, wenn ein anderer ausgeführt wird.
Gruß MKch

Ja!
Und?

Wie sieht die Lösung dieses Dilemmas aus?

Wie beim Essen- Häppchenweise... erst ne Erbse, dann ein Stück Kartoffel, dann ein Stück Fleisch... man kann auch für jedes Häppchen unterschiedlich lange Kauzeiten realisieren...

Wie beim Essen

Zähne putzen, essen, trinken, reden, singen .....

muss ein laufender Tread unterbrochen werden

?? Interrupt ??

Also 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann 1sek Zähne putzen, dann 5sek essen, dann 7sek trinken, dann 2sek reden, dann 15sek singen, dann ?????

Iiiiiiiiiiiiiiiiihhhhhhhhhhhhh!!!!

Ich kann nur raten:
Erst mit dem singen zu beginnen, wenn der Bissen geschluckt wurde.
Also einfach mal so "unterbrechen und nächster Job" funktioniert nicht.

1 sek Zähneputzen, dann 5 sek essen, dann 7 sek trinken...

...vermittelt ein falsches Bild.

Mal abgesehen davon, dass die übliche Geschwindigkeit eines Arduino 100tausend mal schneller ist ( 10 µs Zähneputzen :wink: : Der Hauptfehler an dem Vergleich ist, dass es komplett egal ist, wie kurz die "Zähneputzen" Zeitscheibe ist.

Es geht nur darum: Ist Zähneputzen fertig? Nein: ist die Bürste am Anschlag? Nein: ok, Bürste weiter bewegen. (Bei anderen Statusabfrage-Ergebnissen ergeben sich evtl. andere Reaktionen, aber meistens macht der Arduino nichts anderes, als zu merken dass nichts zu tun ist, und wenn doch, macht er nichts was wirklich Zeit kostet. Ob also ein Durchlauf "Zähneputz-Prozedur" 10 oder 100 oder 500 µs dauert, macht im Ergebnis keinen Unterschied, und Zähneputzen und Essen läuft faktisch gleichzeitig ab. (Wenn das so gewünscht ist). Auch mit nur einem einzigen Prozessor.

Damit (zurück vom Zähneputzen zu den LED) das Faden schön langsam geht, sollte der Arduino also meist nur prüfen, ob endlich eine oder genug Millisekunden vergangen sind und gegebenenfalls den Wert für das zugehörige analogWrite anpassen.