RANT: Konstrukte bei denen man sich manchmal fragt

Zuviel Werbung?
-> Hier kostenlos registrieren
@Axel:
Du wirst sicherlich Recht haben, dass das so entstanden sein könnte - als eine Entschuldigung kann ich das aber nicht akzeptieren.
Genau das, was René schreibt, kenne ich (auch von meinen Kollegen) zur Genüge und bin auch schon zwei-drei Mal darüber gestolpert. Die 2 Sekunden mehr Zeit kann man sich schon nehmen ...

Gruß
Larry
 
Hahaha.. das ist mal ein lustiger Beitrag.

Ich hatte vor kurzem eine lustige Konstellation in einem SPS-Programm einer Fremdfirma. Es ging um eine einfache Uhrzeit-Synchronisation zwischen dem Panel und der CPU.

Das Panel schickt die Uhrzeit als einzelne INT-Varaiblen an die SPS. Im STAT-Bereich des FB ist ein DATE_AND_TIME angelegt. Als es dann aber an das zusammensetzen des DT ging wurde es ein wenig merkwürdig.

Da stand dann sowas.
Code:
L Daten.Jahr
ITB
T DB11.DBB20   //Zuerst werden die Zeitwerte auf irgendeinen DB transferiert.
L Daten.Monat
ITB
T DB11.DBB21

//.... und so weiter

//dann geht's an das setzen der Uhrzeit
Call SET_CLK
IN= #DT_VarAusStat  // wurde eigentlich noch nirgends beschrieben
Bin dann eh schnell drauf gekommen dass der DB11 der Instanz-DB des hiesigen FBs war.
Das war die lustigste Art der "indirekten Adressierung" von STAT-Daten die ich jemals gesehen hab.

Ich glaub Larry pflegt zu sagen: Von hinten, durch die Brust, ins Auge. *ROFL*
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich finde ja, dass die Probleme mit der Verwendung von uninitialisierten Temp-Variablen eigentlich ein Fall für eine Compilerwarnung wären.

Denn der könnte überprüfen ob eine Temp-Variable gelesen, bevor sie geschrieben wird, und dann zumindest eine Warnung ausgeben. Gleiches wenn ich einen FC habe und eine Out-Variable nicht beschreibe. Das wäre für den Compiler-Hersteller nur ein geringer Aufwand, würde aber viele Fehler vermeiden helfen.
 
Aber nur als Warnung bitte. Nicht dass die Initialisierung bzw. das Beschreiben vor dem Lesen an mehreren Stellen nur Bedingt bearbeitet wird. Und dann kann der Kompiler ggf. nicht erkennen ob sicher irgendwo initialisiert wird oder ob alle Schreibzugriffe in einer Konstellation übersprungen werden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Omron Kontaktplan ist einer der Besten, den ich je gesehen habe.

1) Arrays lassen sich nur mit Signed-Integer-Typen indexieren.
2) Es gibt keine Bit-Manipulation mit Integertypen, sondern nur mit Word-typen
3) Addition, Subtraktion etc. sind nur für integertypen definiert, aber nicht für Word-Typen
4) Die Konvertierung kann nicht einfach auf Kontaktplanniveau erfolgen. Daher gibt es jede Menge Warnungen vom Compiler.
5) Typkonvertierungen in ST werden immer von Warnungen des Compiler begleittet, so dass wirkliche Fehler wie ein doppeltes Schreiben auf eine Variable nicht auffallen.
6) Das endet in ST damit, dass man wieder Willen und das bei bester Planung Unmengen von Konvertierungen durchführen muss, weil selbst so simple Funktionen wie SHL() nur einen Word-Typ zurückgeben.
7) Es gibt eine FOR-Schleife, die aber ohne Index-Variable ist, daher kann man dann auch gleich eine State-Machine implementieren.

Omron war nicht einmal in der Lage FBs für die CANbus-Initialisierung zu liefern, die in jeder Situation funktionieren. Stellt man nämlich eine feste Zykluszeit ein, funktionieren die nicht mehr, weil da gepfuscht wurde und nicht auf das Ende des FINS-Kommandos getestet wurde.
 
Nächste krasses Konstruktion.
Ich hab echt manchmal mühe da durchzublicken was eigentlich das Ziel sein sollte.

Code:
      U     "SPS4 - IO DB160"._DBX_10_4 // Not-Aus
      SPB   OE0
      U     #Oelanlage_Freigabe         // Pumpe Freigabe
      SPB   OE1
OE0:  R     #Schalten_Oelanlage_Pu1
      R     #Schalten_Oelanlage_Pu2
      R     #Oelanlage_Anlauf
      R     #Umschaltung
      R     T      1
      R     "SPS -> BR"._DBX_202_6
      SPA   OE12


// Öldruck abwarten, notfalls umschalten    
OE1:  UN    #Schalten_Oelanlage_Pu1     // Eine Pumpe einschalten
      UN    #Schalten_Oelanlage_Pu2
      SPB   OE3
      U     #Schalten_Oelanlage_Pu1     // Beide Pumpen in Betrieb
      U     #Schalten_Oelanlage_Pu2
      SPB   OE12
      U     T      1                    // Anlauf fertig
      U     #Oelanlage_Anlauf
      SPB   OE11
      UN    #Oelanlage_Anlauf           // keine 30bar nach Anlauf
      UN    #Umschaltung
      UN    #RM_Oeldruck_Pumpen_30bar
      SPB   OE2
      U     T      1
      U     #Umschaltung
      SPBN  OE12
      U     #RM_Oeldruck_Pumpen_30bar   // 30bar nach Umschaltung
      SPB   OE12
      U     #Schalten_Oelanlage_Pu1     // keine 30bar nach Umschaltung
      SPB   OE7
      U     #Schalten_Oelanlage_Pu2
      SPB   OE5


OE2:  U     #Schalten_Oelanlage_Pu1     // Umschaltung keine 30bar nach Anlauf
      SPB   OE6
      U     #Schalten_Oelanlage_Pu2
      SPB   OE4
      SPA   OE12


// Ein-/Umschaltung
OE3:  S     #Oelanlage_Anlauf
      L     "SPS -> BR"._DBW_100_0      // Betriebsstunden Pumpe1
      L     "SPS -> BR"._DBW_102_0      // Betriebsstunden Pumpe2
      <I    
      SPB   OE5
      SPA   OE7


OE4:  R     #Schalten_Oelanlage_Pu2     // Umschalten
      S     #Umschaltung
      R     T      1
      S     "SPS -> BR"._DBX_202_6
OE5:  S     #Schalten_Oelanlage_Pu1
      SPA   OE12


OE6:  R     #Schalten_Oelanlage_Pu1     // Umschalten
      S     #Umschaltung
      R     T      1
      S     "SPS -> BR"._DBX_202_6
OE7:  S     #Schalten_Oelanlage_Pu2
      SPA   OE12


OE11: R     #Oelanlage_Anlauf           // Anlauf fertig
      R     T      1
OE12: NOP   0

      U(    
      O     #Oelanlage_Anlauf
      O     #Umschaltung
      )     
[COLOR=#ff0000]      FR    T      1[/COLOR]
[COLOR=#ff0000]      L     S5T#5S[/COLOR]
[COLOR=#ff0000]      SS    T      1[/COLOR]
      U     T      1
      R     #Start_Timer

Ist übrigens ein FB. Wieso da ein S5 Timer sein musste ist mir schleierhaft.
Ab den vielen Sprüngen wird mir direkt schwummrig.

mfG René
 
@René:
Du hast da aber auch ein wirklich Könner am Start gehabt ... 8)
Ich finde das auch schrecklich, was sich so manch einer als Code einfallen läßt um vielleicht ein paar Bytes an Code zu sparen aber dafür einen hohen Preis mit der Durchschaubarkeit bezahlt ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Omron war nicht einmal in der Lage FBs für die CANbus-Initialisierung zu liefern, die in jeder Situation funktionieren. Stellt man nämlich eine feste Zykluszeit ein, funktionieren die nicht mehr, weil da gepfuscht wurde und nicht auf das Ende des FINS-Kommandos getestet wurde.

Also ich glaube Dir, dass Du irgendwie ziemlich sauer bist, wenn Du nach Monaten damit nochmal hervorkommst.
Was sollen das denn für komische FBs sein.
Kann man die sich irgendwo runterladen ?

Arbeitest Du jetzt immer noch an dem Projekt?
 
Also ich glaube Dir, dass Du irgendwie ziemlich sauer bist, wenn Du nach Monaten damit nochmal hervorkommst.
Was sollen das denn für komische FBs sein.
Kann man die sich irgendwo runterladen ?

Arbeitest Du jetzt immer noch an dem Projekt?

Ich arbeite leider immernoch ab und zu in dem Projekt. Da sollen halt noch Erweiterungen rein (solche die in meinen anderen Projekten einwandfrei laufen und der Kunde gefallen dran gefunden hat)

Direkt veröffentlichen will ich das natürlich trotzdem nicht erstens soll nicht daraus ersichtlich werden WER das programmiert hat und auch nicht in welcher Anlage.

Nochmal n kleines Schmankerl, vonwegen InstanzDBs
screenshot.11.jpg


Ich such Verwendungsstelle #AK_Freigabe finde nur diese eine hier am Anfang des FBs. Denke mir "Kann doch nicht sein"
Suche dann in den Referenzen diesen Instanzdb. Ist doch herrlich:
screenshot.10.jpg


Solche S/R Orgien sind mir an sich schon ein Gräuel ich muss mich schon überwinden am Schluss des OB1 noch einen Baustein aufzurufen wo für den Notaus noch eine sichere Stellung gesetzt wird.
Aber hier wird echt der Vogel abgeschossen. Muss ich erwähnen dass etwa die hälfte dieser S/Rs eh zu 100% in der hälfte des Bausteins unbedingt in einen Zustand versetzt werden?

mfG René
 
....dass etwa die hälfte dieser S/Rs eh zu 100% in der hälfte des Bausteins unbedingt in einen Zustand versetzt werden?

.. das 50% eh zu 100% in der "Hälfte" des .... "Viertel nach Dreiviertel vor Um = Halb" ..... außer das man die Startsprungmarke AK2 nicht sieht ist das für mich noch lange keine Orgie .... :rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
.. das 50% eh zu 100% in der "Hälfte" des .... "Viertel nach Dreiviertel vor Um = Halb" ..... außer das man die Startsprungmarke AK2 nicht sieht ist das für mich noch lange keine Orgie .... :rolleyes:

Das meinte ich auch nicht als Orgie, sondern eher das was im Baustein abgeht wo die Referenzliste drauf verweist. Da wird 12 mal in einem Baustein auf die Instanz eines völlig anderen Bausteins geschrieben.

mfG René
 
Wiedermal geiles Schmankerl.

Code:
(*Auf nächste ganze Zahl aufrunden*)
IF (nSV*10) - TRUNC(nSV)*10 <> 0.0 AND nSV > 0 THEN
    Res := TRUNC(nSV) +1;
END_IF;
IF (nSV*10) + TRUNC(nSV)*10 <> 0.0 AND nSV < 0 THEN
    Res := TRUNC(nSV) -1;
END_IF;
IF nSV = 0 OR Einschaltsperre = 1 THEN
    Res := 0;
END_IF;

nSV und Res sind übrigens vom Typ REAL, Einschaltsperre ist BOOL.

Der Programmschnippsel funktioniert sogar (bis Siemens mal restriktiver mit dem Compiler wird, vermutlich)
Man könnt auch meinen Klammern kosten Geld oder bin ich der einzige der Vergleichsoperationen einklammert bevor die Resultate Bitweise verknüpft werden?

mfG René
 
Zuletzt bearbeitet:
Verstehe ich es richtig, daß hier eine Variable auf 0 überprüft wird, die definitionsgemäß überhaupt nicht null werden kann ??
Eine Zahl vom Datentyp Real kann auch Null sein, wieso denn nicht.
Problematisch kann es nur sein wenn man nach verschiedenen Gleitpunkt-Operationen hofft wieder bei Null zu landen, und dann aufgrund der Ungenauigkeiten im Real-Format eben nicht 0,0 sondern 0,000001 herauskommt.

Von den Datentypen her ist das prinzipiell Ok, es nutzt eben die automatische Typwandlung bei SCL aus. Es ist nur umständlich und nicht gerade optimal im Benzug auf Geschwindigkeit programmiert.
 
Verstehe ich es richtig, daß hier eine Variable auf 0 überprüft wird, die definitionsgemäß überhaupt nicht null werden kann ??

Nach der ersten Rechenoperation / Umwandlung ist generell empfehlenswert REAL nur noch auf größer, kleiner oder eben einen bestimmten Bereich zu vergleichen.

Gruß
Dieter
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hm. Ich meine mich aber erinnern zu können, daß eine Float-Zahl grundsätzlich nicht null werden kann, wegen der Spezifik der Mantisse / Exponent Darstellung, denn wenn ich einfach überall Nullen setze, wäre das ja null hoch null und folglich =1. Oder wurde diese Definitionslüke in S7 geschlossen, indem man einfach eine Abfolge von Nullen in als NULL definiert hat ?
 
Eine Zahl vom Datentyp Real kann auch Null sein, wieso denn nicht.
Problematisch kann es nur sein wenn man nach verschiedenen Gleitpunkt-Operationen hofft wieder bei Null zu landen, und dann aufgrund der Ungenauigkeiten im Real-Format eben nicht 0,0 sondern 0,000001 herauskommt.

Sobald da irgendein Messwert in den Wert reinspielt ist es extrem unwahrscheindlich dass da wieder irgendwo eine gerade Zahl wie ne Null rauskommt. Auch =10.0 oder =22.5 abzufragen ist bei Realzahlen mehr oder weniger sinnlos (IMHO).

Von den Datentypen her ist das prinzipiell Ok, es nutzt eben die automatische Typwandlung bei SCL aus. Es ist nur umständlich und nicht gerade optimal im Bezug auf Geschwindigkeit programmiert.

Was mich am meisten stört ist das hin und her gespringe mit der Typwandlung. Entweder man macht die Abfragen in Real (dann gehören IMHO auch die Konstanten in Real reingetippt. Klar geht 10 aber 10.0 Ist imho leserlicher).

Und eben es wäre rein von der Lesbarkeit her sinnvoll Vergleichsoperationen und die Arithmetik in Klammern zu verpacken bevor man sie logisch verknüpft. Arithmetik, Vergleichsoperationen und Logische Verknüpfungen ganz ohne etwas einzugruppieren finde ich extrem unleserlich.
Vor allem da Klammern offenbar bekannt waren. Aber warum man eine Multiplikation in Klammern setzt die doch sowieso höher Priorisiert ist als eine Addition. Aber den gesamten Arithmetik nicht in Klammern setzt um die Lesbarkeit zu erhöhen erschliesst sich mir nicht.

Geschwindigkeit ist bei den heutigen Maschinen ja eher Nebensache. Aber Leserlich und verständlich sollte das Zeug werden.

Und da helfen auseinander gerissene IF Konstrukte auch nicht so wirklich.

mfg René
 
Zuletzt bearbeitet:
Ich hätte es so gemacht.
Ein bisschen Kommentar und Klammerung und man sieht viel schneller was zusammen gehört.


Code:
(*Auf nächste ganze Zahl aufrunden*)
IF ((nSV - TRUNC(nSV)) <> 0.0) AND (nSV > 0.0) THEN  // nSV Positiv aufrunden auf nächstgrössere ganze Zahl
    Betrieb_Soll := TRUNC(nSV) + 1;
ELSIF ((nSV + TRUNC(nSV)) <> 0.0) AND (nSV < 0.0) THEN // nSV Negativ, abrunden auf nächstkleinere ganze Zahl
    Betrieb_Soll := TRUNC(nSV) - 1;
ELSE // nSV genau 0.0
    Betrieb_Soll := 0;
END_IF;

Da Betrieb_Soll im Programm nachher nur noch auf > oder < 0 abgefragt wird, hätte ich diesen gleich als INT definiert.
Unglücklich bin ich trotzdem damit, da eine echte 0 nie erreicht wird und somit immer als Betrieb_Soll zwischen -1 und +1 schwankt. Da wäre eine Hysterese sinnvoll gewesen.

mfG René
 
Zurück
Oben