Rechnen mit SCL

hulla66

Level-1
Beiträge
12
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen.

Ich habe mal wieder ein Problem zu lösen, wo die Lösung für mich nicht direkt ersichtlich ist. Ich lese von einem Sensor einen AD-gewandelten Wert ein. Dieses rechne ich um, damit ich ihn anschließend in einem DB speichern kann. Meine Formel, die in SCL umzusetzen ist lautet:

((MW-17944)/32768)*10

MW hat hierbei den Typen INT. Sobald ich aber alles in INT mache und die Division durchführe meckert der Compiler. Um einen datensatz im DB speichern zu können, muss dieser in WORD vorliegen. INT kann ich dabei leicht konvertieren, REAL macht da mehr Probleme.

Anebi noch mein Codeausschnitt

PHP:
VAR
  // statische Variablen
   i                    : INT := 0;
   DIFF                 : INT;
   MW                   : REAL;
   MW_END               : INT;
END_VAR
VAR_INPUT
    Messwert_IN         : INT;
END_VAR

PHP:
 IF (DB105.DX518.1) THEN
            MW := ABS(((INT_TO_REAL(Messwert_IN)-17616.0))/32767.0*100.0); // /32768)*100
            MW_END:=  REAL_TO_INT(MW); 
            DB105.DW[416+i*2] := INT_TO_WORD(MW_END);
 
            IF i > 49 THEN
                DB105.DX518.1 := FALSE; //Aktiv-Bit entfernen
                i := 0;
            END_IF;
 
Was ist denn nun deine Frage?
Der Code, den du angegeben hast läßt sich bei mir jedenfalls übersetzen.
Was mit nicht gefällt, sind die direkten Zugriffe auf den DB105, aber das nur nebenbei.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Ralle:
ich glaube, ich verstehe das Problem ...

@hulla66:
Bei direkten Zugriffen auf Speicherstellen kannst du nur BYTE, WORD oder DWORD verwenden. Das macht SCL leider nunmal so. Wenn du dass umgehen willst, dann geht das nur symbolisch und das funktioniert nur, wenn dem SCL-Compiler der Aufbau des Ziel bekannt ist.

Wenn du nicht möchtest, dass bei der Zuweisung der direkt adressierten Speicherstellen "etwas in die Hose geht", dann solltest du auf die Typ-Konvertierungen verzichten und anstelle dessen auf die zu übertragenen Variablen eine AT-Sicht in dem anderen Format machen ... Dein Ursprungswert wird sonst ggf. falsch gewandelt ...

An deinem Beispiel :
Code:
[COLOR=#000000][COLOR=#0000cc][/COLOR][COLOR=#006600][FONT=Courier New]VAR
  [/FONT][/COLOR][FONT=Courier New][COLOR=#ff9900]// statische Variablen
   [/COLOR][COLOR=#0000cc]i                    [/COLOR][COLOR=#006600]: [/COLOR][COLOR=#0000cc]INT [/COLOR][COLOR=#006600]:= [/COLOR][COLOR=#0000cc]0[/COLOR][/FONT][FONT=Courier New][COLOR=#006600];
   [/COLOR][COLOR=#0000cc]DIFF                 [/COLOR][COLOR=#006600]: [/COLOR][COLOR=#0000cc]INT[/COLOR][/FONT][FONT=Courier New][COLOR=#006600];
   [/COLOR][COLOR=#0000cc]MW                   [/COLOR][COLOR=#006600]: [/COLOR][COLOR=#0000cc]REAL[/COLOR][/FONT][FONT=Courier New][COLOR=#006600];
   [/COLOR][COLOR=#0000cc]MW_END               [/COLOR][COLOR=#006600]: [/COLOR][COLOR=#0000cc]INT[/COLOR][/FONT][COLOR=#006600][FONT=Courier New];[/FONT][/COLOR][/COLOR]
[COLOR=#000000][COLOR=#006600][FONT=Courier New]   w_MW_End at MW_End   : WORD ;
[/FONT][/COLOR][FONT=Courier New][COLOR=#0000cc]END_VAR
VAR_INPUT
    Messwert_IN         [/COLOR][COLOR=#006600]: [/COLOR][COLOR=#0000cc]INT[/COLOR][/FONT][COLOR=#006600][FONT=Courier New];
[/FONT][/COLOR][COLOR=#0000cc][FONT=Courier New]END_VAR  [/FONT]
[/COLOR][/COLOR]
[COLOR=#000000][COLOR=#0000cc]und im Programm dann :[/COLOR][/COLOR]
[COLOR=#000000][COLOR=#0000cc][/COLOR][/COLOR] 
[COLOR=#000000][COLOR=#0000cc][FONT=Courier New][COLOR=#0000cc]DB105[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]DW[/COLOR][COLOR=#006600][[/COLOR][COLOR=#0000cc]416[/COLOR][COLOR=#006600]+[/COLOR][COLOR=#0000cc]i[/COLOR][COLOR=#006600]*[/COLOR][COLOR=#0000cc]2[/COLOR][COLOR=#006600]] := [/COLOR][COLOR=#0000cc]w_[/COLOR][COLOR=#0000cc]MW_END [/COLOR][/FONT][COLOR=#006600][FONT=Courier New];[/FONT]
[/COLOR][/COLOR][/COLOR]

Gruß
LL
 
Hallo zusamen,

ich habe auch eine Frage was das rechnen in SCL angeht. Ich habe einen AWL-Code den ich gerne in SCL umschreiben möchte. Da muss ja auf Punkt vor Strichrechnung geachtet werden oder?

Mein Code in AWL wäre (Alles REAL-Werte):

L #AER
L #UGREBR
-R
L #D1
*R
L #D2
/R
L #UGRNB
+R
T #REAW


Meine Idee in SCL:
REAW:=(AER - UGREBR) * D1 / D2 + #UGRNB;

Oder ist es besser mit Zwischenergebnissen zu arbeiten? Macht den Code natürlich länger.


Danke euch
 
Meine Idee in SCL:
REAW:=(AER - UGREBR) * D1 / D2 + #UGRNB;
Kannste so lassen. Ist richtig so. (bis auf die Schreibweise mit/ohne '#' davor, die kann variieren je nach SCL-Version)

Oder ist es besser mit Zwischenergebnissen zu arbeiten? Macht den Code natürlich länger.
Das macht den Quellcode länger (und eventuell übersichtlicher) - aber nicht unbedingt das ausführbare Compilat.

Beim SCL-Compiler für S7-300 ist es manchmal hilfreich, mit Zwischenergebnissen zu arbeiten, weil der Compiler ziemlich schlecht compiliert/optimiert. Wenn es auf Effizienz ankommt, dann schau Dir für verschiedene Quellcode-Varianten die Größe des erzeugten Bausteins an oder schau auch mal den erzeugten AWL-Code an (*), um zu sehen, wo man dem SCL-Compiler unter die Arme greifen kann, sprich den Quellcode anders formuliert, damit der dumme Compiler ;) den besser umsetzt.

(*) AWL-Code ansehen: den erzeugten Baustein in einen anderen Bausteine-Ordner kopieren (z.B. anderes Projekt), dann kann er im AWL-Editor geöffnet werden.

Harald
 
Hallo,

funktioniert super auch ohne Zwischnergebnissen.

Wollte jetzt mal etwas runden, bekomme da aber irgendwie kein vernünftiges Ergebnis. Irgendwas mach ich da falsch.

L #REAW (REAL)
L #UGRNB (REAL)
-R
L #D1 (REAL)
*R
L #D2 (REAL)
/R
RND
L #UGRAB (INT)
+I
T #AA (WORD)

In SCL:
AA:=(DINT_TO_WORD(ROUND(REAW - UGRNB * D1 / D2)) + (INT_TO_WORD(UGRAB));

Bekomme die Meldung unzulässige Operandentypen
 
WORD ist kein Datentyp zum Rechnen. Es ist einfach eine Ansammlung von 16 Bits.

Code:
AA:=DINT_TO_INT(ROUND(REAW - UGRNB * D1 / D2)) + UGRAB;

Harald
 
Zurück
Oben