Forum: Mikrocontroller und Digitale Elektronik Deterministisches Kooperatives Multitasking in Speicherprogrammierbarer Steuerung


von Gremling 1 (Gast)


Lesenswert?

Hallo,

ich verstehe wohl irgendwo nicht so ganz das kooperative Multitasking. 
Den Artikel auf mc.net habe ich schon durchgelesen.

Ich habe ein Projekt, in dem die Zyklen folgendermaßen aussehen:

     Zyklus1 (10ms)
         |---> Task1
         |---> Task2

     Zyklus2 (20ms)
         |---> Task3
         |---> Task4

     Zyklus3 (50ms)
         |---> Task5
         |---> Task6

     Zyklus4 (100ms)
         |---> Taks7
         |---> Task8

     Zyklus5 (200ms)

     Zyklus6 (500ms)

     Zyklus7 (1000ms)

     Zyklus8 (10ms)
         |---> Task9
         |---> Task10
         |---> Task11

Je niedriger die zahl hinter Zyklus, desto höher die Priorität.

Mein Problem ist folgendes. Ich möchte erreichen, daß im ersten 
Programmdurchlauf nach Einschalten (1.Zyklus und nur in dem) ein Impuls 
aktiv ist, der am Ende des ersten Zyklus bzw. zu Beginn des 2. Zyklus 
abgeschaltet wird. Ich stelle mir jetzt also die Frage in welchen 
Zyklus(NR) ich jetzt einen Task platzieren sollte, damit das so geht wie 
ich möchte.

Leider kenn ich mich mit Multitasking nicht so gut aus. So wie ich das 
sehe, wird in dem Programm schon mal gar nichts nach jedem Zyklus 
bearbeitet.

Vielleicht sagt eine solche Struktur irgendjemandem da draußen etwas und 
er findet vielleicht die Zeit mir das erklären zu können und wollen.

Danke

von Noname (Gast)


Lesenswert?

Hm. Ich verstehe Dich möglicherweise falsch, aber ich habe den Eindruck, 
dass Du für einen gewissen Zweck eine ungeeignete Methode wählst.

Ich verstehe Dein Posting so, das Du eine ganze Reihe von Impulsen 
erzeugen willst. OK.

Zunächst hat die Aufgabe "Impulserzeugung" per se nichts mit 
Multitasking im allgemeinen oder gar "kooperativem Multitasking" im 
Besonderen zu tun.

"Multitasking" ist in erster Linie eine Methode um mehrere Vorgänge 
(scheinbar) parallel ablaufen zu lassen. Das "kooperative Multitasking" 
ist eine besondere Form, bei der es den Vorgängen selbst überlassen ist, 
wann und nach welcher Zeit sie sich endgültig oder auch nur vorläufig 
beenden und zwar genau zu dem Zweck andere Vorgänge Gelegenheit zu 
geben, abzulaufen.
Man kann nun innerhalb des Paradigmas "Multitasking" auch Impulse, 
auch mehrere erzeugen, aber in gewisser Weise eher "trotzdem" als "am 
besten damit". Ich will damit sagen, das Multitasking nicht das Mittel 
ist, um Impulse bestimmter Dauer oder Anzahl zu erzeugen.
Im allgemeinen benutzt man für soetwas Timer.

Löse Dich am besten nocheinmal kurz von der Auffassung, dass 
"Multitasking" die Lösung darstellt und beschreibe einfach mal, was für 
Impulse Du erzeugen willst.

Eine graphische Beschreibung sähe in etwa so aus:

10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

---_____________________________________________________________________ 
_


Das Minus ist ein High, der Unterstrich ein Low.

von Noname (Gast)


Lesenswert?

Ich habe irgendwie das Stichwort "Speicherprogrammierbare Steuerung" 
verdrängt. Kannst Du das mal erläutern, bitte? Sollen die Impulse auf 
einer SPS erzeugt werden?
Falls ja, kannst Du "Multitasking" sowieso nicht verwenden. Das 
Betriebssystem einer SPS ist fest vorgegeben und Du bist auf die 
Sprachelemente beschränkt die Du z.B. mit AWL erzeugen kannst. Damit 
kannst Du nicht in die Abarbeitungsfolge direkt eingreifen. Vielmehr 
musst Du Dein "Programm" so gestalten, das es die gewünschten Impulse 
ausgibt. Dazu gibt es aber doch Timer.

von Gremling 1 (Gast)


Lesenswert?

Danke für eure Antworten. Ich spreche in der Tat von einer SPS. Auf 
dieser SPS läuft ein Echtzeitbetriebssystem. Mit dem klassischen 
SPS-Weltbild ala Siemens hat das nichts zu tun.

Meine Grafik aus dem ersten Posting ist auch nicht eine von mir erdachte 
Multitasking-Umgebung, sondern Fakt. Natürlich lauten die einzelnen 
Tasks anders als Task1 Task2 usw.

Also das aus meinem ersten Posting ist tatsächlich die Anordnung meiner 
Tasks. Programmiert wird das ganze übrigens in ANSI-C.

Ich möchte nun eben einen Programmteil schreiben, der nur im 1. Zyklus 
(und nur dort) einen 1-Impuls liefert. Wie man das programmiertechnisch 
macht ist mir schon klar. Das Problem ist für mich im Moment nur die 
Frage, wo ich diesen Programmteil hinsichtlich der Sturkutr aus meinem 
ersten Post denn platzieren soll, wenn dieser tatsächlich nur im ersten 
Zyklus kommen soll.

Zum Verständnis:

In allen anderen Zyklen wird dann eben auf meine Impulsvariable immer 
eine 0 geschrieben.

von Georg W. (gewe)


Lesenswert?

Hallo,

nach der Taskstruktur und ANSI-C gehe ich davon aus, dass Du eine B&R 
SPS hast.

Im Automation Studio kannst Du für jeden Task eine Init-Funktion 
definieren. Diese wird beim Starten des Tasks einmal ausgeführt.

Eine Möglichkeit wäre:
1
_LOCAL UINT t_init;
2
3
_INIT void mytask_init(void)
4
{
5
   t_init=0;
6
}
7
8
_CYCLIC void mytask_cyclic(void)
9
{
10
11
   if (t_init==0)
12
   {
13
      t_init=1;
14
      /* was auch immer Du machen willst ab hier */
15
   }
16
17
}

PS: Die Tasks werden beginnend mit der Taskklasse Cyclic #1 
initialisiert.

PPS: die Cyclic #8 ist eine Restzeittaskklasse. Diese wird in Deinem 
Beispiel versucht alle 10ms auf zu rufen. Jedoch wird hier oft eine 
Zykluszeitüberwachung von mehreren Sekunden eingetragen. Somit können 
dort asynchrone Tätigkeiten, z.B. Datenträgerzugriffe oder aufwendige 
Vorberechnungen gemacht werden, ohne das restliche System auszubremsen.



cu
Georg

von Gremling 1 (Gast)


Lesenswert?

Hallo Georg,

vielen Dank für deine Antwort. Wir sprechen in der Tat von einer B&R.

Das was du schreibst bezügliche einer Init war mir schon klar. Diese 
läuft ja nur einmal.

Mein Problem liegt wohl eher im Zeitverhalten.

Der Zyklus1 läuft alle 10ms. Die Laufzeit aller Tasks dieser Taskklasse 
darf nun 10ms nicht übersteigen.

Aber so wie ich das sehe, habe ich keine Möglichkeit meinen Code so zu 
implementieren, daß er tatsächlich in jedem Zyklus durchläuft.

Genau hier ist mein Verständnisproblem. Sehe ich das falsch ?

von Georg W. (gewe)


Lesenswert?

Was willst Du genau machen:

- etwas beim Start des ersten Tasks
  -> dann ersten Task in der Cyclic #1

- etwas nachdem das Laufzeitsystem alle Tasks initialisiert hat
  -> dann in den letzten Task der Cyclic #4. Dann hat aber die Cyclic #1
  schon ein paar Zyklen gemacht.

- verhindern, dass etwas gemacht wird, bevor eine langwierige
  Initalisierung/Hochlauf beendet ist
  -> SPS Globale Variable definieren. Jeden Task bis auf den
  Initialisierungstasks nur bearbeiten, wenn Initialisierung beendet 
ist.
  Im Initialisierungstask die Variable nach erfolgter Initialisierung 
auf
  eins setzten.


cu
Georg

von Michael (Gast)


Lesenswert?

Hallo Gremling 1,

das Problem in diesem Fall ist, du wirst zwar eine Variable setzen 
können und auch löschen im selben Task - die Änderung nach außen 
geschieht jedoch erst nach vollständiger Abarbeitung des Tasks; soll 
heißen:
du gibst eine 1 aus, wartest und löscht sie dann wieder und möchtest das 
an einem Ausgang sehen: du wirst nur "0" sehen, da der Wert erst bei 
Ende des Tasks übernommen wird.

Was soll der Puls bewirken? Willst du damit eine PWM realisieren? 
(Hierfür mal schauen ob du Zugriff auf LoopConR oder AsHydCon hast)
Das Tolle an dem System mit den Tasks und Zyklusklassen ist die 
Änderbarkeit. Machst du deinen Puls von der Dauer eines (fest 
eingestellten) Zyklus abhängig, wird es dir später, wenn du die Zeiten 
mal ändern musst um so schwerer. Mit RTInfo() könntest du Information 
über die Taskklasse holen und entsprechend reagieren - unabhängig davon 
ob dein Task wirklich in der Klasse 1 abläuft.
Unabhängig davon wäre es auch möglich, die Zeit von 10ms weiter nach 
unten zu setzen, womit du z.B. bei 2ms insgesamt 5 mal den Task 
aufgerufen bekommst.

von Michael (Gast)


Lesenswert?

Hallo Gremling 1,

habe gerade noch einmal deinen Beitrag gelesen und festgestellt du 
willst also nur für die Dauer des allerersten Zyklus beim allerersten 
Aufruf den Puls ausgeben?

Georg W. schrieb:
> -> SPS Globale Variable definieren. Jeden Task bis auf den
>   Initialisierungstasks nur bearbeiten, wenn Initialisierung beendet
> ist.
>   Im Initialisierungstask die Variable nach erfolgter Initialisierung
> auf
>   eins setzten.

Dann wäre das deine Lösung;

im _INIT - Task als erste Zeile deinen Ausgang auf 1; als letzte 
Anweisung im _INIT eine Variable setzen; als erste Anweisung im _CYCLIC 
die Variable abfragen und wenn True deinen Ausgang auf 0; Das Ergebnis 
kann ich dabei aber wirklich nicht genau vorhersagen, wegen oben 
genanntem Verhalten kann es auch sein dass die "1" das Programm nie 
verlässt.

Trotzdem interessiert mich, wozu du das tun willst? Soll das eine Art 
"Bitte warten, starte System" werden?

von Gremlin 1 (Gast)


Lesenswert?

Nein,

dieser Impuls wird bei SPSen gerne dazu verwendet Initialisierungen 
durchzuführen oder eben festzustellen wann die Maschine eingeschaltet 
wird. Im Moment des Einschaltens sind evtl. temporäre Zustände nicht 
mehr vorhanden. Der Einschaltmoment stellt somit eine Ausnahme dar, die 
über diesen Impuls abgefangen werden kann.

von Reinhard Kern (Gast)


Lesenswert?

Hallo,

Zykluszeit ist ja die Zeit, nach der ein Programm erneut aufgerufen 
wird, die Laufzeit des Programms kann (und muss) wesentlich kürzer sein. 
Wenn du also nach Ablauf einer Zykluszeit einen Ausgang ändern willst, 
musst du das am Beginn des nächsten Zyklus tun. Um festzustellen, dass 
es der nächste ist (in dem Fall der zweite) musst du eine Variable 
setzen.

Alternativ: eine Task vorsehen, die im ersten Zyklus einen Ausgang 
setzt, im 2. zurücksetzt und sich dann komplett verabschiedet - dann 
werden keine Resourcen mehr verbraucht.

Kooperatives Multitasking sollte in einer SPS eigentlich verboten sein, 
da eine der bei Softwareentwicklern so beliebte Endlosschleife das 
Gesamtsystem lahmlegt.

Zyklen im 10ms-Takt mitzuzählen ist auch nicht viel anders als ein 
Timer.

Gruss Reinhard

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.