Arduino UNO Multitasking

Hallo erst mal,

Ich bin dabei eine Zeitraffer-Steuerung zu realisieren.
Controller ist ein UNO mit LCD-Keypad shield.
Es muss ein Stepper angesteuert werden, der die Kameraplattform dreht, zeitgleich wird ein trigger-Signal an die Kamera geschickt und das Display muss in Echtzeit die Restzeit, und die aktuelle Fotozahl anzeigen.
Folglich habe ich 3 verschiedene Zeitfunktionen (und bei 2 davon muss das Display angesteuert werden).
2 Funktionen werden durch Timer-Interrrupts getimed, die Ansteuerung des Steppers durch ein variable Delay.
Funktioniert aber nicht richtig, mein Programm kann nicht mehr Fotos machen wie Stepper-Schritte.
Zudem wird bei langsamer Umdrehung nicht im Sekundentakt gezählt.

Nun zur Frage:
Verlange ich zu viel von einen UNO?
Wenn nicht, wie kann ich mein Problem lösen? (sind 3 timer interrupts möglich?)

Folgendes Projekt habe ich als Basis verwendet und nach meinen Ansprüchen verändert.

http://markwheeler.com/wordpress/?p=381

Ich habe leider so gut wie keine Ahnung vom programmieren, letztes mal war vor 4 Jahren in der Schule
und ich war nicht der Beste :wink:
Daher verzeiht bitte etwaige sinnlose Coddeabschnitte und schlechte Fomatierung :sweat_smile:

Mein Code im Anhang:

Gruß
David

Timelapse_Panner.ino (11.7 KB)

Beim Arduino gibt es kein Multitasking.
Du mußt die Sachen nacheinander machen. Vergiß delay() benutze millis().
Grüße Uwe

bigbluecoconut:
Verlange ich zu viel von einen UNO?

Jein. Wie Uwe schon schrieb: Vergiss delay(). Nimm millis() und einen „endlichen Automat“. Evtl. hilft ja mein Geschreibsel dazu.

Gruß

Gregor

Ersetze alle delays durch das Zählen und Vergleichen der millis() und alles wird laufen wie du es brauchst... ganz kurz umrissen kann das so aussehen:

void setup()
{ }

unsigned long UpdateIntervall1 = 1000; // ruft die Aktion1() alle 1s auf
unsigned long letztesUpdate1;

unsigned long UpdateIntervall2 = 5000; // ruft die Aktion2() alle 5s auf
unsigned long letztesUpdate2;

unsigned long UpdateIntervall3 = 250; // ruft die Aktion3() alle 250ms auf
unsigned long letztesUpdate3;

void loop()
{
  if (millis() - letztesUpdate1 > UpdateIntervall1) 
  {
    letztesUpdate1 = millis();
    Aktion1();
  }


  if (millis() - letztesUpdate2 > UpdateIntervall2) 
  {
    letztesUpdate2 = millis();
    Aktion2();
  }


  if (millis() - letztesUpdate3 > UpdateIntervall3) 
  {
    letztesUpdate3 = millis();
    Aktion3();
  }
}

Die Intervalle kannst du selbstverständlich jederzeit über irgendwelche Eingangsgrößen ändern.

Zu beachten wäre, dass diese 3 Intervalle zyklisch ablaufen, also immer wieder ohne Ende... Wenn du einen "Programm" oder eine Abfolge von Funktionen nur eine begrenzte Zahl ablaufen lassen möchtest mußt du "letztesUpdate" außerhalb der Schleife auf millis() setzen- denn innerhalb der Schleife wird es ja immer wieder "zurück" gesetzt.

Für regelmäßig wiederkehrende Abläufe habe ich ein every(ms) Makro geschrieben, das die Variablen etc. versteckt. Es kann auch ohne die Task-Makros verwendet werden. Ganz genau ist es nicht, dürfte aber im Rahmen der Abweichung von der Taktfrequenz bleiben.

Ich sehe gerade, die Beschreibung der ALib0 müßte mal überarbeitet werden...

Danke für die Hilfe,
Mittlerweile habe ich das Programm neu geschrieben um es ein bisschen übersichtlicher zu haben,
tatsächlich funktioniert es auch wie es soll. :smiley: :smiley: :smiley:

Jetzt muss nur noch ein Gehäuse gebastelt werden…

Gruß
David

Panner_Neu.ino (16.3 KB)

Du solltest das F() Macro an möglichst vielen Stellen benutzen.

Du solltest von der while/delay Programmierung abrücken.

Wenn alles so läuft wie es ist und nicht mehr geändert/erweitert werden soll,
lohnt sich allerdings der Aufwand nicht, es vernünftig zu programmieren,
es sei denn, man wollte das lernen.

@Whandall
Danke für den Hinweis :slight_smile:

Nur leider habe ich von F() Macro noch nie was gehört. :o
Soviel zu meinen Programmierkenntnissen. xD
Wie du sagst, es läuft, das reicht mir.
Es ist auch noch viel freier Platz auf dem Arduino.
Beim Programm fehlt nur noch die Steuerung für nen 2ten Stepper der die Kamera gegebenenfalls
an einem Seil durch die Gegend zieht, Timelapse Cablecam ftw. :wink:

Gruß
David

bigbluecoconut:
Nur leider habe ich von F() Macro noch nie was gehört. :o

Na dann kannst du ja z.B. Google sinnvoll einsetzen.

bigbluecoconut:
Beim Programm fehlt nur noch die Steuerung für nen 2ten Stepper der die Kamera gegebenenfalls
an einem Seil durch die Gegend zieht, Timelapse Cablecam ftw. :wink:

Das wäre meiner Ansicht nach ein Grund es vernünftig zu machen.
Deine while/delay Methode funktioniert nicht bei gewünschter Gleichzeitigkeit.

Beim ersten Programm habe ich noch mit delay gearbeitet,
Jetzt sitzt das gesamte "Drehprogramm" in einer while-Schleife...
Bei den Einstellungen ist es ja egal.

Gruß
David

Die while Schleife kann durchaus auch blockieren, in deinem Fall wird es später zum Hauptproblem werden.

Loop ist schon eine Schleife, nimm die