- Beiträge
- 9.189
- Reaktionspunkte
- 2.936
-> Hier kostenlos registrieren
Zeig doch mal das Programm. Wenn diese Schwankung nicht wäre, sieht es doch schonmal nicht schlecht aus.
Folge dem Video um zu sehen, wie unsere Website als Web-App auf dem Startbildschirm installiert werden kann.
Anmerkung: Diese Funktion ist in einigen Browsern möglicherweise nicht verfügbar.
ORGANIZATION_BLOCK "Cyclic interrupt 2ms"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
RT_Result : LReal; [COLOR="#008000"]// [s] Laufzeit seit vorherigem Aufruf von RUNTIME()[/COLOR]
RT_Memory : LReal; [COLOR="#008000"]// Stand Systemzeitzähler beim vorherigen Aufruf von RUNTIME()[/COLOR]
RT_Start : LReal; [COLOR="#008000"]// Stand Systemzeitzähler beim Start der Zeitmessung[/COLOR]
RT_T1 : LReal; [COLOR="#008000"]// Endzeitpunkt[/COLOR]
nAIRT : Int; [COLOR="#008000"]// Anzahl aktiver Alarmsperrungen[/COLOR]
END_VAR
VAR CONSTANT
T104us : LReal := 0.000104167;
END_VAR
BEGIN
[COLOR="#008000"] //CPU 1215C DC/DC/DC 6ES7 215-1AG40-0XB0 V4.1
//OB30: Cyclic interrupt 2ms
//Priorität: 7 (nicht änderbar?!)
//zunächst Machbarkeits-Test, Reset der Statistik mit %I0.0 in OB1[/COLOR]
#nAIRT:=DIS_AIRT(); [COLOR="#008000"]//höherpriore Alarm- und Fehler-OB verzögern[/COLOR]
[COLOR="#008000"]//*** Wie lange dauert nur der Aufruf von RUNTIME()? ***[/COLOR]
#RT_Memory := 0.0;
#RT_Result := RUNTIME(#RT_Memory); [COLOR="#008000"]//liefert den Stand des Systemzeitzählers = Anfangszeitpunkt[/COLOR]
"DB30".RUNTIME_Now := #RT_Memory; [COLOR="#008000"]//für beobachten[/COLOR]
[COLOR="#008000"]//Wie lange dauert nur der Aufruf von RUNTIME()? (keine Anweisungen dazwischen)[/COLOR]
#RT_Result := RUNTIME(#RT_Memory); [COLOR="#008000"]//liefert den Stand des Systemzeitzählers seit vorherigem RUNTIME()-Aufruf = Laufzeit in Sekunden[/COLOR]
"DB30".RUNTIME_Last := #RT_Result; [COLOR="#008000"]//für beobachten[/COLOR]
[COLOR="#008000"]//Statistik: Wie sehr schwankt die Laufzeit des RUNTIME()-Aufrufs?[/COLOR]
IF #RT_Result > 0.0 THEN [COLOR="#008000"]//wenn kein Überlauf Systemzeitzähler[/COLOR]
IF #RT_Result < "DB30".RUNTIME_Min THEN
"DB30".RUNTIME_Min := #RT_Result;
ELSIF #RT_Result > "DB30".RUNTIME_Max THEN
"DB30".RUNTIME_Max := #RT_Result;
END_IF;
END_IF;
[COLOR="#008000"]//*** Wartezeit 104.167µs ***[/COLOR]
#RT_Result := RUNTIME(#RT_Memory); [COLOR="#008000"]//aktuellen Stand Systemzeitzähler in #RT_Memory holen[/COLOR]
#RT_Start := #RT_Memory; [COLOR="#008000"]//aktuellen Stand Systemzeitzähler als Startzeitpunkt merken[/COLOR]
#RT_T1 := #RT_Start + #T104us; [COLOR="#008000"]//Endzeitpunkt: Jetzt + 104µs (Jetzt + 0.000104167)[/COLOR]
IF #RT_T1 > #T104us THEN [COLOR="#008000"]//wenn kein Überlauf Systemzeitzähler[/COLOR]
[COLOR="#008000"]//Warteschleife[/COLOR]
REPEAT
#RT_Result := RUNTIME(#RT_Memory);
UNTIL #RT_Memory > #RT_T1 END_REPEAT; [COLOR="#008000"]//bis Systemzeitzähler_Jetzt > Endzeitpunkt[/COLOR]
[COLOR="#008000"] //PLCSIM: RUNTIME schreibt öfter nicht in den INOUT! Wert_Out = Wert_In doch Result > 0.0 !!![/COLOR]
[COLOR="#008000"]//Statistik: Wie genau/schwankend wurden die 104µs getroffen?[/COLOR]
#RT_Result := #RT_Memory - #RT_Start; [COLOR="#008000"]//Dauer := Systemzeitzähler_Jetzt - Startzeitpunkt[/COLOR]
IF #RT_Result < "DB30".RT_104_Min THEN
"DB30".RT_104_Min := #RT_Result;
ELSIF #RT_Result > "DB30".RT_104_Max THEN
"DB30".RT_104_Max := #RT_Result;
END_IF;
END_IF;
#nAIRT := EN_AIRT(); [COLOR="#008000"]//Alarm- und Fehler-OB wieder freigeben[/COLOR]
END_ORGANIZATION_BLOCK
DATA_BLOCK "DB30"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
VAR
RUNTIME_Now : LReal;
RUNTIME_Last : LReal;
RUNTIME_Min : LReal;
RUNTIME_Max : LReal;
RT_104_Min : LReal;
RT_104_Max : LReal;
RUNTIME_Min_us : DInt;
RUNTIME_Max_us : DInt;
RT_104_Min_us : DInt;
RT_104_Max_us : DInt;
END_VAR
BEGIN
RUNTIME_Now := 0.0;
RUNTIME_Last := 0.0;
RUNTIME_Min := 1.0;
RUNTIME_Max := 0.0;
RT_104_Min := 1.0;
RT_104_Max := 0.0;
RUNTIME_Min_us := 0;
RUNTIME_Max_us := 0;
RT_104_Min_us := 0;
RT_104_Max_us := 0;
END_DATA_BLOCK
+--------+ +--------+
%I0.0 | MOVE | | MOVE |
----| |-------------|EN |----------------------------|EN |
1.0--|IN OUT1|--"DB30".RUNTIME_Min 0.0--|IN OUT1|--"DB30".RUNTIME_Max
| OUT2|--"DB30".RT_104_Min | OUT2|--"DB30".RT_104_Max
+--------+ +--------+
+------------+
"AlwaysTRUE" | MUL(LReal) |
----| |-------------|EN |------------------------- ...
"DB30".RUNTIME_Min--|IN1 |
1000000.0--|IN2 OUT|--"DB30".RUNTIME_Min_us
+------------+
das gleiche für
"DB30".RUNTIME_Max --> "DB30".RUNTIME_Max_us
"DB30".RT_104_Min --> "DB30".RT_104_Min_us
"DB30".RT_104_Max --> "DB30".RT_104_Max_us
Für S7-1200-CPUs ab Firmwarestand V4.0 gilt:.
Wenn Sie die OBs als nicht unterbrechbar parametrieren, dann wird ein OB stets zu Ende bearbeitet, und zwar auch dann, wenn während seiner Laufzeit ein Ereignis höherer Priorität auftritt. Das bedeutet im Einzelnen:
Jeder OB mit einer Priorität >= 2 unterbricht das zyklische Programm.
Ein OB der Priorität 2 bis 25 kann von keinem Ereignis unterbrochen werden. Das gilt auch dann, wenn ein Ereignis mit höherer Priorität als der des momentan aktiven OB auftritt, also auch für einen Zeitfehler. Diese Ereignisse werden zu einem späteren Zeitpunkt bearbeitet.
ohne Beobachten | mit Beobachten
--------------------------------------------------------------------------------
Dauer Aufruf RUNTIME() : 18 - 44 : 26 µs Jitter | 18 - 83 : 65 µs Jitter
Genauigkeit Schleife 104µs : 104 - 134 : 30 µs Jitter | 104 - 156 : 52 µs Jitter
Noch keine Erklärung habe ich warum Bit.6 länger ist.
Allerdings schreibt Siemens nicht explizit, ob OBs durch das Betriebssystem z.B. für Kommunikation unterbrochen werden oder ob beim Aufruf von Betriebssystem-Funktionen (z.B. RUNTIME()) noch andere Sachen eingeschoben werden können.
Vielleicht kann man die PWM-Ausgabe auf eine Ausgabefrequenz von knapp 100kHz (10.4µs) programmieren und die Ausgabefrequenz mitzählen oder den PWM-Ausgang auf einen schnellen Zähleingang verbinden und den Zählerstand mit Peripheriezugriffen auslesen. Dann wäre man unabhängig von RUNTIME() doppelt so genau, doch da bliebe auch noch das Problem mit den ominösen Unterbrechungen des OB30.Gibt es noch eine andere Möglichkeit zur Abmessung der 104µs?
Ca. etwas weniger als ein 1/3 Bit (bei 9600) also so 30usWie lang ist die Unterbrechung eigentlich?
Nein ich keine entscheidende Verbesserung festgestellt. Bei eine Auflösung der Phasenverschiebung von 1msPassiert/stört die Unterbrechung auch, wenn Du als Aufrufintervall 3ms wählst, und/oder mit 1ms Phasenverschiebung?
Harald
Ich habe schon fast alles Probiert ………Du kannst mal das Startbit testweise 10µs kürzer oder länger machen.
_ _
_ _ _ _ _ _ _ _ 191
S 0 1 2 3 4 5 6 7 S
_ _
_ _ _ _ _ _ _ _ 223
_ _ _
_ _ _ _ _ _ _ 159
_ _ _
_ _ _ _ _ _ _ 63
_ _
_ _ _ _ _ _ _ _ 127
_ _ _
_ _ _ _ _ _ _ 190
_ _ _ _ _
_ _ _ _ _ 85
Um auszuschließen dass der Wert von Runtime wackelt, würde ich mal probieren, eine entsprechende Anzahl an Anweisungen zwischen dem Zugriff des PAW einzufügen, die dann die Zeitverzögerung darstellen. Beispielsweise ein Merkerwort um 1 erhöhen.......
Vermutlich nicht. Du könntest aber einen eigenen RUNTIME-Zähler erzeugen wie ich in #48 schrieb. Ich kenne die S7-1200 nicht genau genug, doch es muß möglich sein, für einen PWM-Ausgang eine Ausgabefrequenz zu programmieren - die wird dann freilaufend in Hardware erzeugt. Vielleicht kann man den Peripherie-Ausgang abfragen und mitzählen, notfalls kann man den aber mit einem schnellen Zähleingang verbinden und den Zählerstand oder den Eingang abfragen. Eine eventuelle Unterbrechung des OB30 kann man dadurch aber nicht verhindern - vielleicht kommt die Schwankung aber auch nur dann wenn man RUNTIME() aufruft?Gibt es keinen besseren weg direkt an die Runtime Variable zu kommen ?
Ich will es jetzt einfach wissen …..Ich bewundere Eure Hartnäckigkeit.
Mit einen 8 Bit‘er PIC oder AVR kann das ja jeder …. zu einfach ….Da hätte ich schon längst ein PIC-gesteuertes Modul in's Auge gefasst, welches über einen DO getriggert wird.
Hobby: maximaler Aufwand, minimaler NutzenIch will es jetzt einfach wissen …..
Löten kann aber auch nicht jeder.Mit einen 8 Bit‘er PIC oder AVR kann das ja jeder …. zu einfach ….
Wir verwenden essentielle Cookies, damit diese Website funktioniert, und optionale Cookies, um den Komfort bei der Nutzung zu verbessern.
Siehe weitere Informationen und konfiguriere deine Einstellungen