Step 7 PCS7 Ungenauigkeit bei Zeitmessung

B1tst0rm

Level-1
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich bitte um Hilfe bezüglich des folgenden Sachverhaltes: Software PCS7 V8.0 SP2, CFC V8.0 SP4 + Upd4, SCL V5.3 + SP6 + Upd 1

In einem Funktionsbaustein laufen zwei Zeitmessungen wie folgt:
- Zeitmessung 1 über zyklischen Aufruf von TimerP (AdvLib71 FB1810) Baustein
- Zeitmessung 2 über Aufsummierung der Zykluszeit des aufrufenden OB (100ms) Rechenvorschrift Zeit := Zeit + 0.1;

Beide Zeitmessungen laufen nach gemeinsamen Start deutlich auseinander:
- Wert Zeitmessung 1 über TimerP: 223.8338 s
- Wert Zeitmessung 2 über Zykluszeit des OB: 220.5043 s

Frage 1: Wie ist diese Abweichung zu erklären?
Frage 2: Wie kommt bei der Rechenvorschrift Zeit := Zeit + 0.1; die 0.0043 zustande?

MfG
 
Rundungsfehler durch die begrenzte Auflösung von REAL-Zahlen. IEEE 754
Dadurch passiert es sogar irgendwann, daß bei der Addition "Zeit := Zeit + 0.1;" Zeit 'rauskommt, Zeit sich also nicht mehr ändert - so als hätte man 0.0 addiert.

Harald
 
Anbei der Quelltext des FB:


FUNCTION_BLOCK TEST
TITLE = 'TEST'
//
// TEST
//
{
S7_m_c := 'false'
}
VERSION : '0.1'
AUTHOR : TEST
NAME : TEST
FAMILY : TEST

VAR_INPUT

SAMPLE_T {
S7_visible := 'false';
S7_link := 'false';
S7_sampletime := 'true'
} : REAL := 0.01;

START {S7_m_c := 'false'; S7_link := 'false'; S7_visible := 'true'} : BOOL := FALSE;
RESET {S7_m_c := 'false'; S7_link := 'false'; S7_visible := 'true'} : BOOL := FALSE;

END_VAR
VAR_OUTPUT

ZEIT_TIMER_P {S7_m_c := 'false'; S7_visible := 'true'} : REAL;
ZEIT_ZYKLUS {S7_m_c := 'false'; S7_visible := 'true'} : REAL;

END_VAR
VAR

ST_IN_TRUE : STRUCT
VALUE : BOOL := TRUE;
ST : BYTE := 16#80;
END_STRUCT;

ST_IN_FALSE : STRUCT
VALUE : BOOL := FALSE;
ST : BYTE := 16#80;
END_STRUCT;

ST_IN_BOOL : STRUCT
VALUE : BOOL := FALSE;
ST : BYTE := 16#80;
END_STRUCT;

ST_OUT_BOOL : STRUCT
VALUE : BOOL := FALSE;
ST : BYTE := 16#80;
END_STRUCT;

ST_OUT_REAL : STRUCT
VALUE : REAL := 0.0;
ST : BYTE := 16#80;
END_STRUCT;
Timer_P_1 : TimerP; //FB1810

END_VAR


BEGIN

//Einschaltverzögerung
Timer_P_1.Ti := 86400.0; //24 Stunden
Timer_P_1.SampleTime := SAMPLE_T; //Abtastzeit automatisch an Timer weiterreichen
Timer_P_1.Mode := 2; //Timer einschaltverzögernd starten
Timer_P_1.Reset := ST_IN_FALSE;

ST_IN_BOOL.Value := START;

Timer_P_1.In := ST_IN_BOOL;
Timer_P_1();

ST_OUT_REAL := Timer_P_1.TimeRemaining;

IF START THEN
ZEIT_TIMER_P := 86400.0 - ST_OUT_REAL.Value;
ZEIT_ZYKLUS := ZEIT_ZYKLUS + 0.1; //Zykluszeit aufrufender OB = 100ms = SAMPLE_T
END_IF;

IF RESET THEN
RESET := FALSE;
ZEIT_TIMER_P := 0.0;
ZEIT_ZYKLUS := 0.0;
END_IF;

END_FUNCTION_BLOCK
 
- Zeitmessung 2 über Aufsummierung der Zykluszeit des aufrufenden OB (100ms) Rechenvorschrift Zeit := Zeit + 0.1;
Betrachte es mal so: eine Anzahl von 0.1s-Einheiten zählen.

Zählen: Üblicherweise zählt man ganze Einheiten, was den netten Effekt hat, daß keine Rundungsfehler entstehen.

Du könntest/solltest also statt Aufsummieren von 0.1 auf einen REAL-Wert besser 1 in einen DINT-Wert aufsummieren (also zählen), und erst zu Anzeige- oder Berechnungszwecken die DINT-Summe zu REAL wandeln und durch 10.0 teilen. Genauer geht es nicht.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wobei man dann noch klären müßte:

1. wie genau schlägt der Zeit-OB zu (da muß es ja einen Jitter geben)
2. Auch die Zeiten sind nur endlich genau
 
Also ich bau das mal nach....
Das mit dem Jitter als Ursache glaube ich nicht so recht, weil der Timer_P ja dieselbe SAMPLE_T zur Verfügung hat.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ein weiterer Unterschied wird durch die zusätzliche Subtraktion beim TimerP zustandekommen. Du kannst ja mal den ersten Fehler korrigieren, und dann deinen Timer über die Zykluszeit genauso programmieren wie den TimerP. Also bei Startflanke auf Wert setzen, und dann rückwärtszählen.
 
Danke für die bisherigen Ratschläge. Ich habe den Datentyp wie vorgeschlagen angepasst.

Auszug Quelltext:

IF START THEN
ZEIT_TIMER_P := 86400.0 - ST_OUT_REAL.Value;
Zyklen := Zyklen + 1;
ZEIT_ZYKLUS := DINT_TO_REAL(Zyklen);
ZEIT_ZYKLUS := ZEIT_ZYKLUS / 10.0;
END_IF;

IF RESET THEN
RESET := FALSE;
ZEIT_TIMER_P := 0.0;
ZEIT_ZYKLUS := 0.0;
Zyklen := 0;
END_IF;

Abweichung der Zeiterfassung:

TimerP = 138.2266 s
OB Zyklus = 136.2 s

TimerP = 215.5156 s
OB Zyklus = 212.3 s

Die Abweichung von einem Zyklus möchte bzw. kann ich im Testfall vernachlässigen (konstanter systematischer Fehler).

Das Problem ist der deutlich anwachsende Fehler mit der Dauer der Messung und dessen Ursache!

Als erstes dachte ich es könnte an PLCSIM liegen. Aber die gleiche Abweichung stellt sich auf einer realen S7-416 ein.
 
Ich würde den Vergleich zwischen den beiden Funktionen so programmieren:
Code:
IF START AND NOT START_ALT THEN
    ZEIT_ZYKLUS := 86400.0;
ELSIF START THEN
    ZEIT_TIMER_P := ST_OUT_REAL.Value;
    ZEIT_ZYKLUS := ZEIT_ZYKLUS - SAMPLE_T; //Zykluszeit aufrufender OB = 100ms = SAMPLE_T
END_IF;
START_ALT := START;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also ich habe das auch ausprobiert, allerdings mit einem Timer aus ELEMENTA.
Dasselbe Ergebnis.
Der prozentuelle Unterschied der beiden Werte steigt einerseits mit dem Startwert des Timers (zB ist 3600.0 viel besser als 86400.0) und andererseits mit der Verkleinerung der Aufrufzeiten.

Wie oben schon von Harald vermutet liegt das an der Rechengenauigkeit des Systemes.
Ob der Timer_P im "Bauch" ungünstig programmiert ist, weiss ich nicht, kommt mir aber fast so vor.
 
Die Hilfe zum TimerP sagt, dass der Abstand zwischen Ti und SampleTime nicht mehr als 10^7 betragen darf. Bei 0.1 wäre das also 100000, zumindest ist die 86400 schon in der Nähe davon.
Dadurch dass seine beiden Rechnungen gegenläufig arbeiten, wird die eine Berechnung mit laufender Zeit genauer (TimerP bei Start mit Subtraktion einer kleinen Zahl von einer großen) und die andere mit laufender Zeit ungenauer (Zyklus bei Ende mit Addition einer kleinen Zahl zu einer großen).
 
Ich finde den Wertzuwachs der sich einstellenden Abweichung für bedenklich. Ich möchte nicht wissen wie viele Anwender bzw. Kunden nicht von ihrem Glück der „genauen“ Zeitererfassung wissen. Bin gespannt was die Leute vom SIEMENS- Support zum Thema zu sagen haben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ist das Thema für Dich nur allgemein von Interesse oder hast Du damit ein konkretes Problem, das man vielleicht anders lösen kann?
Es ist ja durchaus nicht sehr vernünftig lange Zeiträume im 100ms Takt zu zählen.
 
Ich bin auf der Suche nach der genauesten Möglichkeit unter PCS7 Zeiträume im ms bis min Bereich zu erfassen.

TimerP scheint diesbezüglich ein Witz zu sein. Der Baustein fällt mit Blick auf Echtzeit scheinbar komplett durch.

Was ist eurer Meinung hierfür am besten geeignet?

Eigenbau über das Zählen von Aufrufzyklen des OB über eine DINT Variable?

Ist beim zyklischen Aufruf der OBs harte Echtzeit garantiert?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich bin auf der Suche nach der genauesten Möglichkeit unter PCS7 Zeiträume im ms bis min Bereich zu erfassen.

TimerP scheint diesbezüglich ein Witz zu sein. Der Baustein fällt mit Blick auf Echtzeit scheinbar komplett durch.

Was ist eurer Meinung hierfür am besten geeignet?

Eigenbau über das Zählen von Aufrufzyklen des OB über eine DINT Variable?

Ist beim zyklischen Aufruf der OBs harte Echtzeit garantiert?

lies zum Start und zum Ende der Messung die Systemzeit der SPS aus (SFC64), danach subtrahierst du die Werte.
Genauer gehts nicht.

Gruß Micha
 
Danke für eure Hinweise. Die Abfrage der Systemzeit ist mir bekannt. Ich dachte es existiert eine schlankere Lösung als das Zerlegen und Rechnen mit den Elementen der DATE_AND_TIME- Struktur.
 
Du musst beim SFC64 nix zerlegen, es wird die Zeit seit CPU-Start in ms ausgegeben.
Es genügt eine Subtraktion der Werte um die Differenz in ms zu erhalten.
 
Zurück
Oben