Mehrere Sensoren, Motoren usw. gleichzeitig betreiben. Nur wie?

Hallo, arbeite an einem kleinen bzw. eigentlich doch schon größeren^^ Schulprojekt (kleines Arduino-gesteuertes Auto). Der Hauptteil der Arbeit lief bisher in die Programmierung einer kleinen GUI für Windows. Nun bin ich so langsam am Arduino angekommen. Ich habe schon die Schrittmotorenansteuerung, Servo-, Ultraschallsensoren- usw. getestet.. allerdings mit dem Lernset von Fritzing wo leider meist nur einzelne Module angesteuert werden. Nun steh ich vor dem Problem dass ich relative viele Module gleichzeitig ansteuern muss und einige davon eine gewisse Zeit benötigen (wie z.B. die Abstandsmessung mit Ultraschall benötigt schon wenige Millisekunden). Iwie muss nun aber eben alles gleichzeitig funktionieren. Heißt es sollen durchgehend Abstandsmessungen durchgeführt werden, 3 Schrittmotoren jederzeit ansteuerbar sein, ein LCD Display aktuelle Messdaten ausgeben, eine Bluetooth Verbindung aufrecht gehalten werden und in kurzen Zeitabständen anfallende Daten zum PC übertragen werden.. usw. Nur wie löst man so ein Problem am besten. Mir geht es weniger um Code/Sketches sondern viel mehr um Hilfreiche Tipps was ich mir dazu mal durchlesen kann. Momentan weiß ich noch nicht einmal wonach ich suchen muss um Informationen zum Lösen dieses Problems zu finden. Erste Idee die ich hatte war, dass ich alles "modulartig" programmiere... also jeder Schrittmotor, Ultraschallsensor usw. als Modul in einer Art "eigenem Thread" laufen lasse. Jeder Thread würde dann einfach nur eine kurze Rechenzeit bekommen. Das Problem ist hier aber schon, dass Ultraschall eben mehr als nur wenige MikroSekunden benötigt und somit schon das Modulkonzept nicht mehr ganz funktionieren würde wenn verschiedene Module zu lange brauchen (die Schrittmotoren würden zu lange warten müssen und das Auto fährt somit sehr ruckweise) . Wie bzw. mit welchem "Konzept" löst man so ein Problem?

Wie bzw. mit welchem "Konzept" löst man so ein Problem?

Hmmm... Dann werde ich dir mal ein paar Stichworte liefern...

Cooperatives Multitasking. (in vereinfachter Form) Ein Anfang: http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay Also der konsequente Verzicht auf langlaufenden Delays. Evtl wären die ProtoThreads was für dich.... um viele Dinge quasi parallel ablaufen zu lassen.

Konsequent auf endliche Automaten setzen. (Finite State Machines) Gibt im Forum schon einige Threads dazu.

Der Abstandssensor könnte z.B. beim eintreffen des Echos einen Interrupt auslösen. Und überhaupt, über Timer und Interrupts lässt sich viel parallelisieren.

Die Rückantwort mehrerer Ultraschall-Sensoren (per Interrupt ?) ist vermutlich schwierig. Da solltest du aber bedenken, dass das wegen gegenseitiger Beeinflussung vermutlich sowieso nicht gleichzeitig geht. Im übrigen wäre ein Gefühl für den Unterschied zwischen µs und ms hilfreich. Schrittmotoren "ruckeln" immer, das ist ihr Funktionsprinzip. ;)

Aus dem Einstieg "BlinkWithoutDelay" solltest du lernen, dass ein loop() Durchlauf die Funktionalität während eines Zeitpunkts beschreibt, und du nur dafür sorgen musst, dass der Zeit"punkt" nicht zu lange dauert. Dann kannst du alles quasi gleichzeitig erledigen.

Der Schritt von den Beispielen für einzelne Sensoren zu einem Projekt mit mehreren Aufgaben gleichzeitig ist tatsächlich nicht so einfach. Da ich von der Modellbahn zu Arduino gelangt bin, habe ich mit einer Ampelschaltung abgefangen, schön mit delay() dazwischen. Dann wollte ich noch unabhängig zwei LEDs blinken lassen. Daher mußte delay() raus und millis() rein. Später habe ich dann auch noch for-Schleifen etc. als möglicherweise blockierend entdeckt. Irgendwann setzte sich dann bei mir die Erkenntnis durch, loop() müsse möglichst schnell durchlaufen werden, damit die unterschiedlichen Aufgaben quasi parallel abgearbeitet werden können.

An einer Stelle ist mir das mal nicht gelungen, da bin ich dann auf einen zweiten Prozessor (ATtiny85) ausgewichen.

Schaut Euch mal den Sketch in diesem Beispiel an, da werden auch verschiedene Aufgaben quasi gleichzeitig und in verschiedenen Dateien aufgeräumt abgelegt abgearbeitet.

agmue: Schaut Euch mal den Sketch in diesem Beispiel an, da werden auch verschiedene Aufgaben quasi gleichzeitig und in verschiedenen Dateien aufgeräumt abgelegt abgearbeitet.

Ja, eine witzige Sache!

Gefallen tut mir das aufgeräumte Schrittkettenkonzept.

Weniger gefällt mir, dass alles in einen 1ms Interrupt gequetscht wird. Und über die Massen an #define kann man ja sowieso streiten.

Danke für die Anregung.

combie:
Danke für die Anregung.

Gerne doch!

Schau doch bitte auch noch auf mein Programm für die Ampel mit Blinklicht parallel, ob das als Beispiel zu dieser Fragestellung paßt.

void loop() {
  // Blaulicht
  if (millis() > blauMillis + 750) {
    blauMillis = millis();
    digitalWrite(blau_1, ein);
    digitalWrite(blau_2, aus);
  }
  if (millis() == blauMillis + 50) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, aus);
  }
  if (millis() == blauMillis + 100) {
    digitalWrite(blau_1, ein);
    digitalWrite(blau_2, aus);
  }
  if (millis() == blauMillis + 150) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, aus);
  }
  if (millis() == blauMillis + 500) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, ein);
  }
  if (millis() == blauMillis + 550) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, aus);
  }
  if (millis() == blauMillis + 600) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, ein);
  }
  if (millis() == blauMillis + 650) {
    digitalWrite(blau_1, aus);
    digitalWrite(blau_2, aus);
  }
  //
  // Ampelschaltung
  if (millis() > ampelMillis) {
    switch (zustand) {
      case ROT:
        digitalWrite(ampel_1_RotPin, ein);
        digitalWrite(ampel_1_GelbPin, aus);
        digitalWrite(ampel_1_GruenPin, aus);
        digitalWrite(ampel_2_RotPin, aus);
        digitalWrite(ampel_2_GelbPin, aus);
        digitalWrite(ampel_2_GruenPin, ein);
        zustand = ROTGELB;
        ampelMillis = millis() + ZEITROTPHASE;
        break;
      case ROTGELB:
        digitalWrite(ampel_1_RotPin, ein);
        digitalWrite(ampel_1_GelbPin, ein);
        digitalWrite(ampel_1_GruenPin, aus);
        digitalWrite(ampel_2_RotPin, aus);
        digitalWrite(ampel_2_GelbPin, ein);
        digitalWrite(ampel_2_GruenPin, aus);
        zustand = GRUEN;
        ampelMillis = millis() + ZEITGELBPHASE;
        break;
      case GRUEN:
        digitalWrite(ampel_1_RotPin, aus);
        digitalWrite(ampel_1_GelbPin, aus);
        digitalWrite(ampel_1_GruenPin, ein);
        digitalWrite(ampel_2_RotPin, ein);
        digitalWrite(ampel_2_GelbPin, aus);
        digitalWrite(ampel_2_GruenPin, aus);
        zustand = GELB;
        ampelMillis = millis() + ZEITROTPHASE;
        break;
      case GELB:
        digitalWrite(ampel_1_RotPin, aus);
        digitalWrite(ampel_1_GelbPin, ein);
        digitalWrite(ampel_1_GruenPin, aus);
        digitalWrite(ampel_2_RotPin, ein);
        digitalWrite(ampel_2_GelbPin, ein);
        digitalWrite(ampel_2_GruenPin, aus);
        zustand = ROT;
        ampelMillis = millis() + ZEITGELBPHASE;
        break;
    }
  }
}

Test_Forum.ino (3.39 KB)