SCL, String + DB. Kleine Frage

noeppkes

Level-1
Beiträge
150
Reaktionspunkte
5
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo an alle,

ich will in SCL einen String, der im DB20 liegt in Integer umrechnen, verarbeiten und in den DB10 zurückschreiben.

Ich habe dies versucht mit:

Code:
VAR_TEMP
  temp : INT;
END_VAR
 
// 5 Zecichen kopieren. (Format VZ + 4 Stellen: z.B. +1276 oder -0312)
temp := STRING_TO_INT(MID(IN:=DB20.DBB, L:=5, P:=13));
 
// Hier wird temp bearbeitet
 
//Nun möchte ich den INT-Wert wieder im gleichen Format zurückschreiben in den DB10 an Position 5. d.h. VZ + 4 Stellen
z.B. +0031 oder -8360

Stehe total auf dem Schlauch.
Wie kann ich dies lösen ?

Ich danke schon mal für euere Hilfe.

noeppkes ...
 
Wo klemmts denn genau?

Falls es schon mit dem kopieren ins temp klemmt, gib deine Quelle Symbolisch an.



Code:
VAR_TEMP
  temp : INT;
END_VAR
 
// 5 Zecichen kopieren. (Format VZ + 4 Stellen: z.B. +1276 oder -0312)
temp := STRING_TO_INT(MID(IN:=[COLOR=red]mein_DB.mein_String[/COLOR], L:=5, P:=13));
 
// Hier wird temp bearbeitet
 
//Nun möchte ich den INT-Wert wieder im gleichen Format zurückschreiben in den DB10 an Position 5. d.h. VZ + 4 Stellen
z.B. +0031 oder -8360
 
Zuviel Werbung?
-> Hier kostenlos registrieren
SCL, DB + String herausholen

Danke für deine Antwort,

jedoch habe ich glaube ich ein Datentyp-Problem.
Der DB (DB20, RCV_DB) ist als Array[1023] als char angelegt.
Ich möchte nun ab Position 13, 5 Zeichen (VZ + 4 Stellen) in einen Integer-Wert bringen.
Die Daten stehen ASCII codiert im DB.

Der Integer-Wert wird dann bearbeitet und im gleichen Format in den DB10
(SEND_DB) geschrieben. auch ASCII codiert.

Irgendwie klappt das bei mir nciht.

Hier noch einmal mein Code:
Code:
FUNCTION_BLOCK Telegrammbetrieb_rs485
// ...
 
// temporäre Variablen
VAR_TEMP
// ...
  temp : INT;
END_VAR
 
// ...
 
  temp := STRING_TO_INT(MID(IN:=s, L:=5, P:=13));
 
// Hier wird temp bearbeitet.
 
// temp schreiben als ASCII mit VZ + 4 Stellen mit führender 0 in den DB10 Pos. 13
 
DB10.DBB13 := INT_STO_STRING(temp);  // 5 Stellen: VZ + 4 Stellen. z.B.: +1230 oder -0031

Kann mir jemand die 2 Zeilen der Typumwandlung(DB nach INT und INT nach DB) korrigieren, damit ich mal weiterkomme ?
Danke.
noeppkes ...
 
Tippfehler. hier noch einmal

Danke für deine Antwort,

jedoch habe ich glaube ich ein Datentyp-Problem.
Der DB (DB20, RCV_DB_A) ist als Array[1023] als char angelegt.
Ich möchte nun ab Position 13, 5 Zeichen (VZ + 4 Stellen) in einen Integer-Wert bringen.
Die Daten stehen ASCII codiert im DB.

Der Integer-Wert wird dann bearbeitet und im gleichen Format in den DB10
(SEND_DB_a) geschrieben. auch ASCII codiert.

Irgendwie klappt das bei mir nicht.

Hier noch einmal mein Code:
Code:
FUNCTION_BLOCK Telegrammbetrieb_rs485
// ...
 
// temporäre Variablen
VAR_TEMP
// ...
  temp : INT;
END_VAR
 
// ...
// An Position 13 steht meine Temperatur mit Vorzeichen. (5 Zeichen länge).
  temp := STRING_TO_INT(MID(IN:=DB20.DBB, L:=5, P:=13));
 
// Hier wird temp bearbeitet.
 
// temp schreiben als ASCII mit VZ + 4 Stellen mit führender 0 in den DB10 Pos. 13
 
// Ab Position 13 soll die Temperatur (5 Stellen) geschrieben werden mit Vorzeichen.
 
DB10.DBB13 := INT_STO_STRING(temp);  // 5 Stellen: VZ + 4 Stellen. 
z.B.: +1230 oder -0031
 
// ...

Kann mir jemand die 2 Zeilen der Typumwandlung(DB nach INT und INT nach DB) korrigieren, damit ich mal weiterkomme ?
Danke.
noeppkes ...[/quote]
 
Hallo,
was siehst du denn in deinem SCL-Script in der Online-Ansicht ?
Nach meiner Meinung (hat Zefix auch schon geschrieben) übergibst du an die Funktion MID keinen String.
Sinnvollerweise würde ich mir dein ARRAY_OF_CHAR erstmal auf eine SCL-Variable transferieren (ggf. teilweise) und dann damit weiterarbeiten.

Was ist denn der eigentliche Sinn deines Bausteins ? Vielleicht lässt sich ja am Ansatz ja schon etwas ändern ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
SCL, DB + String

Hallo Larry Laffer,

Ich habe folgendes vor:

Aus dem DB20 an der richtigen Position die Istwerttemperatur (Format VZ + 4 Stellen, +1230) zu lesen.

Diese Temperatur soll berarbeitet werde und wieder an eine andere Adresse gesendet werden.
Gleiches Format: VZ + 4 Stellen

Das empfangen, auslesen und wandeln in INT funktioniert nun.
temp := STRING_TO_INT(MID(IN:=DB20.COMMENT[13], L:=5, P:=13));

Das zurückschreiben in den DB10 bekomme ich allerdings nicht geregelt.

Ich habe es probiert mit:
DB10.MULTIDATA[5]:=IN T_TO_STRING(temp);

Das Problem:
1. Fehlermeldung: ungültige Variable, obwohl Multidata im DB steht.
Der DB ist allerdings angelegt als:
struct, dann einzelne CHAR's (22 Stück, jedes hat einen Bezeichner), dann end_struct

2. Ungültiger Datentyp INT_TO_STRING(temp);
Hier wird temp beanstandet, obwohl temp als INT angelegt ist.

noeppkes...
 
Hallo,
die Wandler-FC's wollen IMMER in eine initialisierte Variable zurückschreiben bzw. damit arbeiten. Für dich heißt das :

Code:
VAR_TEMP
   hString : string [10] ;
END_VAR ;
 
hString := ''" ;
hString := INT_TO_STRING (temp) ;

Jetzt sollte deine Variable korrekt gewandelt sein.
Ich würde sie jetzt Byteweise an den Ziel-DB schicken.

Das Problem bei SCL ist, dass die Variablen beim compilieren immer bekannt und im Aufbau passend sein müssen.

Warum kopierst du die Bytes nicht gleich von dem einen in den anderen DB ?

Gruß
LL
 
Hallo,
die Wandler-FC's wollen IMMER in eine initialisierte Variable zurückschreiben bzw. damit arbeiten. Für dich heißt das :

Code:
VAR_TEMP
   hString : string [10] ;
END_VAR ;
 
hString := ''" ;
hString := INT_TO_STRING (temp) ;

Jetzt sollte deine Variable korrekt gewandelt sein.
Ich würde sie jetzt Byteweise an den Ziel-DB schicken.
Wie ?

Das Problem bei SCL ist, dass die Variablen beim compilieren immer bekannt und im Aufbau passend sein müssen.
O.K. Das ist einleuchtend.

Warum kopierst du die Bytes nicht gleich von dem einen in den anderen DB ?
Weill ich den Wert erst noch bearbeiten muss.
Das geht in einer INTEGER am einfachsten.

Das eigentliche Problem ist aber noch nicht gelöst.
Wenn ich die Int nach String wandle, bekomme ich doch nicht immer die passende Formatierung.
Ich benötige ab er immer das FormatVZ + 4 Stellen für den Wert
Wenn der INT-Wert z.B. 1 ist, dann mich int_to_string bestimmt nicht +0001 daraus oder ?

noeppkes ...


Gruß
LL[/quote]
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich benötige ab er immer das FormatVZ + 4 Stellen für den Wert
Wenn der INT-Wert z.B. 1 ist, dann mich int_to_string bestimmt nicht +0001 daraus oder ?

Ich würde da folgendermassen verfahren :
Code:
VAR_TEMP
   hString : string [10] ;
   bString at hString : array [-1..10] of byte ;
END_VAR ;
 
hString := ''" ;
hString := INT_TO_STRING (10000 + temp) ;
 
bString[1] := 43 ;  // ich glaube das ist der ASCII-Code von "+" sonst korrigieren

probier das mal.
Das versenden des neuen String per kopieren kannst du nun eigentlich auch ganz komfortabel mit der AT-Sicht von hString (also bString) machen ...

Gruß
LL
 
Danke

Danke noch einmal für deine ausführliche Hilfe.
Ich denke das hat mir geholfen.
Werde es heute abend ausprobieren.

noeppkes ...
 
Hallo Noeppkes, noch ein Hinweis:

INT_TO_STR kommt mit Vorzeichen zurück:

+1
+12
+123
+1234
-1234
-123
-12
-1

Bei kleinen Werten gibt es da mit deinem Format Probleme, du wolltest ja +0001 in den DB schreiben. Also mußt du das Vorzeichen abschneiden und an richtiger Stelle wieder einsetzen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@Ralle:
Das mit dem pos. Vorzeichen wusste ich auch noch nicht ...
Das erspart dann schon mal ein Problem.

@noeppkes:
Ich würde bei dem FB wie folgt vorgehen:
Als Übergabe-Parameter je einen ANY-Pointer für die Quell-Daten (und deren Länge) und die Ziel-Daten. Einen weiteren Parameter für den Korrekturwert.
Du zerlegst nun den 1. ANY-Pointer zu einer in SCL brauchbaren Adresse (genauso den 2. natürlich). Nun lädst du dir die Daten in eine interne Variable (kann vom Typ TEMP sein - am Anfang zum Probieren wäre aber ggf. eine STAT besser). Diese wandelst du in eine INT, addierst den Korrekturwert, formatierst das Ding, wandelst es wieder in einen String und transferierst den dann an die Ziel-Adresse, die du über den 2. ANY-Pointer erhalten hast.
--- Das ist nicht so kompliziert, wie es sich vielleicht anhört ...

Gruß
LL
 
Hi

INT_TO_STR kommt mit Vorzeichen zurück:

+1
+12
+123
+1234
-1234
-123
-12
-1

Bei kleinen Werten gibt es da mit deinem Format Probleme, du wolltest ja +0001 in den DB schreiben. Also mußt du das Vorzeichen abschneiden und an richtiger Stelle wieder einsetzen.
Schau dir doch mal die OSCAT-LIB an.
DWORD_TO_STRF

Auszug Handbuch:

DWORD_TO_STRF konvertiert ein DWORD, Word oder Byte in einen STRING fester
Länge. Der Ausgangsstring ist exakt N Stellen lang, wobei führende Nullen eingefügt
werden oder führende Stellen abgeschnitten werden.
Beispiel: DWORD_TO_STRF(5123, 6) = '005123'

DWORD_TO_STRF(5123, 3) = '123'


Anschliessend noch das Vorzeichen dazu.
P.S: Quellcode ist in SCL vorhanden.
 
Ich hab mal was zum Testen programmiert, ohne Any, auf herkömmliche Weise. Vielleicht kann das ja als Anregung dienen.

Code:
FUNCTION FC110 : INT

VAR_TEMP
    // temporäre Variablen
    iTemp, L, I : INT;
    strTemp: STRING[5];
    strTemp4: STRING[4];
    strTemp4_help: STRING[4];
    tempArray AT strTemp: ARRAY[0..6] OF CHAR; 
      
END_VAR

    // 5 Zeichen kopieren. (Format VZ + 4 Stellen: z.B. +1276 oder -0312)
    strTemp := '+0000';      //initialisieren!
     
    FOR I := 0 TO 4 DO
       tempArray[I+2] := DB20.Werte_CharArray[I + 13];
    END_FOR;   

    iTemp := STRING_TO_INT(strTemp);
   
    // Hier wird iTemp bearbeitet
    iTemp := iTemp + 1;
    IF iTemp > 9999 THEN
       iTemp := -9999;
    END_IF;  
      
    //den INT-Wert wieder im gleichen Format zurückschreiben in den DB10 an Position 5. d.h. VZ + 4 Stellen
    //z.B. +0031 oder -8360   
          
    strTemp4 := '0000';     //initialisieren!
    strTemp4_help :='0000'; //initialisieren!
     
    //ausschneiden ohne Vorzeichen!  
    strTemp4 := MID(IN:=INT_TO_STRING(iTemp), L:=4, P:=2);
    //Nullen auffüllen
    L := LEN(strTemp4);
    WHILE L < 4 DO
        strTemp4_help := CONCAT(IN1:='0',IN2:=strTemp4);
        strTemp4 := strTemp4_help;
        L := L + 1;
    END_WHILE;

    //das richtige Vorzeichen dazu    
    IF iTemp < 0 THEN
       strTemp := CONCAT(IN1 := '-'       // IN: STRING
                         ,IN2 := StrTemp4 // IN: STRING
                         );               // STRING
    ELSE  
       strTemp := CONCAT(IN1 := '+'       // IN: STRING
                         ,IN2 := StrTemp4 // IN: STRING
                         );               // STRING
    END_IF;
   
    //in den DB schreiben  
    FOR I := 0 TO 4 DO
       DB10.Werte_CharArray[I + 13] := tempArray[I+2];
    END_FOR;   
     
    ;
    FC110 := 100;
END_FUNCTION

Das funktioniert erstmal so. Meine erste Variante war mit Strings, die lief auch, ließ sich aber nicht so einfach für char umsetzen, weil die Siemensfunktionen das nicht mögen, wie mit scheint.
 
Zurück
Oben