TIA Wie muss man eine Berechnung aus AWL in SCL Übersetzen?

Ich habe noch eine Frage:

Das ist meine AWL Code um die Zeit zu messen wenn der Schritt aktiv ist:

Code:
      L     #timeS2
      L     #timeS1
      -D
      T     #stepTime

Wenn aber die Freigabe fehlt, dann soll eine Pause gemacht werden:

Code:
      L     #timeS2
      L     #stepTime
      -D
      T     #timeS1

Zusammen gefasst sieht das so aus:
Code:
// neuer Schritt ?
      L     #l_stepNr
      L     #stepNr
      <>I
      =     #stepOnce
// Startzeit des Schrittes
      U     #stepOnce
      SPBN  ntim
      L     #stepNr
      T     #l_stepNr
      L     0
      T     #stepTime
      CALL  TIME_TCK
         RET_VAL :=#timeS1
// aktuelle Zeit
ntim: CALL  TIME_TCK
         RET_VAL :=#timeS2
// Zeitmessung unterbrechen, wenn keine Freigabe
      SET
      UN    #I_Freigabe_x
      SPBN  kkfr
      L     #timeS2
      L     #stepTime
      -D
      T     #timeS1
kkfr: NOP 0
// Zeitdifferenz seit Eintritt
      L     #timeS2
      L     #timeS1
      -D
      T     #stepTime

Denn Teil aus hochzählen und runterzählen habe ich so übersetzt:

Code:
 IF #I_Freigabe_x = 1 THEN
        #timeS2 := TIME_TCK();
        #stepTime := #timeS2 - #timeS1;
        
        
    ELSE
        #timeS1 := #timeS2 - #stepTime;
    END_IF;

Aber bei dem ELSE bekomme ich denn Fehler, dass die Datentypen nicht zusammen passen.
bzw "-" ist nicht kompatibel mit dem Daten Typ time und UDint

Wie kann ich das anpassen?
 
Zuletzt bearbeitet:
Kein Problem,

ohne den komplette Code jetzt angeschaut zu haben, musst du nachschauen, welche Datentypen du hast.
Ich vermute mal, dass dein #stepTime ein WORD oder DWORD ist.

Mit WORD und DWORD kann man in SCL nicht rechnen ( +-/*.... ) Du müsstest diesen auf INT DINT umstellen,
insofern dies dein Programm nicht anderweitig beeinflusst.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Juhu,

eine Alternative wäre auch gewesen, den Operant auf Word / Dword zu lassen und ihn nur zum berechnen zu konvertieren:
Dass würde ich persönlich allerdings nicht machen bzw. man müsste es nur machen wenn der Wert zwingend WORD oder DWORD bleiben muss.

#timeS1 := #timeS2 - WORD_TO_INT(#stepTime);

bzw. wenn es ein WDORD ist:
#timeS1 := #timeS2 - DWORD_TO_DINT(#stepTime);
 
Bei AWL teilst du der CPU mit den operatoren mit was sie tun soll. +I addiert zwei 16 Bit Integer +D addiert zwei Double Integer etc. Völlig egal was du da in den Akku geladen hast, der Akku hat nämlich keinerlei Info zum Datentyp.

In SCL Ist der Operator aber immer gleich + addiert alles was sich irgendwie addieren lässt. Aber was soll er addieren wenn du ein Timeformat und ein Integer addieren willst. Dann musst du z.B. so explizit vorgeben was für Datentypen zu verrechnen sind. z.B. so:
#integerZiel := TIME_TO_DINT(DINT_TO_TIME(#dintzeit) - #timevariable);
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ah ok. Danke für eure Hinweise. Ich habe erst gestern mit SCL angefangen und es ist noch etwas ungewohnt. Hier auf jeden Fall meine Schrittkette: Dazu gibt es dann immer eine Interface was ich in meinem Baustein Logik aufrufe


AWL
Code:
CALL  "test", "test_DB"
         I_Freigabe_x :=#freigabe_test
         I_Reset_x    :="Abl".Test.Reset_x
         StepNr_b     :="GlobalDB".stepnr
         IQ_Busy_x    :="Abl".Test.Busy_x
         IQ_Start_x   :="Abl".Test.Start_x

Code:
REGION Infrastruktur für Schrittkette
    (*
    Befehle in der Schrittkette:
    
    "StepOnce" liefert einen Impule wenn eine neuer Schritt gestartet wird.
    
    "StepTime" liefert die Zeit die der Schritt aktiv ist. Bei Freigabe = 0 
    wird die Zeit auf Pause gesetzt. 
    
    Mit "#stepTime > 4000" kann man z.B. eine Zeit für den nächsen
    Schritt nutzen
    *)
    
    (*Busy setzen oder rücksetzen bei StepNr grösser als 0*)
    IF #stepNr > 0 THEN
        #IQ_Busy_x := 1;
    ELSE
        #IQ_Busy_x := 0;
    END_IF;
    
    (*Start Schrittkette*)
    IF #IQ_Start_x AND NOT #IQ_Busy_x THEN
        #stepNr := 1;
    END_IF;
    
    (*Reset Schrittkette*)
    IF #I_Reset_x THEN
        #stepNr := 999;
    END_IF;
    
   // Infrastruktur für Zeitberechung
    IF #l_stepNr <> #stepNr THEN
        #stepOnce := 1;
        // Stepnummer wird mit Zwischenspeicher gleichgesetzt
        #l_stepNr := #stepNr;
        #stepTime := 0;
        // Systemzeit wird in timeS1 geschrieben
        #timeS1 := TIME_TCK();
    ELSE
        #stepOnce := 0;
    END_IF;
    
    // Zeitberechnung für steptime
    IF #I_Freigabe_x = 1 THEN
        #timeS2 := TIME_TCK();
        #stepTime := #timeS2 - #timeS1;
    ELSE
        #timeS1 := #timeS2 - #stepTime;
    END_IF;
    
END_REGION
REGION Schrittkette
    CASE #stepNr OF
            
            
        1: (* Schritt *)
            //------ setzen------------------------------------        
            "Lampe80.0" := 1;
            //------ rücksetzen--------------------------------
            
            // Weiter zum nächsten Schritt---------------------
            IF "SchalterE80.0" = 1
            THEN
                #stepNr := #stepNr + 1;
            END_IF;
            
            
            
            
            
        2: (* Schritt *)
            //------ setzen------------------------------------
            "Lampe80.1" := 1;
            //------ rücksetzen--------------------------------
            
            IF "SchalterE80.1" = 1
            THEN
                #stepNr := #stepNr + 1;
            END_IF;
            
            
            
        3: (* Schritt *)
            //------ setzen------------------------------------
            "Lampe80.2" := 1;
            //------ rücksetzen--------------------------------
            
            IF "SchalterE80.2" = 1
            THEN
                #stepNr := #stepNr + 1;
            END_IF;
            
            
            
        4: (* Schritt *)
            //------ setzen------------------------------------
            "Lampe80.3" := 1;
            //------ rücksetzen--------------------------------
            
            IF "SchalterE80.3" = 1
            THEN
                #stepNr := #stepNr + 1;
            END_IF;
            
            
        5: (* Schritt *)
            //------ setzen------------------------------------
            //------ rücksetzen--------------------------------
            
            IF #stepTime > 4000
            THEN
                #stepNr := 999;
            END_IF;
            
        998: // Immer letzter Schritt alles zurück setzen. 
            //------ setzen------------------------------------
            //------ rücksetzen--------------------------------
            
            "Lampe80.0" := 0;
            "Lampe80.1" := 0;
            "Lampe80.2" := 0;
            "Lampe80.3" := 0;
            "Lampe80.4" := 0;
            
        999: (* letzter Schritt und Infrastruktur *)
            REGION Infrastruktur
                #stepNr := 0;
                #l_stepNr := 0;
                #stepTime := 0;
            END_REGION
            ;ELSE; END_CASE;
    END_REGION
 
Ich habe jetzt nicht alles gelesen aber ich würde an deiner Stelle versuchen, Funktionen zu vereinfachen:

IF #stepNr > 0 THEN
#IQ_Busy_x := 1;
ELSE
#IQ_Busy_x := 0;
END_IF;

könnte man z.B. so vereinfachen:

#IQ_Busy_x := #stepNr > 0;

sind schon mal 4 Zeilen gespart und einfach zu lesen.
 
Ich habe jetzt nicht alles gelesen aber ich würde an deiner Stelle versuchen, Funktionen zu vereinfachen:



könnte man z.B. so vereinfachen:

#IQ_Busy_x := #stepNr > 0;

sind schon mal 4 Zeilen gespart und einfach zu lesen.

Zum Verständnis, ich muss nicht immer eine IF nutzen um etwas auszuführen.

IQ-Busy_x ist das Verknüpfungsergebnis aus stepNr bei > als 0? Das Else ist dann wenn das VKE nicht erfüllt ist?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Else ist dann wenn das VKE nicht erfüllt ist?

Ja, dass ist richtig. Aber in deinem Falle, wo du nur ein Bit auf TRUE setzen möchtest wenn eine Variable >0 ist reicht dir auch
die einfache Variante

#IQ_Busy_x := #stepNr > 0;

Nein, man braucht kein IF, um irgendetwas zu machen. Es macht natürlich Sinn es zu nutzen ( wenn es Sinn macht ).
 
Ja, dass ist richtig. Aber in deinem Falle, wo du nur ein Bit auf TRUE setzen möchtest wenn eine Variable >0 ist reicht dir auch
die einfache Variante



Nein, man braucht kein IF, um irgendetwas zu machen. Es macht natürlich Sinn es zu nutzen ( wenn es Sinn macht ).

Wann macht es Sinn das If zu nutzen?
 
Nehmen wir an, man möchte etwas mehr machen, wenn etwas zutrift. Z.B. diverse Zeilen Code Ausführen wenn ein Zustand eingetreten ist.
Du hattest ja jetzt z.B. nur einen Wert, welcher eine Bool-Variable auf True setzen soll, wenn >0. Hier braucht man kein IF.
Nehmen wir an, wenn dein Wert > 10 ist, möchtest du 10-20 Zeilen Code ausführen mit irgendeiner Funktion, dann würde man dies in ein IF ... ELSIF....ELSE...ENDIF
packen können. ( ELSIF / ELSE braucht mal natürlich nicht zwingend ).

Ich denke du solltest dich mal einlesen in das Thema SCL da du zu sehr versuchst deinen AWL Code möglichst 1:1 in SCL umzusetzen.
Beispiel
U E0.0
= A 0.0

versuchts du umzusetzen in

IF E 0.0 THEN
A 0.0 := TRUE;
ELSE
A0.0 := FALSE;

Dass ist nicht der Sinn der Sache. Man muss in SCL etwas umdenken. Dann kann man auch "lesbare" Programme schreiben mit möglichst wenig
Zeilen. Also möglichst wenig Zeilen heißt nicht dass etwas gut ist aber wenn man einfache Sachen kompakt und verständlich schreibt, hat man
es einfach leichter.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... Ich denke du solltest dich mal einlesen in das Thema SCL da du zu sehr versuchst deinen AWL Code möglichst 1:1 in SCL umzusetzen.
Beispiel
U E0.0
= A 0.0

versuchst du umzusetzen in

IF E 0.0 THEN
A 0.0 := TRUE;
ELSE
A0.0 := FALSE;

Dass ist nicht der Sinn der Sache. Man muss in SCL etwas umdenken. ...
Sorry, DeltaMikeAir, aber der TE hat doch versucht, eine (zwar zweizeilige) Zuweisung in AWL zu ersetzen durch eine IF-Abfrage in SCL. Das war schon viel zu viel des Umdenkens! Völlig unnötig.
Wie fast immer gilt: weniger (umdenken) ist oft mehr (Geradlinigkeit).
Die AWL-Zuweisung
U E0.0
= A0.0
lässt sich problemlos als SCL-Zuweisung mit
A0.0 := E0.0
formulieren.
Das "Umdenken" ist nur insoweit nötig, als in AWL die ZielVariable A0.0 zuletzt genannt wird und in SCL zuerst.
Wenn es in einer Aufgabenstellung lapidar heisst "wenn Bedingung A erfüllt ist, dann soll die Variable X den Wert Y annehmen", dann sollte man nicht an "IF-THEN" denken, sondern an "IF-THEN-ELSE" und den Aufgabensteller sofort nageln, was denn in dem Falle passieren soll, wenn die Bedingung A nicht erfüllt ist!
Viele denken, die Antwort darauf sei bereits implizit in der Aufgabenstellung enthalten und sagen dann etwas verwirrt "ist doch klar!".
Aber genau das (nämlich klar) ist es eben nicht und genau daraus resultieren regelmässig die Missverständnisse!
Den ELSE-Zweig darf man nur weglassen, wenn im ELSE-Fall tatsächlich absolut gar nichts passieren soll!!!
Aber das ist oft nicht so gemeint. Also, wenn der ELSE-Fall - aus welchen Gründen auch immer - verschwiegen wird: unbedingt nachhaken und klären!
Wenn sich dabei herausstellt, im Fall A soll X true sein und im Fach Nicht-A soll X false sein, dann spricht das für eine simple WertZuweisung anstelle einer kaum zu rechtfertigenden IF-THEN-ELSE-Konstruktion.
Leider lernt man in ProgrammierKursen etc. die VergleichsOperatoren meistens nur im Zusammenhang mit IF-Abfragen kennen, manchmal auch in Case-Selektionen. Darum kommen viele gar nicht erst auf die Idee, sie einfach in Zuweisungen zu benutzen. Und schwupps wird etwas in einer IF-Abfrage verpackt, was nicht unvermeidlich dort hingehört.

Will man R (Rücksetzen) oder S (Setzen) aus AWL in SCL umsetzen, so hat man aber den Fall, dass man sinnvoll eine IF-Abfrage (nämlich eine ohne den ELSE-Zweig!) programmieren kann (aber nicht muss).
Z.B. lässt sich eine Hysterese so programmieren
IF Temp > 22 THEN Heizung := false
IF Temp < 20 THEN Heizung := true
Wenn Temp also im Bereich 20 ... 22 liegt, soll tatsächlich nichts (neues) passieren, sondern der bisherige Zustand (bewusst) beibehalten werden.
Dies kann natürlich auch in SCL ohne IF und ohne CASE programmiert werden, aber es ist dann für viele (Elektriker ausgenommen, die einen Blick für "SelbstHaltung" haben) nicht so gut lesbar.
Gruss, Heinileini
 
Zurück
Oben