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
_LOCALUINTt_init;
2
3
_INITvoidmytask_init(void)
4
{
5
t_init=0;
6
}
7
8
_CYCLICvoidmytask_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