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
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.
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.
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.
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
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 ?
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
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.
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.