Funktion wird nicht in einem Zyklus durchlaufen

Bensen83

Level-1
Beiträge
777
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich habe folgendes Problem.

Ich rufe in einer CASE Struktur im CASE 104 einen FC auf, welcher mir verschiedene Umwandlungen durchführt.
Wenn er fertig ist, ändert sich eine Variable von 0.0 auf -999.999.
Wenn ich den Case 104 durchlaufe und direkt nach dem aufrufen des FC´s in den CASE 105 laufe, dann schreibt er mir allerdings die Variable nicht auf -999.999, sonder verändert garnichts.
Es ist so, als würde die Funktion nicht durchlaufen.
Wenn ich allerdings nicht weiter laufe und im case 104 verharre, ändert sich die Variable auf -999.999. Es kommt mir irgendwie so vor, als würde die Funktion mehr als einen Zyklus brauchen.
Ich habe sie auch schon in FUB aufgerufen und den aufruf mit dem AUSgang ENO zurückgenommen, dann sollte sie ja auf jeden Fall durchlaufen sein, aber dort ist es der gleiche effekt. erst wenn ich sie dauernd aufrufe, dann funktioniert es. hat jemand ne idee?
 
Wenn du jetzt noch sagen würdest welche Funktion du da aufrufst,
diese evtl. sogar posten kannst, dann wäre schon viel Grundlage einer vernünftigen Antwort geschaffen.

Mfg
Manuel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also habe die jetzt nicht hier am rechner, aber es ist eien slbst geschriebene SCl Funktion.
Diese wandelt einen RS232 Lesepuffer, welcher in einem DB steht in ein Array von Strings um. DIese Umwandlung erfolgt durch indirektes lesen und schreiben der DBs. Hilf dir das etwas weiter?
 
Hier der Code

Also ich Rufe die Funktion "Keyence to real" hier in der Case auf: ( Step 104)

Code:
  //  Abfrage ob neue Daten vorhanden sind   
    104:
        IF  "Steuerung_Keyence".Austausch.Lesen.Allgemein.Neue_Daten_vorhanden = TRUE THEN
            
                "Steuerung_Keyence".Austausch.Lesen.Allgemein.anfordern := FALSE;
        END_IF;
        
        IF  "Keyence_Lesebereich".Lesebyte[1] = "Steuerung_Keyence".Konstanten.ASCII_M AND
            "Keyence_Lesebereich".Lesebyte[2] = "Steuerung_Keyence".Konstanten.ASCII_A AND
            "Keyence_Lesebereich".Lesebyte[3] = "Steuerung_Keyence".Konstanten.ASCII_Komma THEN
                
                
                "Daten_Keyence".Lesungen.Hand.Anzahl_Werte := Keyence_to_Real(Laenge_Paket :=  "Steuerung_Keyence".Austausch.Lesen.Allgemein.Laenge// IN: INT
                ,DB_Paket :=  "Keyence_Lesebereich"// IN: BLOCK_DB
                ,Startbyte_Paket :=  0// IN: INT
                ,DB_Real :=  "REALTEST"// IN: BLOCK_DB
                ,Startbyte_Real :=  0// IN: INT
                ); // INT
                 
               
                IF  "REALTEST".REAL_01 = -999.999 THEN 
                    
                    //"Steuerung_Keyence".Umwandeln.Hand.Start := FALSE;
                    "Steuerung_Keyence".Allgemeines.State := 0;
                ELSE
                    "Steuerung_Keyence".Test := "Steuerung_Keyence".Test + 1;
                END_IF;
        END_IF;

Habe jetzt eine Abfrage auf -999 rein gemacht, bis dies erreicht ist, wird eine testvariable hochgezählt, welche mir die Zyklen Zählt. die Funktion braucht im Moment ca. 5-7 Zyklen, bis sie die Werte raus gibt.

Hier die Funktion:

Code:
FUNCTION FC951 : INT

// Diese Baustein konvertiert ein vom Keyence Messystem empfangenes Datenpaket in Reals
VAR_INPUT
   Laenge_Paket : INT;
   DB_Paket : BLOCK_DB;
   Startbyte_Paket : INT;
   DB_Real : BLOCK_DB;
   Startbyte_Real : INT; 
END_VAR
VAR_TEMP
    
    Modus : INT;                // 1 = MA --> Es wurde nur eine Messung abgerufen
    Kanal : INT;                // 2 = AD --> Es wurden mehrere Messungen abgerufen   
    Realzahl : REAL;            // Errechnete Realzahl
    Teiler_Realzahl : REAL;     // Gibt an, durch welchen Faktor die Zahl geteilt werden soll
    Zaehler : INT;              // Zaehler für Schleifenindex
    Index_Real : INT;           // Index für die Realzahl
    Freigabe_addieren : BOOL;   // Freigeb zum Aufaddieren der einzelnen Werte
    Zwischenint : INT;          // Wird zur Zwischenspeicherung benötigt
    Zahl_positiv : BOOL;        // Wird gesetzt, wenn die Zahl Positiv ist
END_VAR
    // Abfragen des Modus, welcher gefahren wird.
    IF  DB_Paket.DB[Startbyte_Paket + 0] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_M) AND
        DB_Paket.DB[Startbyte_Paket + 1] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_A) AND
        DB_Paket.DB[Startbyte_Paket + 2] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_Komma) THEN
    
            Modus := 1;
                    
    END_IF;
    
    Realzahl := 0.0;
    Teiler_Realzahl := 1.0;
    Index_Real := 0;
    Zahl_positiv := TRUE;        
            
    CASE Modus OF
        
        // Hier wird Modus eins Durchlaufen
        1: 
            FOR Zaehler := Startbyte_Paket + 3 TO Startbyte_Paket + Laenge_Paket BY 1 DO
                
                // Rücksetzen der Freigabe Addition
                Freigabe_addieren := FALSE;
                               
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_0) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_1) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_2) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_3) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_4) THEN
                        
                        Freigabe_addieren := TRUE;
                            
                END_IF;
                
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_5) OR 
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_6) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_7) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_8) OR
                    DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_9) THEN
                    
                        Freigabe_addieren := TRUE;
                            
                END_IF;     
                
                IF  Freigabe_addieren = TRUE THEN
                    
                    Zwischenint := BYTE_TO_INT(DB_Paket.DB[Zaehler]);
                    Realzahl := Realzahl + INT_TO_REAL(Zwischenint - 48)/ Teiler_Realzahl;
                    //Realzahl := Realzahl + INT_TO_REAL(BYTE_TO_INT((DB_Paket.DB[Zaehler]))/Teiler_Realzahl;
                    IF Teiler_Realzahl > 1.0 THEN
                        Teiler_Realzahl := Teiler_Realzahl * 10.0;
                    END_IF;
                    
                END_IF;
            
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_Punkt) THEN
                
                        Teiler_Realzahl := Teiler_Realzahl * 10.0;     
                
                END_IF; 
                
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_Minus) THEN
                
                        Zahl_positiv := FALSE;    
                
                END_IF;
                
                 // Die Abfrage auf 0 bis 9 musste auf 2 Abfrage aufgeteilt werden (SIEMENS !!! ;-) )
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_F) THEN
                
                    Realzahl := 999.999;
                
                END_IF;
            
                IF  DB_Paket.DB[Zaehler] = CHAR_TO_BYTE("Steuerung_Keyence".Konstanten.ASCII_Komma) OR
                    Zaehler = Startbyte_Paket + Laenge_Paket THEN
                                               
                        DB_Real.DD[Startbyte_Real + Index_Real] := REAL_TO_DWORD(Realzahl);
                        IF Zahl_positiv = FALSE THEN
                        
                            DB_Real.DD[Startbyte_Real + Index_Real] := REAL_TO_DWORD(Realzahl * -1.0);    
                         
                        END_IF;
                                
                        Index_Real := Index_Real + 4;                        
                        Realzahl := 0.0;
                        Teiler_Realzahl := 1.0;
                        Zahl_positiv:= TRUE;
                END_IF; 
                
            END_FOR;
    END_CASE;
    
    FC951 := Index_Real/4;        
END_FUNCTION

Woran kann das liegen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also, was ich sehe, ist:
Bevor Du die Funtion aufrufst, vergleichst Du die Lesebytes 1-3 auf eine Wertfolge. In der Funktion wird die Variable Modus auf 1 gesetzt, wenn die Lesebytes 0-2 die selben Werte habe. Und erst wenn Modus = 1 ist, wird die Case-Bedingung abgearbeitet. D.h. Modus kann nie 1 werden, weil die Abfragen kollidieren - ausser es hilft jemand nach. Und dann bleibt Modus auch auf 1, Die Case-Bedingung kann abgearbeitet werden. Der erste Teil in der Funktion ist also erstmal sinnfrei...

Zu Deiner Frage: Ich würde sagen, das Du die Abarbeitung bereits startest, bevor der Empfangspuffer komplett geschrieben ist. Darum braucht es mehrere Zyklen, bevor Du ein brauchbares Ergebnis bekommst. Kopierst Du die Daten direkt in den "DB_Paket" oder mit Blockmove oder so was ähnlichem?

Vielleicht kannst Du das Protokollende abprüfen, um sicherzustellen, das der Empfangspuffer vollständig ist, bevor Du die Funktion aufrufst. Oder die Anzahl der mindest zu empfangenen Zeichen erhöhen.

Oder Du musst damit leben und Dein Programm umstricken, das es mehrere Zyklen verträgt.
 
Erklärung

Also das mit dem Lesebyte 1 und Lesebyte 0 was du geschrieben hast ist nicht richtig.
Ich vergleiche Zwar Lesebyte[1] bis Lesebyte[3] dies sind aber Symbolische Variablen.
Diese liegen auf dem Selben Speicherbereich wie indirekt adressiert 0 - 2.
Das ARRAY Lesebyte fängt bei 1 an hat aber die Adresse 0 ;-)

Ich dachte wenn der P RCV der mir die Daten in den DB läd Fertig meldet wäre der schreibvorgang beendet aber dem scheint ja nicht so zu sein. Wie bekomme ich raus, wann er wiklich fertig ist und wie kann man große daten mit ihm empfangen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
OK, dann nehme ich das erst mal zurück. Ich wusste nicht, das das eine Array mit 1 beginnt.

Frage: Wie prüfst Du das Ende des Empfangs ab? Mit .NDR oder .LEN > X?
Ich kann mich dunkel erinnern, das ich mit dem .NDR auch solche Probleme hatte und habe dan auf .LEN > X geprüft.
 
ich frage im Moment das NDR ab.
Auf was sollte ich denn .LEN abfragen?
Also ich weis ja vorher nicht wie lange die Daten sind. Verändert sich .LEN noch, wenn NDR schon ansteht?
Und kannst du mir vielleicht sagen wie man mehr als 1024 Bytes empfangen kann, bzw. woran man erkennt, dass mehr als 1024 Bytes vom Gegenüber gesendet wurden.
 
Anderer Vorschlag: Baue einen FIFO-Buffer auf. Füge die Daten unkontrolliert hinternanderweg dort hinein. Suche dann deinen Protokollstring, werte den aus und lösche alles, was Du nicht mehr brauchst. Das Problem würde ich dann so lösen, wenn man beim Empfang nicht weis wie lang das Protokoll ist.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hatte auch schon die Idee mir alles in einen Buffer zu schreiben, bis ich die letzten Daten empfangen habe, dabei besteht aber immer noch das gleiche Problem, dass ich nicht weis, wann er die letzten Daten empfangen hat, oder?
 
Hatte auch schon die Idee mir alles in einen Buffer zu schreiben, bis ich die letzten Daten empfangen habe, dabei besteht aber immer noch das gleiche Problem, dass ich nicht weis, wann er die letzten Daten empfangen hat, oder?

Jeder Datensatz hat eine Endkennung. Die suchen und schon weißt du wann Ende ist.
Oder am Anfang steht drin, wie lang der Satz und auch dann weißt du wieviel du auswerten musst.
Den Aufbau des Telegramms musst du schon wissen.


bike
 
Ich kenne den Aufbau des Telegramms, es handelt sich aber um Messwerte und wenn das Messgerät 1s aufzeichnet bekomme ich ca. 600 Byte und wenn 3 s Sekunden aufzeichnet eben 1800 Byte.
Habe gerade etwas gesehen, das der P_RCV nur 128 Byte pro Zyklus überträgt stimmt das?
Muss man also wenn man 600 Daten empfängt 5 Zyklen warten bis diese da sind?
Ps. wenn ich über die 1024 Komme muss ich dann die Konfiguration so einstellen, dass der Lesepuffer nicht überschrieben wird?
Komme leider echt nicht weiter :-(((
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kenne den Aufbau des Telegramms, es handelt sich aber um Messwerte und wenn das Messgerät 1s aufzeichnet bekomme ich ca. 600 Byte und wenn 3 s Sekunden aufzeichnet eben 1800 Byte.
Habe gerade etwas gesehen, das der P_RCV nur 128 Byte pro Zyklus überträgt stimmt das?
Muss man also wenn man 600 Daten empfängt 5 Zyklen warten bis diese da sind?
Ps. wenn ich über die 1024 Komme muss ich dann die Konfiguration so einstellen, dass der Lesepuffer nicht überschrieben wird?
Komme leider echt nicht weiter :-(((

Der Baustein meldet doch, wenn er fertig ist.
Du kennst die Endkennung des Messwertes.
Dann den Datenbereich nach dem Anfang und dem Ende des Messwert durchsuchen.
Wenn mehr Daten da sind, dann in mehren Schritten die Daten nacheinander in ein Datenfeld schreiben.
Sorry, ich verstehe dein Problem nicht.

Du solltest bevor du programmieren beginnst, dir zuerst die Unterlagen durchlesen.
Wenn du die Informationen hast, kannst dir ein Konzept erstellen, wie du die Aufgabe lösen willst und erst dann anfangen zu codieren.
Diese Reihenfolge passt, nach dem das ich gelesen habe, nicht.


bike
 
Das Problem ist ja, dass er fertig meldet und dies wahrscheinlich noch nicht ist. Denn wenn er fertig meldet habe ich noch lange nicht alle Daten im Lesepuffer.
Und wenn ich mehr als 1024 Bytes empfange, werden die ersten Bytes wieder überschrieben und somit kann ich den Anfang nicht finden.

Zu deiner Frage des Problems:
Mir ist nirgendwo ersichtlich, wie der P_RCV die Daten in das angegebene Feld sichert. Sind jetzt 1024 Bytes schon da, wenn er NDR meldet, oder werden immer nur 128 Bytes pro zyklus in den angegebenen Speicher geladen?
Und du sagt wenn mehr daten da sind in mehreren Schritten in ein Datenfeld schreiben. .... In mehreren Zyklen? und wieviele daten kann ich auf einmal schreiben? also wieviel kommen denn auf einmal an???
 
Was würde denn passieren, wenn die Konfiguration so eingestellt ist, dass 25 Puffer bestehen und nichts überschrieben wird. Wenn ich dann den Empfang frei gebe und es würden 2000Bytes vom Partner gesendet werden. erscheint dann das NDR Bit erst wenn alle 2000 Bytes im Speicher sind, oder schon nach den ersten 1024?
Wenn schon nach den ersten 1024, was würde dann passieren, wenn ich diese wegspeichere und die freigabe zum empfangen weg nehme und wieder setze (Also um das nächste Paket zu bekommen? geht das, oder bekommt er dann probleme, weil ich die freigabe weggenommen habe? Oder wie holt man sonst das nächste Paket aus dem Speicher? Bitte bitte helft mir ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit solch "großen" Datenpaketen habe ich leider keine Erfahrung. Aber um das Verhalten zu begreifen würde ich mir eine Testumgebung aufbauen. Man kann z.B. mit Hilfe vom Hyperterminal (Start->Alle Programme-->Zubehör-->Kommunikation-->Hyper Terminal) eine 2000 Byte große Textdatei über die COM-Schnittstelle senden. Baue Dir einfach eine Textdatei mit der Zeichenfolge 012345678901234567890... usw. zusammen. Dann kannst Du prüfen, was im DB ankommt und wie das Verhalten vom CP ist.

Wo willst Du in der Konfiguration 25 Puffer einstellen?
 
Das Problem ist ja, dass er fertig meldet und dies wahrscheinlich noch nicht ist. Denn wenn er fertig meldet habe ich noch lange nicht alle Daten im Lesepuffer.
Und wennich mehr als 1024 Bytes empfange, werden die ersten Bytes wieder überschrieben und somit kann ich den Anfang nicht finden.

Zu deiner Frage des Problems:
Mir ist nirgendwo ersichtlich, wie der P_RCV die Daten in das angegebene Feld sichert. Sind jetzt 1024 Bytes schon da, wenn er NDR meldet, oder werden immer nur 128 Bytes pro zyklus in den angegebenen Speicher geladen?
Und du sagt wenn mehr daten da sind in mehreren Schritten in ein Datenfeld schreiben. .... In mehreren Zyklen? und wieviele daten kann ich auf einmal schreiben? also wieviel kommen denn auf einmal an???

Nach dem erstem NDR die empfangenen Daten aus dem Empfangsdatenbereich in einen anderen Speicherbereich sichern, abwarten bis zum nächsten NDR, wieder sichern in einen weiteren freien Speichbereich (oder vielleicht direkt hinter dem ersten), usw.
Damit hast Du die Empfangsdaten in der richtigen Reihenfolge in diesem freien Speicherbereich liegen.
Dann kannst du die empfangenen Daten auf Anfang und Ende prüfen und auch auswerten, ein Überschreiben findet dann nicht statt.;)
 
Ok

Also im Moment ist es so, dass ich nach dem Empfang von 1030 Zeichen nur noch 6 im Puffer stehen habe. du meinst also es kommen dort 2 NDR Signale? eins wenn 1024 Bytes gesendet wurden und dann noch eins?
Dem ist aber leider nicht so, ich empfange nur einmal ein NDR
 
Zuletzt bearbeitet:
Zurück
Oben