TIA Arrays in SCL

meikelneit

Level-2
Beiträge
146
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Schönen guten Tag,

ich möchte folgendes in SCL programmieren. Ich lese der Reihe nach die Kommunikationszeit meiner CANOpen Kommunikation in ein Array ein und möchte dabei direkt das minimum und maximum erfassen.

Für das minimum habe ich folgendes Programmiert:

FOR #n := 0 TO 50 DO

IF "CANOpen_Zeitstempel".Array_Counter = 1 THEN

"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];

END_IF;

IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min >= "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN

"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];

END_IF;

END_FOR;

Das tuts aber nicht. Wenn ich aber in der zweiten IF Bedingung eine Ergänzung mache, kommt ein Wert an:

FOR #n := 0 TO 50 DO

IF "CANOpen_Zeitstempel".Array_Counter = 1 THEN

"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];

END_IF;

IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min >= "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN

"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];
"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[1];

END_IF;

END_FOR;

Dann kommt ein Wert an, also erreicht er den Schritt ja. Es wirkt so als hätte er Probleme damit #n in dem Array anständig zu verarbeiten.
Kennt jemand eine Lösung oder generell eine bessere Methode?

Vielen dank im Voraus.
MfG Meikelneit


PS: Bitte entschuldigt, irgendwie kann ich die Zeilen nicht einrücken.
 
PS: Bitte entschuldigt, irgendwie kann ich die Zeilen nicht einrücken.
Wenn Du den Programmcode in [CODE]-Tags setzt (der #-Button im Beitragseditor), dann bleiben die Einrückungen erhalten.

Für das minimum habe ich folgendes Programmiert:
Code:
FOR #n := 0 TO 50 DO    
         IF "CANOpen_Zeitstempel".Array_Counter = 1 THEN     
                  "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];     
         END_IF;
    
         IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min >= "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN        
                 "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];        
         END_IF;
END_FOR;
Das tuts aber nicht. Wenn ich aber in der zweiten IF Bedingung eine Ergänzung mache, kommt ein Wert an:
Code:
FOR #n := 0 TO 50 DO    
         IF "CANOpen_Zeitstempel".Array_Counter = 1 THEN        
                "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];     
         END_IF;
    
         IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min >= "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN     
                "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];     
                [B]"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[1];[/B]
         END_IF;
END_FOR;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Werden alte Werte im Array auch mal gelöscht? Du darfst vermutlich nur Werte bis "CANOpen_Zeitstempel".Array_Counter verarbeiten/vergleichen. Außerdem gehört die Initialisierung des Min-Anfangswertes nicht in die Schleife.
Code:
"CANOpen_Zeitstempel".Zeitmessung_Array_Min := 2147483647; //auf größtmöglichen Wert initialisieren

[COLOR="#0000CD"]FOR #n := 0 TO 50 DO[/COLOR]
    IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min > "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN
        "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];
    END_IF;
END_FOR;
oder
Code:
"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];

[COLOR="#0000CD"]FOR #n := 1 TO 50 DO[/COLOR]
    IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min > "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN
        "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];
    END_IF;
END_FOR;
oder
Code:
"CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];

[COLOR="#0000CD"]FOR #n := 1 TO "CANOpen_Zeitstempel".Array_Counter - 1 DO[/COLOR]
    IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min > "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN
        "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];
    END_IF;
END_FOR;

Harald
 
Danke für deine Antworten.
Also ich habe es jetzt wie in deinem ersten Vorschlag gemacht.
Funktioniert leider auch erstmal nicht. Was mich wundert, der Wert den ich initialisiere kommt nichtmal in der Variablen "CANOpen_Zeitstempel".Zeitmessung_Array_Min an, wenn ich das alles in der Beobachtungstabelle verfolge.

Ergänzend vielleicht noch:
Die Variablen Sind beide vom Typ time, habe ich nochmal geprüft.
 
... oder
Code:
IF "CANOpen_Zeitstempel".Array_Counter = 0 THEN
    "CANOpen_Zeitstempel".Zeitmessung_Array_Min := 0;
ELSE
    "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];

    FOR #n := 1 TO "CANOpen_Zeitstempel".Array_Counter - 1 DO
        IF "CANOpen_Zeitstempel".Zeitmessung_Array_Min > "CANOpen_Zeitstempel".Zeitmessung_Array[#n] THEN
            "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[#n];
        END_IF;
    END_FOR;
END_IF;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Meikelneit!
Wäre interessant zu erfahren, ob Deine MaximumsErmittlung nach demselben Prinzip programmiert ist und trotzdem richtig funktioniert.
Ich kann in Deinem Code keinen Fehler entdecken.
Du fragst auf ">=" ab. ">" würde genügen, da bei "=" ein erneutes Überschreiben nichts bringt.
Was ist '"CANOpen_Zeitstempel".Array_Counter'? Ich hätte dort auf #n=0 bzw. #n<1 abgefragt.
Gruss, Heinileini
 
Danke dir Harald, das hat funktioniert. Aber was war das Problem der obigen Algorithmen? Was wurde hier jetzt im großen und ganzen anders gemacht?

@ Heinilein,
der Array_counter läuft mit weil ich auch den Mittelwert haben will. Das funktioniert aber soweit.
 
Zuletzt bearbeitet:
Was mich wundert, der Wert den ich initialisiere kommt nichtmal in der Variablen "CANOpen_Zeitstempel".Zeitmessung_Array_Min an, wenn ich das alles in der Beobachtungstabelle verfolge.
Das wirst Du in der Beobachtungstabelle vermutlich nur nicht sehen können, weil da siehst Du nur den Wert der am Ende des Programms (nach der Schleife) drinsteht.

PS: hat sich erledigt
Wird "CANOpen_Zeitstempel".Zeitmessung_Array_Min noch woanders im Programm überschrieben?
Frage zur Sicherheit: Wird der Programmcode auch ausgeführt? Ist die CPU in Run?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also der "CANOpen_Zeitstempel".Zeitmessung_Array_Min wird nur an der Stelle verwendet. Die SPS ist im RUN modus, ich kann Telegramme Senden, bekomme die richtigen Antworten und der Mittelwert wird ja auch laufend, neu und richtig, berechnet.
 
Danke dir Harald, das hat funktioniert. Aber was war das Problem der obigen Algorithmen? Was wurde hier jetzt im großen und ganzen anders gemacht?
Das hatte ich schon im Beitrag #3 geschrieben:
Werden alte Werte im Array auch mal gelöscht? Du darfst vermutlich nur Werte bis "CANOpen_Zeitstempel".Array_Counter verarbeiten/vergleichen.
Die letzte Programmversion Beitrag #5 verarbeitet nur gültige/aufgezeichnete Werte.
- wenn noch gar kein Wert aufgezeichnet ist, dann wird Min für "bessere Optik" auf 0 gesetzt
- wenn mindestens 1 Wert aufgezeichnet ist, dann wird Min mit dem ersten Wert initialisiert und bis zum letzten tatsächlich aufgezeichneten Wert verglichen

Harald
 
der Mittelwert wird ja auch laufend, neu und richtig, berechnet.
Ist Dein Array ein Ringpuffer (werden alte Werte durch neue überschrieben)?
Ist "CANOpen_Zeitstempel".Array_Counter der Index-Pointer in den Ringpuffer oder zeigt der den Füllstand des Arrays an?
Wie sieht die Mittelwert-Berechnung aus?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
OMG, jetzt fällt der Groschen. Meine version hat grundsätzlich immer das ganze Array abgegrast, aber alle nicht vom Ablauf beschriebenen Felder enthielten #T0ms, klar kommt da immer 0ms raus solange das Array nicht voll ist.

Danke dir Harald.
 
Den Mittelwert bilde ich ganz simpel:

Code:
#temp := T#0ms;

FOR #i := 0 TO 50 DO
    
    #temp := #temp + "CANOpen_Zeitstempel".Zeitmessung_Array[#i];
    "CANOpen_Zeitstempel".Zeitmessung_Mittelwert := #temp / "CANOpen_Zeitstempel".Array_Counter;
    
END_FOR;

Also das ganze ist noch eine Rohversion und nicht lauffähig konzipiert. Am ende Werde ich den ArrayCounter einfach wieder auf 0 setzen so das er anfängt das Array wieder von vorne zu überschreiben, und der Teiler zur Mittelwertbildung bleibt auf 50.
 
Deine simple Mittelwertbildung ist nicht korrekt solange das Array noch nicht komplett gefüllt ist. Du addierst immer 51 Werte, auch wenn erst weniger Werte erfasst sind.
Und: die Zeile mit der Division gehört nicht in die Schleife sondern dahinter.
Und: wenn noch gar kein Wert aufgezeichnet ist, dann dividierst Du durch 0

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ...
Code:
         IF "CANOpen_Zeitstempel".Array_Counter = 1 THEN     
                  "CANOpen_Zeitstempel".Zeitmessung_Array_Min := "CANOpen_Zeitstempel".Zeitmessung_Array[0];     
         END_IF;
... nix mit der "MinimumsFindung" zu tun hat, sondern zur MittelwertBildung gehört, dann nehme ich meine Behauptung "kann keinen Fehler entdecken" zurück.
Ich dachte, das sollte die Initialisierung sein und beim 1. Schleifendurchlauf wirksam werden.
Harald stimme ich natürlich zu, dass die Initilisierung vor der Schleife sauberer ist.
 
Zurück
Oben