Sonstiges CPU 1515 FW V2.5 - Web Zugriff

JoGi65

Level-2
Beiträge
324
Reaktionspunkte
52
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

hab gestern die neue FW V2.5 aufgespielt. Dabei ist mir aufgefallen, das die Zykluszeit bei Webzugriff nicht mehr steigt.
Vorher hatte ich bei offener Webseite durchschnittlich ca. 30ms, jetzt ca 15ms, gleich wie ohne Webzugriff. Die max. Zeit ist gleich.

Allerdings fehlen beim Seitenaufruf/wechsel manchmal einzelne Bilder, die zwar bei einem Refresh da sind, aber ich kann mich nicht erinnern, das das vorher auch (öfters) passiert ist.

Ist das noch jemandem aufgefallen? Kann ich da was beeinflussen? (Browser Firefox aktuell).
Auch ein berechneter Wert ist zeitweise nicht da. (erster Wert von einer String Übertragung) Hätte ich vorher auch nicht bemerkt.
 
Hi,

das ein berechneter Wert nicht da ist kenne ich nur aus der asynchronen datenübermitlung mit Strings, wenn der String nicht rechtzeitig eine refresh durchs programm erhält bevor der webserver die aktualwerte abfragt.

Das andere mit dem das inhalte nicht direkt mitgeladen werden kenne ich so nicht.

Viele Grüße
RedCali
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für Deine Rückmeldung. Da der (Teil)wert des Strings ja in einem DB steht, der zyklisch aktualisiert wird, kann er dort praktisch nie "nicht vorhanden" sein, oder?

Aber möglicherweise hängts mit der doppelten Wandlung zusammen. Leider kann ichs nicht anders Reinschreiben. Ev vorher ins richtige Format, und dann erst zusammenfügen? Die Strings sind auch mehrfach verschachtelt. (String gesammt = string1 und 2 und 3..)

Code:
"DB_WWW".SM.str1 := CONCAT(IN1 := INT_TO_STRING(REAL_TO_INT("DB_Modbus_Real_Data".SM.P_W_G)),
                           IN2 := '/',
                           IN3 := INT_TO_STRING(REAL_TO_INT("DB_Modbus_Real_Data".SM.P_W_L1)),
                           IN4 := '/'....

Aber da es ja nur zum anschauen ist, ist es nicht so tragisch. Möglicherweise ist es mir vor dem FW Update auch nur nicht aufgefallen.

Und das mit dem Bild, das nicht da ist, ist nur am Standrechner. Auf den Tablets werden die Bilder nachgeladen. Dürfte somit eher mit eine Browser Eigenheit sein.
 
das verknüpfen der Daten in einen String würde ich in einen TempString machen, denn ich am ende dann einmalig auf den zu lesenden im DB kopiere.
Dann ist sichergestellt, das der String für den Webserver immer komplett ist, da der Webserver ja asynchron zwischen den Operationen zugreifen kann ist das so die sicherere variante.

Ich weiß nicht wie die Concat im System im Hintergrund arbeitet - deswegen über einen Temp.
Bei Siemens gibt es auch ein beispiel wir man das ganze noch verbessern kann mit Abspaltung der Daten in eine eigen Datei im JSON Format.
 
Wenn der Webserver asynchron auf die Daten zugreift, dann bekommst du das auch mit einer Temp-Variable nicht 100%ig in den Griff. Nur die Wahrscheinlichkeit dass mitten beim Umkopieren darauf zugegriffen wird ist geringer.

Ich habe das schon mit einem normalen Variablenzugriff über eine Visualisierung an einer 1200 ausgetestet. Selbst eine String-Zuweisung StringA := StringB ist nicht unterbrechungsfrei. Es gibt nur die Möglichkeit das Programm in einen Task mit höchster Priorität laufen zu lassen, was dann nicht mehr durch Kommunikation unterbrochen werden kann. Das behauptet Siemens jedenfalls, konnte es selber noch nicht verifizieren. Das läuft dann aber auch mit einer höheren Priorität als Zeit-Interrupts für Regler o.Ä.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
da geb ich dir recht, das es nicht 100% sind, allerdings hatte ich die Erfahrung gemacht das es so bei mir hingehaun hat :)
und er muss ja zwingend asynchron zugreifen, sonst müsste ja die Zykluszeit Überwachung kommen ;-)
 
Danke Euch. Den Beitrag hab ich nicht gefunden gehabt, da ich an einen FW Zusammenhang glaubte. Dem ist offensichtlich nicht so, sondern ich bin einfach auf ein standard Feature gestossen. Wie ich noch klein war wurde das anders bezeichnet. Schaut aus der Einfluss von MS schlagt zu Siemens durch.
Da bei mir ja schon leichter Alzheimer vorliegt, hab ich zuerst gedacht ich hab einen Baustein programmiert, der zum Überstrom Sicherung testen, alle Heizkörper sporadisch kurz einschaltet, und ich kann mich nicht mehr dran erinnern. Dabei ist es ja nur ein Leistungsmerkmal der CPU, damit der Anwender munter bleibt.

Der Task mit höherer Priorität - da reicht nicht OB30 zB. ?

Das mit den TempStrings muß ich mir anschauen. Bin erst am Lernen und hab bis jetzt alles nur in DBs.

Aber jetzt ergibt sich eine zweite Frage:
Ich hab die Datenübertragung von der Webseite zur CPU gerade komplett auf eine "ein String" Kommunikation umgestellt, da es sehr schnell ist und einfacher geht, wenn viele Werte auf einer Seite änderbar sind.

Die plausibilitäts Prüfung der Eingabe erfolgt auf der Webseite. Heißt das jetzt, dass auch diese Kommunikation korrupt sein kann?

Das würde bedeuten alle Werte, die in der SPS ankommen erneut zu prüfen, vor allem auch die, die Array Zähler ansprechen, da es sonst zu CPU Stops führen kann, wenn man einen Wert ändert? Das wäre schon ein bisschen schei..e.
Ich hab mich da eigentlich auf das TCP Protokoll verlassen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Selbst eine String-Zuweisung StringA := StringB ist nicht unterbrechungsfrei. Es gibt nur die Möglichkeit das Programm in einen Task mit höchster Priorität laufen zu lassen, was dann nicht mehr durch Kommunikation unterbrochen werden kann. Das behauptet Siemens jedenfalls, konnte es selber noch nicht verifizieren. Das läuft dann aber auch mit einer höheren Priorität als Zeit-Interrupts für Regler o.Ä.

kennst Du den hier: https://support.industry.siemens.com/cs/ww/de/view/59193558

interessant, dass PN-IO-Kommunikation auf der X2 einer S7-1515-2PN mit Priorität 26 läuft etc.


Gruß.
 
ich für meinen Teil kopiere mir die Werte in einen String und in der Webseite per Java dann in die entsprechenden Elemente.
Beim Schreiben gebe ich nur die entsprechenden Werte an die CPU weiter welche ich verändere / zusammengehören.
Ich nutze dazu die Methode "POST" aus der jQuery Bibliothek.
Ich hatte damit bisher keinerlei Schwierigkeiten gehabt.

hier in den beispielen "zur Erweiterung" steht dazu etwas: https://support.industry.siemens.com/cs/de/de/view/68011496

VG
RedCali
 
Zuletzt bearbeitet:
Ich tue mir mit den Begriffen etwas schwer, da ich mir das gerade erst erarbeitet hab, aber so wie es auscchaut nutze ich ja auch die Post Methode.
Allerdings verwende ich immer die gleiche AWP Variable (Variablen Datei) für alles (Ich hoffe das ding heißt wirklich so), weil es ja mit mehreren sehr langsam wird. Vor allem wenn es 126 Werte sind, die auf dieser einen Seite eingestellt werden können.

Auf der Webseite

Code:
var StringT = 'x' + ',' + Bereich  + ',' + Nr + ',' + Wert_neu + ';'
 $.post("Write/Heizung_Werte.htm",'"DB_WWW".Heizung.Empfang_Werte.get_strT=' + (StringT),function(result){});
 alert(unescape('Werte an SPS %FCebertragen!'));

Variablen Datei
<!-- AWP_In_Variable Name='"DB_WWW".Heizung.Empfang_Werte.get_strT'-->:="DB_WWW".Heizung.Empfang_Werte.get_strT:

In SPS
Code:
Strg_TO_Chars(Strg := "DB_WWW".Heizung.Empfang_Werte.get_strT,
              pChars := 0,
              Cnt => "DB_WWW".Heizung.Empfang_Werte.Count_char,
              Chars := "DB_WWW".Heizung.Empfang_Werte.Array_getT);

IF "DB_WWW".Heizung.Empfang_Werte.Array_getT[0] = 'x' THEN
    
    //Eingangsstring löschen
    "DB_WWW".Heizung.Empfang_Werte.get_strT := '0';
    
    // Diese Werte sind eigentlich im DB fix eingetragen - könnte man sich hier ersparen
    "DB_WWW".Heizung.Empfang_Werte.Suchstring := ',';
    "DB_WWW".Heizung.Empfang_Werte.Endstring := ';';
    "DB_WWW".Heizung.Empfang_Werte.Pos := 2;
    "DB_WWW".Heizung.Empfang_Werte.Mode := (16#0000_0010);
    
    "DB_WWW".Heizung.Empfang_Werte.Ret_Val := SPLIT(Mode := "DB_WWW".Heizung.Empfang_Werte.Mode,
                                                    RecSeparator := "DB_WWW".Heizung.Empfang_Werte.Suchstring,
                                                    EndSeparator := "DB_WWW".Heizung.Empfang_Werte.Endstring,
                                                    SrcArray := "DB_WWW".Heizung.Empfang_Werte.Array_getT,
                                                    Count => "DB_WWW".Heizung.Empfang_Werte.Count_str,
                                                    DstStruct := "DB_WWW".Heizung.Empfang_Werte.Array_getStr,
                                                    Position := "DB_WWW".Heizung.Empfang_Werte.Pos);
    
    IF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '0' THEN
        "DB_WWW".Heizung.Nr := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1]);
        "DB_WWW".Heizung.Hand_ein["DB_WWW".Heizung.Nr] := 1;
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '1' THEN
        "DB_Heizung".Arrays.P_W[STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1])] := STRING_TO_REAL("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2]);
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '2' THEN
        "DB_Heizung_Prio".Empfang.Hk := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1]);
        "DB_Heizung_Prio".Empfang.Prio_neu := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2]);
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '3' THEN
        "DB_Heizung".Arrays.LFZ_PT[STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1])] := (ULINT_TO_TIME(STRING_TO_ULINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2])) * 60000);
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '4' THEN
        "DB_Heizung".Arrays.OT_Vorgabe[STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1])] := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2]);
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '5' THEN
        "DB_Heizung_OT_max".Zykluszeit := STRING_TO_UINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2]) * 60;
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '6' THEN
        "DB_WWW".Heizung.Nr := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1]);
        "DB_WWW".Heizung.Aktiv_PV_ein["DB_WWW".Heizung.Nr] := 1;
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '7' THEN
        "DB_WWW".Heizung.Nr := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1]);
        "DB_WWW".Heizung.Aktiv_Kalender_ein["DB_WWW".Heizung.Nr] := 1;
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '8' THEN
        "DB_WWW".Heizung.Nr := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[1]);
        "DB_WWW".Heizung.Aktiv_Dauer_ein["DB_WWW".Heizung.Nr] := 1;
    ELSIF "DB_WWW".Heizung.Empfang_Werte.Array_getStr[0] = '9' THEN // kommt von WWW Wartung!!
        "DB_I_max".max_Strom := STRING_TO_USINT("DB_WWW".Heizung.Empfang_Werte.Array_getStr[2]);
    END_IF;
    
END_IF;

Die Werte die nur 0/1 übertragen werden dann noch rückgesetzt, das sie nur als Trigger verwendet werden.
Aber ich werde jetzt trotzdem vorsichtshalber für alle Werte in der SPS eine Plausibilitätsprüfung einbauen. Das ist sowieso kein Fehler.

Ich hab jetzt versucht OB31 mit einer Rate von einer Sekunde für den concat Befehl zu verwenden, aber das hat nix gebracht, so wie es ausschaut.
War das oben mit "Task mit höchster Priorität laufen zu lassen.." gemeint? (Sorry mein erstes und einziges Haus Hobby Projekt)

Da hier immer der erste Wert fehlt, und der ja auch aus der Kommunikation mit dem Smartmeter (Modbus TCP - Subnet RTU) stammt, werde ich das noch mit anderen Werten die nicht schon beim Einlesen Fehlerhaft sein könnten, versuchen.
Habs ja bei Bitmustern im String die direkt aus der SPS kommen auch schon gesehen.

Das mit dem Temp Variablen werd ich noch versuchen sobald ich gefunden habe wie man das schreibt :oops:. Ganz schön viel zum lesen für das Zeugs.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich hab mir deine Codefragmente eben mal durchgesehen, netter Ansatz ;-)

ABER, so wie ich das sehe, schreibst du immer nur 4 werte zu dem Zeitpunkt?
Wenn dem so ist, würde ich mir beim Schreiben die String Geschichte sparen (nicht beim Lesen, nur beim Schreiben)
4 Werte zu schreiben machen nicht aus hinsichtlich der Ladezeit, zudem wird dein Codefragment auch lesbarer.

deine Empfang würde ich zu einem Struct machen mit
- der Bool für die Flanke - was ich im übrigen sehr gut finde! -- BRAUCHT MAN ABER NICHT - siehe Bereichsnummer
- Bereichsnummer - STATE - ungleich null --> neue werte mit entsprechender Auswertung, am ende auf 0 gesetzt - Übergang von 0 nach Nr. ist auch eine Flanke :)
- Nummer
- Wert (oder werte) falls unterschiedliche Datensätze / Datentypen

Man kann auch mehrere AWP Kommandos verwenden, aber muss nicht zwingend immer dann ganzen Satz an Daten schreiben.
Das heißt man schreibt nur die Daten welche man zu dem Zeitpunkt verändert hat, dadurch kann man sich das ganze String Handling beim schreiben sparen.

der zu übertragende Datensatz muss dann folgender massen aufgebaut werden:
Code:
parameter=value&also=another


'"DB_WWW".Heizung.Empfang_Werte.Nummer=nummer&DB_WWW".Heizung.Empfang_Werte.Wert=wert&DB_WWW".Heizung.Empfang_Werte.Bereich=bereich'


Hier noch mal lesbarer, in roit die S7 Variable:
' [COLOR=#ff0000]"DB_WWW".Heizung.Empfang_Werte.Nummer[/COLOR] = nummer & [COLOR=#ff0000]"DB_WWW".Heizung.Empfang_Werte.Wert[/COLOR] = wert & [COLOR=#ff0000]"DB_WWW".Heizung.Empfang_Werte.Bereich[/COLOR] = bereich'

Die Flanken Variable kommt im Datensatz dann immer am ende
das übergibt man an den $.POST und gut ist's, dann kann man sich auch die String Operationen zum auseinander drösseln in der SPS schenken :)
 
Zuletzt bearbeitet:
Das mit dem verunden der AWPs hab ich nicht gewußt, danke!, aber ich hab das Modul für die Übertragung der Zeiten gebaut, wo 12 Werte auf einen Sitz übertragen werden.
Dann hab ichs einfach für die komplexeren Bausteine Systemgleich durchgezogen (obwohl ja sogar die ganze Sende Com über den einen String laufen könnte). Damit hab ich nicht zu viele verschiedene Sende Systeme.

Das mit dem Bereichstrigger versteh ich nicht ganz. Der Bereich spricht ein Array an, die Nummer den SW Taster im Array. Dann wird in einem anderen Baustein der Status der "Nr." abgefragt (wenn 1 toogle), und vor dem neuerlichen Durchlauf wird die „Nr.“ rückgesetzt. Das ist aber nicht im Code drinnen, den ich gepostet hab. Das ist vor dem Strg_to.. bzw. in einem andern Baustein.


Aber zurück zum lesen, was ja das eigentliche Thema ist:
Mir ist noch aufgefallen, das es scheinbar immer der erste String Teil ist, der nicht richtig gelesen wird. Allerdings hab ich jetzt schon versucht die Abfrage etwas Zeitlich zu versetzen, was auch keinen Einfluß hat. (Webserver arbeitet ja auch im Sekunden Takt – Abfrage etwas Phasen verschoben)

OB 31 hat Priorität 10 (da muß ich mich auch erst einlesen).

Und eine Temp. variable ohne OB anzulegen hab ich bis jetzt nicht geschafft. Oje ;-).
 
es muss ja nicht zwingent eine temporäre Variable sein, mit temporär meine ich, das man diese nur zum zusammenbauen nutzt :)
Ein String in dem man es zusammen baut, und einer den man zum lesen verwendet - so in etwa meine ich das:

Code:
"DB_WWW".tempString := '';

"DB_WWW".tempString :=  concat - was auch immer da rein gehört;

// am ende dann 

"DB_WWW".leseString:= "DB_WWW".tempString;

Wie gesagt, damit hatte ich dann nie Probleme, ich nutze auch keine zeit Interrupts dafür.
Das der Anfang vom String fehlt wundert mich, wie baust du ihn den zusammen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, jetzt hab ich es auch verstanden :lol: .

Code:
"DB_WWW".Heizung."Stat_str1.1" := CONCAT(IN1 := INT_TO_STRING(REAL_TO_INT("DB_Heizung".Arrays.P_W[1])),
                                         IN2 := '/',
                                         IN3 := INT_TO_STRING(REAL_TO_INT("DB_Heizung".Arrays.P_W[2])),
                                         IN4 := '/',

"DB_WWW".Heizung."Stat_str2.1" .....
"DB_WWW".Heizung."Stat_str3.1" .....

                                         ...
"DB_WWW".Heizung.Stat_strG1 := CONCAT(IN1 := "DB_WWW".Heizung."Stat_str1.1",
                                      IN2 := "DB_WWW".Heizung."Stat_str2.1",
                                      IN3 := "DB_WWW".Heizung."Stat_str3.1",
                                      IN4 := USINT_TO_STRING("DB_Heizung".Arrays.OT_Vorgabe[16]),
                                      IN5 := '/',
                                      IN6 := USINT_TO_STRING("DB_Heizung".Arrays.OT_Vorgabe[17]),
                                      IN7 := '/',
                                      IN8 := USINT_TO_STRING("DB_Heizung".Arrays.OT_Vorgabe[18]),
                                      IN9 := '/',
                                      IN10 := REAL_TO_STRING("DB_Heizung_OT_max".Zykluszeit));

Bei diesem fehlt dann der erste Sub String.

Beim andern Beispiel das ich vorher gepostet hab war es auch der erste (in dem Fall dann aber nur ein Wert und nicht der ganze sub String, da dort die Substrings am schluß rein kommen.)
Deswegen hab ich das mit der Zeitverschiebung versucht (10 zyklen später) aber hat nix gebracht. Fehlt genau der gleiche Teil!
 
na da :)
Welcher von den INPUTS wird zuerst verarbeitet?
Die Reihenfolge der Parameter sagt ja nun erst mal nichts aus wie der CONCAT intern arbeitet - ich weiß es zumindest nicht
Die Vermutung liegt nahe das er intern quasi hinten anfängt und darum der vordere teil fehlt.....
Deshalb mach ich das über zwei Strings, zusammenbauen und anschließend zuweißen.

Das hat - zumindest bei mir - immer tadellos funktioniert bisher.
 
So, habs jetzt versucht und fehlt wieder ab und zu. Die Häufigkeit hab ich nicht mehr geschaut.
Jetzt verdrehe ich aber einfach einmal die Reihenfolge und verwende am Anfang ein Bit das nicht ins Auge sticht. Der Smartmeter Wert kommt weiter hinten hin.

Edit - Ergebnis:
Das mit dem Tauschen hat funktioniert - der Auffällige Wert ist jetzt immer da, und der neue erste Wert fällt nicht so auf. Also so wie es ausschaut ist es der erste Wert von concat, der nicht immer kommt. Werd jetzt Dummy Werte die nicht ausgewertet werden an erster Stelle setzen, und damit sollte es passen.

Danke für Eure Hilfe!
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Zur Info:
So wie es nach den ersten Tests ausschaut, ist der beschriebene Kommunikationsfehler mit CPU FW 2.6.0 behoben oder wenigstens massiv verbessert.
Ich hab in den letzten 10 Minuten bei meiner Web Anzeige keine falschen oder fehlenden Werte mehr feststellen können.
 
Womit erstellt ihr eigentlich die Webseiten ? Gibt es da einen vernünftigen WEB Editor wo man nicht alles in HTML schreiben muß. Ich kann nicht viel HTML und dadurch ist der Zeitaufwand unbezahlbar für Kunden wenn wir sowas erstellen würden
 
WEB-Editor für S7-1200/1500 gesucht

Da ich gerade wieder ein bisschen angefangen habe meine SW weiter zu entwickeln, hab ich gestern "Visual Studio Code" runtergeladen. Auf den "ersten Blick" schaut das gut aus. EV besser als Notepad++ (jede Menge Erweiterungen - ob sinnvoll weiß ich noch nicht). So oder so - für mich sehr viel Zeitaufwand im Gegensatz zu Logik in Tia.
 
Zurück
Oben