Step 7 Wie bastel ich mir mit Double Integern einen String?

Qnkel

Level-1
Beiträge
99
Reaktionspunkte
6
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

baue gerade eine kleine Restzeitberechnung für eine Schrittkette.

Aktuell gehe ich so vor, dass bei Beginn die aktuelle Systemlaufzeit mit SFC64 (Time_Click) auslese und bei Ende nochmal. Subtrahieren und ich habe die Laufzeit.

Zuerst teile ich mit DIV_DI durch 60000 um Gesamt-Minuten zu erhalten (alles hinter dem Komma fällt bei der Operation ja weg, richtig? Sekunden sind unwichtig)
Dann teile ich wieder durch 60 um Gesamt-Stunden zu erhalten.
Dann nehme ich den Rest mit MOD_DI von Gesamt-Minuten durch 60 für die tatsächlichen Minuten.
Das Gleiche mit den Stunden und 24 für die tatsächlichen Stunden.
Die Gesamt-Stunden teile ich nochmal mit DIV_DI durch 24 für die Tage.

Oder geht es einfacher?

Auf jeden Fall hab ich jetzt Minuten, Stunden und Tage als Werte vom Typ DI.

Nun will ich einen String basteln, der in WinCC flexible innem EA-Feld angezeigt wird in Form von "00d 00h 00m" - mehr als 100 Tage werden es nicht!

Wenn ich bis jetzt richtig verstanden habe brauche ich ein String mit 13 Byte, weil das 1.Byte ja die Länge angibt und im 2.Byte die tatsächliche Länge hinterlegt wird.
Habe auch schon gesehen, dass es Funktionen geben soll aus DI einen String zu machen. Aber wie bastel ich das jetzt in mein gewünschtes Format?

Oder steinigt mich, wenn ich viel zu kompliziert denke!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Vorgehensweise wäre wie folgt :
Du errechnest dir aus deinem DINT die Tage, die Stunden und die Minuten als Einzel-Elemente. Der Wert, den du da hast, ist ja etwas auf Millisekunden-Basis.
Nun wandelst du dir diese Einzel-Komponenten in Strings um und verkettest die Teilstring dann mit Concat zu einem Gesamt-String.
Am Schönsten könntest du das in SCL erstellen ...

Gruß
Larry
 
SCL habe ich leider nicht.

Wenn ich das richtig sehe könnte ich da ja fast den Code, den ich bereits in CoDeSys habe (dort heißt es ST) kopieren.

--

edit:

So, CONCAT mag mich nicht. Gebe an "IN1" einen 2-Byte-String an (die gewandelten Tage) und an "IN2" kommt 'd', weil hinter den Zahlenwert der Buchstabe sein soll. RET_VAL hat ein 3-Byte-String (entsprechend meiner Logik).

Step7 meckert das 'd' das Format STRING[1] hat, aber STRING[254] erwartet wird. Warum erwartet der an den INs eine Summe von 256Byte??

edit2: Ja, ich bin dumm... dutzend Mal den Satz ignoriert, dass nur Symbole an den INs erlaubt sind.
 
Zuletzt bearbeitet:
Also erstens : Ja ... dein CodeSys-Code würde mit großer Wahrscheinlichkeit und/oder wenigen Änderungen auch von SCL "geschluckt" werden ...

Zweitens : Du mußt bei den String-Funktionen mehrere Dinge beachten. Dazu gehört auch, dass die Strings immer initialisiert sein müssen (also die Header-Information über die definierte Länge MUSS mindestens da sein - das wäre bei TEMP-Strings nicht automatisch der Fall).
Da ich String-Funktionen nur immer innerhalb von SCL einsetze weiß ich nicht, ob du nicht auch ein einzelnes Zeichen als Konstante übergeben kannst - in SCL ginge es.
Der Baustein erwartet nicht eine Summe von 256 Bytes an den IN's - aber er gibt dir einen String[254] als Rückgabewert zurück - der Wandler weiß ja im Vorfeld nicht, was da alles so passieren soll - also wer das wie benutzen möchte.

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich richtig erinnere gehen einzelne Zeichen oder Zeichengruppen in AWL/KOP am IN nicht, man muß diese vorher in eine Stringvariable schreiben oder erstellt sich gleich einen globalen DB, der die wichtigsten Konstanten Strings als deklarierte Variable enthält. Diesen Variablen kann man dann auch selbsterklärende Namen geben und sie an den Input legen.
 
Habe die Strings jetzt nicht initialisiert sondern im FB als STAT-Variablen mit entsprechender Länge angelegt.

Gebe ich Typ "String" ein, belegt die Variable volle 256Byte. Gebe ich z.B. "String[2]" ein für 2 Zeichen, belegt sie entsprechend 4 Byte.
Muss ich sie dann trotzdem nochmal initialisieren?

Bei den Strings, die nur die Zeichen "d ", "h " und "m" enthalten, habe ich diese direkt in der Variablentabelle als Anfangswert eingestellt.
Wenn initialisiert werden muss: Reicht es dafür, bei den anderen Strings auch einfach schonmal Dummy-Anfangswerte vorzugeben? Oder muss ich jedesmal ins 1.Byte die Gesamt-Länge reinschreiben?

Leider fehlt mir auch die Simulation in Step7 :(
 
Hi!

Nein, du musst sie nicht initialisieren, weil sie genauso wie deine anderen Variablen schon einen Anfangswert haben. Hier aber halt den Wert '' . Also nichts zwischen den Hochkommas.

Die Frage ist halt, was angezeit wird, bis deine Berechnung fertig ist. Da würden ja dann nur die Buchstaben stehen. Vielleicht solltest du während die Berechnung läuft folgendes anzeigen und dementsprechend bei den Anfangswerten und während der Berechnung wie folgt initialisieren:
??d ??h ??m

Gruß,

Ottmar
 
Zuletzt bearbeitet:
Die Frage ist halt, was angezeit wird, bis deine Berechnung fertig ist. Da würden ja dann nur die Buchstaben stehen. Vielleicht solltest du während die Berechnung läuft folgendes anzeigen und dementsprechend bei den Anfangswerten und während der Berechnung wie folgt initialisieren:
??d ??h ??m

Ja, die Variable "Restzeit", die aufm Panel angezeigt wird, hat als Anfangswert bereits "00d 00h 00m".

Ich würde die Laufzeit (DInt) an WinCC weitergeben und dort umformatieren.

Habe in WinCC flexible 2008 SP3 nichts gefunden, dass ich Millisekunden aus einem DInt direkt in Tage/Stunden/Minuten anzeigen lassen kann.
 
Flex macht das auch nicht selber - hat Hub ja auch nicht geschrieben ... 8)
Du mußt den String in der Visu basteln (würde ich jetzt nun nicht machen), vorausgesetzt deine Visu kann Scripte.
Oder du machst es, wie schon angefangen, in der SPS ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Jetzt is das Problem noch aufgetaucht, dass DI_STRING mir das Vorzeichen mit reinhaut.

Wie löse ich das am schlauesten?
Will ungern jetzt nochmal jeden String zwischenspeichern und durchn DELETE laufen lassen.
Wenn ja: wie funzt DELETE? Also von wo fängt der an zu zählen?
 
Die String-Routinen benötigen zwar den Header, zählen ihn aber nicht mit.
Ich würde da so vorgehen :
Du wandelst das als String um und schneidest dir hinterher mit MID den relevaten Teil heraus.
Willst du nur das Vorzeichen vorne heraus haben dann wäre das ab Pos.2 im String für Länge Stringlänge-1.
 
Ich würde das gar nicht mit Stringfunktionen machen, sondern mir den String aus einzelnen Zeichen zu Fuß zusammenstellen. Das wird letztendlich einfacher und vor allem wesentlich schneller als das mit den Stringfunktionen.
 
Habe in WinCC flexible 2008 SP3 nichts gefunden, dass ich Millisekunden aus einem DInt direkt in Tage/Stunden/Minuten anzeigen lassen kann.
Für deine Aufgabe ist SCL oder VB besser geeignet als AWL.
Da du kein SCL hast, aber flex schon, wäre VB der einfachere Weg.

Ich weiß nicht, ob dein Code die Stunden/Minuten immer 2stellig mit führenden Nullen ausgibt.
Wäre in VB kein Problem.
Oder Tage nur anzeigen, wenn auch Tage vorhanden sind. Gleiches natürlich mit den Stunden.
 
Codevorschlag in AWL, ohne Optimierung:
Code:
FUNCTION "TIME_TO_STRING" : STRING [254]
TITLE =Time to String im Format "00d 00h 00m", nur pos. Zeiten
VERSION : 0.1


VAR_INPUT
  IN : TIME ;	//Zeitwert, nur positive Zeiten erlaubt
END_VAR
VAR_TEMP
  wDbNr : WORD ;	
  di_tmp : DINT ;	
  diStellenwert : DINT ;	
  diZeichenwert : DINT ;	
  diTage : DINT ;	
  diStunden : DINT ;	
  diMinuten : DINT ;	
  diSekunden : BYTE ;	
END_VAR
BEGIN
NETWORK
TITLE =

//////////////////////////////////////////
// Vorbereitung, Stringadresse in Adressregister laden
      L     P##RET_VAL; 
      LAR1  ; 
      L     W [AR1,P#0.0]; 
      T     #wDbNr; 
      AUF   DB [#wDbNr]; 
      L     D [AR1,P#2.0]; 
      LAR1  ; 
//////////////////////////////////////////
// Stringlänge prüfen, Mindestlänge 11 Zeichen
      L     B [AR1,P#0.0]; 
      L     11; 
      <I    ; 
      SPB   FEHL; 
//
//////////////////////////////////////////
// Es sind keine negativen Zeiten zugelassen
      L     #IN; 
      T     #di_tmp; 
      L     0; 
      <D    ; 
      SPB   FEHL; 

//////////////////////////////////////////
// String Startwert "00d 00h 00m" setzen
      L     11; 
      T     B [AR1,P#1.0]; // Stringlänge setzen

      L     '0'; 
      T     B [AR1,P#2.0]; 
      T     B [AR1,P#3.0]; 
      L     'd'; 
      T     B [AR1,P#4.0]; 
      L     ' '; 
      T     B [AR1,P#5.0]; 
      L     '0'; 
      T     B [AR1,P#6.0]; 
      T     B [AR1,P#7.0]; 
      L     'h'; 
      T     B [AR1,P#8.0]; 
      L     ' '; 
      T     B [AR1,P#9.0]; 
      L     '0'; 
      T     B [AR1,P#10.0]; 
      T     B [AR1,P#11.0]; 
      L     'm'; 
      T     B [AR1,P#12.0]; 

//////////////////////////////////////////
// Einzelwerte erstellen
      L     #di_tmp; 
      L     L#86400000; 
      /D    ; 
      T     #diTage; 

      L     #di_tmp; 
      L     L#86400000; 
      MOD   ; 
      T     #di_tmp; 

      L     #di_tmp; 
      L     L#3600000; 
      /D    ; 
      T     #diStunden; 

      L     #di_tmp; 
      L     L#3600000; 
      MOD   ; 
      T     #di_tmp; 

      L     #di_tmp; 
      L     L#60000; 
      /D    ; 
      T     #diMinuten; 

      L     #di_tmp; 
      L     L#60000; 
      MOD   ; 
      T     #di_tmp; 

      L     #di_tmp; 
      L     L#1000; 
      /D    ; 
      T     #diSekunden; 
//////////////////////////////////////////
// In Zeichen konvertieren

// Tage
      L     #diTage; 
      L     L#10; 
      MOD   ; 
      T     #diStellenwert; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#3.0]; 

      L     #diTage; 
      L     #diStellenwert; 
      -D    ; 
      L     10; 
      /D    ; 
      L     L#10; 
      MOD   ; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#2.0]; 
// Stunden
      L     #diStunden; 
      L     L#10; 
      MOD   ; 
      T     #diStellenwert; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#7.0]; 

      L     #diStunden; 
      L     #diStellenwert; 
      -D    ; 
      L     10; 
      /D    ; 
      L     L#10; 
      MOD   ; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#6.0]; 
// Minuten
      L     #diMinuten; 
      L     L#10; 
      MOD   ; 
      T     #diStellenwert; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#11.0]; 

      L     #diMinuten; 
      L     #diStellenwert; 
      -D    ; 
      L     10; 
      /D    ; 
      L     L#10; 
      MOD   ; 
      +     48; // Zeichenwert von '0'
      T     B [AR1,P#10.0]; 

      SPA   ENDE; 
//////////////////////////////////////////
FEHL: CLR   ; 
      SAVE  ; 
      BE    ; 
ENDE: SET   ; 
      SAVE  ; 
END_FUNCTION
 
Zurück
Oben