3 Probleme in einem Baustein

Licht9885

Level-1
Beiträge
346
Reaktionspunkte
18
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin zusammen,

ich habe ein Baustein welcher Seriennummern in ein Array schreibt mit Datum und Zeit, in diesem Baustein wird auch das Schreiben der Seriennummern in eine CSV Datei angestoßen und der Vergleich ob diese Seriennummer schonmal benutzt wurde durchgeführt. Nun habe ich bei der Inbetriebnahme folgendes festgestellt.

1. Die erste Seriennummer nach Anlagenneustart wird zwar geschrieben aber Datum und Zeitstempel sind leer Seriennummer wiederum steht drin.
2. im CSV Feld stehen alle werte hintereinander sollen aber Untereinander pro Eintrag stehen
3. Die FOR schleife die den Vergleich durchführt wird nicht korrekt abgearbeitet


hier der Entsprechende Bausteincode:

IF bTrigger THEN
arBuffer[iBufferFill].sID := STRING_TO_CSVFIELD(in:=id1 , bQM:=FALSE );
arBuffer[iBufferFill].sDatum := STRING_TO_CSVFIELD(in:=fbSystemTime.sDatum , bQM:=FALSE );
arBuffer[iBufferFill].sUhrzeit := STRING_TO_CSVFIELD(in:=fbSystemTime.sZeit , bQM:=FALSE );
END_IF;

fbSystemTime(
bStart:= bTrigger,
sDatum=> ,
sZeit=> ,
bBusy=> ,
sDatum_File=> );
bWriteLog := bTrigger;

SR(SET1:= bTrigger, RESET:= bWriteFinish, );

fbFileopen(
sNetId := '5.39.61.62.1.1',
sPathName := sPhath,
nMode := FOPEN_MODEAPPEND,
ePath := ,
bExecute := bWriteLog,
tTimeout := t#3s,
bBusy => ,
bError => ,
nErrId => ,
hFile => hFile);

ton[0](IN:= SR.Q1, PT:= t#1s , Q=>bTriggerLog,);

fbFileWrite(
sNetId:= '5.39.61.62.1.1',
hFile:= hFile,
pWriteBuff:= ADR(arBuffer[iBufferFill]),
cbWriteLen:= SIZEOF(arBuffer[iBufferFill]),
bExecute:= bTriggerLog,
tTimeout:= t#3s,
bBusy=> ,
bError=> ,
nErrId=> ,
cbWrite=> );

ton[0](IN:= SR.Q1, PT:= t#3s , Q=>bWriteFinish,);

fbFileClose(
sNetId:= '5.39.61.62.1.1',
hFile:= hFile,
bExecute:= bWriteFinish,
tTimeout:= t#3s,
bBusy=> ,
bError=> ,
nErrId=> );

SR1(SET1:= bTrigger , RESET:= bIDOK or bSameID ,);

IF SR1.Q1 THEN
FOR i := 1 TO (iBufferFill-1) DO
IF (arBuffer.sID = id1) THEN
bSameID := TRUE;
bIDOK := FALSE;
EXIT;
i := (i+1);
bIDOK := TRUE;
END_IF;
END_FOR;
END_IF;


IF bResetCompare THEN
bSameID := FALSE;
i := 0;
END_IF;




Leider bin ich nicht so warm mit FOR Schleifen und Stringverabeitung weil ich es auch kaum nutze deswegen müsste ich hier mal bitte um Hinweise oder Lösungsansätze fragen um schnell zu einer funktionsfähigen Lösung zu kommen .


die Signal bTrigger & bReset Compare sind Eingänge welche über ein R_Trig reinkommen. Um Hinweise wo mein Fehler liegt währe ich dankbar.
 
Zuletzt bearbeitet:
1. Erster Zeitstempel fehlt.
Du trägst die Zeit in den Puffer ein, bevor Du sie gelesen hast. Ruf den Systemzeitbaustein mal ständig auf.
Code:
fbSystemTime(
 bStart:=NOT fbSystemTime.bBusy);

2. Textanordnung
STRING_TO_CSVFIELD macht nur Sinn, wenn Du auch die zugehörigen FBs zum Lesen/Schreiben der Daten verwendest. Da müsstest Du Dich mal im InfoSys schlau machen.
Vielleicht reicht es aber auch schon, die Textfelder von arBuffer um je ein Zeichen zu vergrössern und bei .sId und .SDatum ein Komma anzufügen, bei .sUhrzeit ein CR.

3. Schleife
iBufferFill-1 darf nicht kleiner sein als der Startwert 1 der Schleife
Das i:=(i+1) in der Schleife muss weg, das macht die FOR-Schleife selbst.

Für die Steuerung der File-FBs gibt es bessere Lösungen, aber ich denke Du hast erstmal genug zu tun.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo danke für die Antworten

habe gerade erfahren das ich das Logging doch nicht brauche deswegen entfällt Punkt 2 komplett (Gott sei dank)
mit der schleife habe gerade rumgetüftelt leider fällt mir nicht ein wie ich das iBufferFill - 1 so abfangen kann das es nicht kleiner wird als i?
 
Zwischendurch steht noch 2x der gleiche Timer mit verschiedenen Parametern, was sich ja beißt:
Code:
ton[0](IN:= SR.Q1, PT:= t#1s , Q=>bTriggerLog,);
...
ton[0](IN:= SR.Q1, PT:= t#3s , Q=>bWriteFinish,);
Tippfehler bei der TON-Nummer?



mit der schleife habe gerade rumgetüftelt leider fällt mir nicht ein wie ich das iBufferFill - 1 so abfangen kann das es nicht kleiner wird als i?
Du könntest z.B. von FOR auf WHILE umschwenken:
Code:
i := 1;
WHILE i < iBufferFill DO
   ...
   i := i + 1;
END_WHILE;
 
leider fällt mir nicht ein wie ich das iBufferFill - 1 so abfangen kann das es nicht kleiner wird als i?
Wo kommt das iBufferFill denn her, welche Werte können korrekterweise drin stehen und wie soll dann reagiert werden?
(In Deinem Programm ist es so: wenn iBufferFill 1, 0 oder <0 ist dann wird die FOR-Schleife nicht ausgeführt.)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du könntest z.B. von FOR auf WHILE umschwenken:
Code:
i := 1;
WHILE i < iBufferFill DO
   ...
   i := i + 1;
END_WHILE;
Das ist haargenau das gleiche wie die FOR-Schleife, nur umständlicher formuliert.
Code:
FOR i := 1 TO (iBufferFill-1) DO
  ...
END_FOR;

Harald
 
@Hucki:
Das ist legitim. In dem Fall wird der Code in der Schleife nicht bearbeitet und die Schleife wird im Prinzip übersprungen (weil sofort fertig).

Gruß
Larry
 
Ich hab' solche unlogischen Aufrufe bisher immer vermieden.
Und ich bin bis dato davon ausgegangen, das die FOR-Schleife mindestens einmal mit dem Startwert durchlaufen wird und erst am Ende die Erhöhung und Überprüfung auf den Endwert erfolgt.


Bei FOR kann man zwischendurch zumindest bei TIA auch nicht (mehr?) den Wert der Index-Variable selber manipuliern.
(Ich hatte vor einiger Zeit mal testweise ein i := i-1; eingefügt, um einen Zykluszeitüberlauf zu provozieren.)
Ist das auch allgemein so?
 
Zuletzt bearbeitet:
Schleifenendwert >= Schleifenstartwert wird nicht geprüft. Wenn das nicht gegeben ist, zählt die Schleife über den Integerüberlauf hinweg, bis der Zähler irgendwann mal den Endwert erreicht. Das kann je nach Typ des Schleifenzählers ziemlich lange dauern und natürlich auch interessantes Verhalten hervorrufen, falls der Schleifenzähler als Arrayindex benutzt wird.

Huckis WHILE-Lösung würde schon funktionieren, weil die Schleife bei iBufferFill=1 erst gar nicht durchlaufen wird.
Falls es unbedingt FOR sein soll, dann
Code:
IF iBufferFill>1 THEN
   FOR i:=1 TO iBufferFill-1 DO
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Schleifenendwert >= Schleifenstartwert wird nicht geprüft. Wenn das nicht gegeben ist, zählt die Schleife über den Integerüberlauf hinweg, bis der Zähler irgendwann mal den Endwert erreicht. Das kann je nach Typ des Schleifenzählers ziemlich lange dauern und natürlich auch interessantes Verhalten hervorrufen, falls der Schleifenzähler als Arrayindex benutzt wird.
Laut Larry und Harald ist das Verhalten anders.
:confused:


Huckis WHILE-Lösung würde schon funktionieren, weil die Schleife bei iBufferFill=1 erst gar nicht durchlaufen wird.
Das Funktionieren des WHILE-Konstrukts stand auch nicht zur Debatte, sondern das der FOR-Aufruf schon genau das Gleiche macht (also ggf. keinen Schleifendurchlauf), aber dabei einfacher formuliert ist.
 
Naja ... ich weiß es auch eigentlich nicht aus der CodeSys/BeckHoff-Welt.
Wobei ich schon öfter Schleifen hatte, bei denen "StartWert" und/oder "EndWert" Variablen waren.

Gruß
Larry

Nachsatz : wenn ich "Endwert" < "StartWert" habe dann läuft die Schleife (aus eigener Erfahrung) auch nur wenn ich "By -1" als Schrittweite mit hinzufüge ...
 
Weil die Systeme sonst auch bei jedem Pups meckern und hier mal trotz unlogischer Anweisung seitens des Programmierers nicht?
:confused:
Ob die Anweisung vielleicht unlogisch ist kann der Compiler nicht wissen, weil der Vergleichsausdruck mit einer Variable gebildet wird, deren Wert erst zur Laufzeit bekannt ist. Deshalb ist es zulässig daß der Vergleichsausdruck schon gleich bei der ersten Prüfung noch vor dem ersten Durchlauf nicht erfüllt ist und die Schleife verlassen wird ohne sie auch nur einmal auszuführen.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Compiler ist mir klar.
CPU hätte ich erwartet. Ähnlich falschem Arrayindex.

Naja, halt vergebens auf "logische" Schleifenbedingungen geachtet und demzufolge machmal etwas umständlich programmiert.
Kann ich mir in Zukunft dann sparen. Schön das wir drüber gesprochen haben.
:ROFLMAO:
 
Zurück
Oben