PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Multitasking



FancanTeik
21.04.2005, 19:20
Hallo,

wie fragt ihr eure Sensoren ab? Mit Multitasking oder immer wieder im Hauptprogramm?
Ohne Multitasking muss ich ja mein Programm in kleine Schritte zerlegen
und dazwischen immer den Sensor abfragen (z.B. den Bumper ob ich wo angestossen bin). Ist aber mehr als blöd zu programmieren.
Mit Multitasking kann ich mein Hauptprogramm einfach runterprogrammieren, der Sensor Task schläft und unterbricht mein
Hauptprogramm wenn er aktiviert wird. Der nachteil hier ist das Multitasking auf dem µController.
Wie macht ihr das so auf eurem Kontroller? Welche Reaktionszeiten braucht man für einen Roboter?

Fancan

JanB
21.04.2005, 20:07
Hallo,

dazwischen immer den Sensor abfragen (z.B. den Bumper ob ich wo angestossen bin)Sowas lässt sich auch mit Interrupts ganz gut behandeln.
Da braucht man nicht gleich einen Multitask-Kernel dazu.

Gruß Jan

ACU
21.04.2005, 20:15
Hallo!
Bei einem Bumper mag das ja funktionieren, aber wenn es um komplexe Signale geht (zum Beispiel Analogsignal), kommst du mit deinen Interrupts nicht weit (oder irre ich mich?).

Ich verwende ja die CC2, die standardmäßig mit Multitasking ausgestattet ist.
Ich würde sehr ungern darauf verzichten.
Geschwindigkeitsprobleme hatte ich bis jetzt keine.


MfG ACU

JanB
21.04.2005, 20:31
Auch der AD-Wandler liefert einen Interrupt,
wenn er mit der Wandlung fertig ist.
Da kann man dann entsprechend reagieren.

Ich behaupte nicht, das Interrupts das alleinseligmachende sind.
Aber je nach Aufgabenstellung kann Multitasking auch mit Kanonen
auf Spatzen geschossen sein.
Oder es frisst einem dringend benötigte Ressourcen weg.
Meist Rechen- oder Reaktionszeit, aber auch Speicherplatz.
Wenn du auf einem kleinen AVR mit 2KFlash und 128Byte RAM noch
mit Multitasking anfängst...

Wie gesagt, kommt darauf an was man womit machen will.

Gruß Jan

Felix G
21.04.2005, 20:39
Hallo!
Bei einem Bumper mag das ja funktionieren, aber wenn es um komplexe Signale geht (zum Beispiel Analogsignal), kommst du mit deinen Interrupts nicht weit (oder irre ich mich?).Wo ist das Problem?
Der ADC löst nach jeder Wandlung einen Interrupt aus, dann kann man die Daten erstmal irgendwie verarbeiten und danach läuft das Programm normal weiter.

Interrupts sind ein sehr wichtiges Werkzeug das einem der Prozessor bietet, und sie nicht zu benutzen ist Verschwendung.
Multitasking kann Interrupts nicht ersetzen!


Für die meisten Anwendungen würde ich empfehlen, zeitkritische und unvorhersehbare Sachen per Interrupt zu machen (dafür sind die ja da), und alle übrigen Funktionen einfach zyklisch aufzurufen.

21.04.2005, 22:00
Hallo,

Interrupts lösen das Problem nicht. Es ist richtig auch eine AD Wandlung kann einen Interrupt auslösen wenn sie fertig ist. Das ist aber nur die halbe Miete. Jetzt will ich ja z.B. beim Bumper eine Ausweichroutine fahren lassen (1sec zurück, 1sec mit einem Motor zur Kurve). Diese ganze Aktion (2 sec) kann ich aber nicht in der Interruptroutine laufen lassen ...

Fancan

Felix G
21.04.2005, 22:34
natürlich nicht, aber dafür braucht man noch lange kein Multitasking.

wie gesagt...
zeitkritische Sachen in Interrupts (und in den Interruptroutinen wirklich nur das notwendigste)
und den Rest ruft man bei Bedarf mit einer Art "ultra-primitiv-Taskmanager" auf.

Angenommen man kriegt über den ADC irgendein Signal das man zunächst mal filtern möchte um es dann irgendwie weiter zu verarbeiten.
Dann schreibt man in der ADC-Interruptroutine nur den gemessenen Wert irgendwo hin, und setzt dann ein Flag das signalisiert, daß ein neuer Wert da ist.
Im Hauptprogramm steht dann im Extremfall nurnoch eine Endlosschleife, in der die verschiedenen Funktionen aufgerufen werden.
(FlagXY gesetzt? -> Flag löschen und Funktion XY aufrufen)
In diesem Beispiel wäre dann halt das Flag das wir uns vorher für den ADC definiert haben gesetzt,
also würde bei der entsprechenden IF-Anweisung zunächst mal das Flag wieder gelöscht, und dann die Funktion aufgerufen die das Filter implementiert.


Ich behaupte mal, daß dieses Verfahren für die meisten Anwendungen absolut ausreichend ist. (und teilweise besser geeignet als echtes Multitasking)

Goblin
22.04.2005, 01:28
@felix: so wie ich das gerad verstanden hab, meinst du, dass wenn ein interrupt erfolgt, im hauptprogramm eine schleife aufgerufen wird, die eine bestimmte aktion aufruft (wenn nicht, dann vergiss diesen beitrag). aber ich glaube gerade das will FancanTeik vermeiden. also wenn der prozessor erst dem motortreiber die ausweichen-signale geben muss, wartet der hauptprozess natürlich erstmal, bis der bot ausgewichen ist. ne möglichkeit wäre dann, nen zweiten mini-prozessor mit der motorsteuerung zu betrauen. hauptprozessor bekommt interrupt und sagt dem motorprozessor: "weich ma aus!". und dann kann der hauptprozessor in aller ruhe seine sachen machen während der motorprozessor ausweicht.

Blackbird
22.04.2005, 08:43
also wenn der prozessor erst dem motortreiber die ausweichen-signale geben muss, wartet der hauptprozess natürlich erstmal, bis der bot ausgewichen ist.
Wenn das Programm (oder die Funktion oder der Thread) so programmiert wäre, würde auch Multithreading nicht helfen!

Blockierende Programmteile, wie etwa "Sleep" oder "Wait", die einfach den Prozessor zu NOPs zwingen, darf es nicht geben. Die Idee von felix ist doch: warte auf ein Ereignis, unterbreche alles andere, mache nur das notwendige (AD-Wert abfragen und speichern) und setze einen Event (oder Flag), gib den Prozessor sofort wieder frei.
Da ein Prozesser ja nicht NICHTS tun kann, muß es irgendwo ein main-Programm geben, dass nichts weiter macht, als alle Events (oder Flags) ständig reihum abzufragen. War eins gesetzt, wird die dazu passende Funktion (gespeicherten AD-Wert umrechnen, skalieren, verarbeiten, ...) aufgerufen. Nach dem Ende der Funktion geht es zum main-Programm zurück, das die nächsten Flags abfragt.

Das "Komplizierte" an so einem Programmaufbau ist, sich Events zu schaffen, die den Beginn und/oder das Ende einer Handlung signalisieren. Das können Interrupts (auch Timer) sein, oder einfach auch nur irgendwelche Flags, die irgendwer zu irgendeinem Zeitpunkt setzt.


Bitte kein "Sleep" oder "Wait" verwenden, sondern einen Timer starten und die Funktion verlassen (oder mit was anderem weiterarbeiten). Der Timer kommt später in einer Interrupt-Routine zurück, die jetzt dort weitermacht, was nach "Sleep" oder "Wait" stehen würde.

Blackbird

Felix G
22.04.2005, 14:18
@Goblin:
nein, ich meinte das so wie Blackbird es beschrieben hat.
Der Prozessor wird auf die Art nie länger als absolut notwendig blockiert.

Im Hauptprogramm läuft eine Endlosschleife (ist doch normalerweise eh so)
in der der Reihe nach alle Funktionen aufgerufen werden die gerade aufgerufen werden sollen.

Diese Schleife läuft immer, d.h. sie wird nicht vom Interrupt aus aufgerufen (was ziemlich schwachsinnig wäre),
sondern nur durch den Interrupt unterbrochen

22.04.2005, 16:55
Hallo,

auch mit den vorgeschlagenen Events ist das nicht so einfach.
Aber nehmen wir mal an alle Aktionen (Motor An/Aus, An mit Zeit) sind mit Events und nich blokierend programmiert. Das heisst ich sage Motor An for 2 sec. Die Funktion kehrt sofort zurück und das Ende wird über einen Event signalisiert. Da habe ich dann eine Event Loop und muss mühselig mit eine State Maschine meine Aktionen codieren.
z.B. Motor1An(1sec), warte auf fertig event1, Motor2An(1sec), warte fertig event2, ...
Sieht nicht so einfach aus ...

Fancan

Blackbird
25.04.2005, 09:16
Das ist der eben der Preis dafür. Hört sich aber viel schwieriger an, als es ist.
Das Wichtigste ist, dass das Programm(teil) sich den letzten Zustand (oder Zustände) merkt und an Hand des Events (können/sollen ja verschiedene sein) die neue Aktion ermittelt. Und dann ausführt (und den neuen Zustand speichert, den nächsten Event "in Auftrag" gibt und darauf wartet).
Da ja nicht in jedem Zustand jeder Event sinnvoll ist, hat man so die Möglichkeit, gezielt auf Fehler/Fehlverhalten zu reagieren.

Wenn Du es einmal erfolgreich so umgesetzt hast, wirst Du es nicht mehr anders machen wollen.

Blackbird