Structured Text gemäß IEC 61131-3)

megni

Level-1
Beiträge
17
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo @ ich bin Anfänger im Bereich SPS und muss für ein vorstellungsgespräch folgende Aufgabe lösen

In der diskreten Messwertverarbeitung wird oft eine Filterung mit gleitendem Mittelwert (FIR)
verwendet. Hierbei werden die Eingangswerte x[k] in einem festen Zeitraster von der
Steuerung eingelesen. Zusammen mit den gespeicherten Eingangswerten vorangegangener
Steuerungszyklen x[k-1] … x[k-n+1] wird dann der Mittelwert über diese Werte
gebildet, was den Ausgangswert y[k] ergibt. n bestimmt die Anzahl der zu
berücksichtigenden Eingangsgrößen. Die zugehörige Formel ist:
n-1
y[k]= (1/n) £ x[k-1]
i=0
Das zu erstellende Programmmodul hat mindestens folgende Schnittstelle:
Eingang
IN_nx: INT; (* Einheit [1]; zu filternder Wert *)
IN_ucFiltergrad: BYTE; (* Einheit - ; Filtergrad: Anzahl abzuspeichernder Werte *)
Ausgang
OUT_y: INT; (* Einheit [1]; gefilterter Wert *)

Aufgabe
Bitte bereiten Sie in ST (Structured Text gemäß IEC 61131-3) eine industrietaugliche Lösung
für das oben beschriebene gleitende Mittelwertfilter vor. Das von Ihnen erstellte
Programmmodul sollte von Ihren Fachkollegen später beispielsweise als Bibliotheksfunktion

kann jemand mir helfen?
 
ich muss ehrlich sagen, dass dein neuer arbeiteger hat ein hohes lob verdient. die doch "eigentlich" einfache aufgabe kann so viel über dich aussagen.

ich hoffe die wird nur bei direkten, präzisen fragen geholfen.
es gibt bei deiner aufgabe so viele kleine besonderheiten oder unwichtigkeiten die viel über dich aussagen.

meine meinung :)

streng dich an, hilfe bekommst du im forum eigentlich immer.
 
Aber immerhin interessant, wie man eine recht einfache Aufgabe hinter einem bombastisch und wissenschaftlich klingendem Text verstecken kann.
Klingt, als hätten die das aus irgendeinem Uni-Lehrtext geklaut. :ROFLMAO:

Ich denke auch, Lösungsansatz machen und hier posten. Aber ob dem TE dazu die Zeit reicht?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich muss ehrlich sagen, dass dein neuer arbeiteger hat ein hohes lob verdient. die doch "eigentlich" einfache aufgabe kann so viel über dich aussagen.

ich hoffe die wird nur bei direkten, präzisen fragen geholfen.
es gibt bei deiner aufgabe so viele kleine besonderheiten oder unwichtigkeiten die viel über dich aussagen.

meine meinung :)

streng dich an, hilfe bekommst du im forum eigentlich immer.

Können Sie mir bitte was für eine besonderheiten hinter dieser Aufgabe steckt
 
Hallo @ das ist mein Lösungsvorschlag für die obige Augagbe
FUNCTION_BLOCK GMBerechnung
VAR_INPUT
IN_nx : INT; (* zu filternder Wert*)
IN_ucFitergrad: BYTE; (*Anzahl abzuspeichernder Werte*)
END_VAR
VAR_OUTPUT
OUT_y: INT; (* Mittelwert: gefilterter Wert*)
END_VAR
VAR
Messwerte:ARRAY[1..n] OF INT;
index_Write:INT:=1;
index_Read:INT:=1;
Sum:INT:=0; (*enthält*)
END_VAR

(*zu filternder Wert im FIFO schreiben*)

Messwerte[index_Write:INT]:=IN_nx;

IF index_Write >= n THEN
index_Write:=1;

ELSE

index_Write:=index_Write+1;

END_IF;

(*zu filternder Wert im FIFO auslesen*)

IF index_Read < index_Write THEN
Sum:= Sum + Messwerte[index_Read];
index_Read:=index_Read+1;
END_IF;

(*Mittelwert Berechnung*)
IF index_Read >= n THEN
OUT_y:=Sum\n;
Sum:=0;
index_Read:=1;
END_IF;

Werde ich mich für die Kritik und Verbesserungsvorschläge freuen.
 
Mal auf die Schnelle:

Du hast "IN_ucFitergrad" nicht berücksichtigt.

Du kannst in Codesys m.W. keine variablen Array anlegen. Daher legst du ein Array mit n als Konstante an, die so groß ist, dass künfitge max. Filtergrade abgedeckt sind. (Oder es muß bei Änderungen immer neu compiliert werden) Viellecht 20 oder 50?
Statt n bei den Vergleichen setzt du dein "IN_ucFitergrad" ein, wobei du ganz am Anfang einen Vergleich machen solltest, dass "IN_ucFitergrad" <= n ist, ansonsten einen Fehler ausgeben.

Deine FB ist so aufgebaut, dass er immer, wenn ein neuer Wert eingelesen werden soll genau einmal aufgerufen wird, ist das so gewollt? Wenn nicht wäre noch eine Eingang möglichm der dann im FB über eine Flankenbildung den Eintrag und die Berechnung veranlaßt.

Der FB kann nicht zurückgesetzt (genullt werden), was man noch einbauen sollte.

Den Mittelwert berechnest du erst, wenn die Anzahl von "IN_ucFitergrad" Werte eingetragen wurden. Das heißt in der Praxis z.Bsp. immer 10 Werte (bei "IN_ucFitergrad" = 10) abwarten, dann Mittelwert berechnen.
Ich würde den Mittelwert jedes Mal berechenen, du hast ja praktisch einen Ringbuffer gebaut, so dass immer ein alter Wert überschrieben wird.

Nun gibt es mehrere Möglichkeiten:

1. Immer alle Werte Addieren und durch "IN_ucFitergrad" teilen. (kostet Rechenzeit)
2. Wert, der überschrieben wird. vor dem Überschreiben von SUM abziehen, neuen Wert dazu addieren, dur "IN_ucFitergrad" teilen. (eleganer, weniger Rechenzeit)

Aufpassen, du mußt dann am Anfang einen Zählwert mitführen, wie viele Werte du überhaupt schon im Buffer hast, da ja bei den ersten (z.Bsp. 4) Werten nicht durch "IN_ucFitergrad" getteilt werden darf, sondern nur durch 4! Dann hättest du schon nach dem ersten eingelesenen Wert ein Ergebnis für den Mittelwert parat, auch wenn das noch ungenau ist.
 
Dem ist nicht viel hinzuzufügen.
Deine FB ist so aufgebaut, dass er immer, wenn ein neuer Wert eingelesen werden soll genau einmal aufgerufen wird, ist das so gewollt? Wenn nicht wäre noch eine Eingang möglichm der dann im FB über eine Flankenbildung den Eintrag und die Berechnung veranlaßt.
Wie weit man die strikt zyklische Bearbeitung des gesamten Programms durch bedingte FB-Aufrufe aufweicht, ist sicher eine Frage der Philosophie. Für diesen FB würde ich schon einen bedingten Aufruf vorziehen, denn wenn kein neuer Messwert eingetragen werden muss, hat der FB ja auch nichts weiter zu tun.
Ich würde den Mittelwert jedes Mal berechenen, du hast ja praktisch einen Ringbuffer gebaut, so dass immer ein alter Wert überschrieben wird.
Das muss er sogar, denn genau das ist doch die Aufgabenstellung. Dabei kann man auch gleich überlegen, ob man unbedingt den "index_read" braucht. Schliesslich zeigt "index_write" vor dem Überschreiben auf genau den ältesten Wert, den man zunächst von der Summe abziehen muss.
Aufpassen, du mußt dann am Anfang einen Zählwert mitführen, wie viele Werte du überhaupt schon im Buffer hast, da ja bei den ersten (z.Bsp. 4) Werten nicht durch "IN_ucFitergrad" getteilt werden darf, sondern nur durch 4!
Dieser Zählwert, sozusagen der Füllstand des Ringpuffers, könnte auch für den Anwender interessant sein. Ich würde ihn deshalb auch als VAR_OUTPUT deklarieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du brauchst nen Array und ne FOR-Schleife.
Ist der Befehl MEMMOVE erlaubt?

Braucht man für die Aufgabenstellung überhaupt ein Array bzw. Ringbuffer?
ich hätte das jetzt so gemacht:
Mittelwert := LetzterMittelwert + ((Messwert - LetzterMittelwert) / AnzMesswerte);

und jedesmal wenn ein neuer Wert in eingeschoben werden soll
Letztermittelwert := Mittelwert;

mfG René
 
Zuletzt bearbeitet:
Laut Aufgabenstellung ist der FB-Ausgang der Mittelwert der letzen n Messwerte. Vor jedem Neueintrag eines Wertes muss also der älteste Wert aus der Summe herausgerechnet werden. Ich wüsste nicht, wie das ohne Ringpuffer gehen soll.
 
Braucht man für die Aufgabenstellung überhaupt ein Array bzw. Ringbuffer?
ich hätte das jetzt so gemacht:
Mittelwert := LetzterMittelwert + ((Messwert - LetzterMittelwert) / AnzMesswerte);

und jedesmal wenn ein neuer Wert in eingeschoben werden soll
Letztermittelwert := Mittelwert;

mfG René

Hmm, da gebe ich StructuredTrash recht. Ich glaube auch, dass Deine Variante eher der Mittelwert seit Beginn der (Wetter-)Aufzeichnung ist...
 
Danke zuerst an alle. Ich habe meine Code nochmal geändert.
FUNCTION_BLOCK GMBerechnung
VAR_INPUT
IN_nx : INT; (* zu filternder Wert*)
IN_ucFitergrad: BYTE; (*Anzahl abzuspeichernder Werte*)
END_VAR
VAR_OUTPUT
OUT_y: INT; (* Mittelwert: gefilterter Wert*)
Out_Pufferstand:INT; (*Anzahl gelieferternder Werte*)
END_VAR
VAR
Messwerte:ARRAY[1..20] OF INT;
index_Write:INT:=1;
index_Read:INT:=1;
Sum:INT:=0;
Zähler:INT=0;
END_VAR

IF IN_ucFitergrad <= 20

(*zu filternder Wert im FIFO schreiben*)
Messwerte[index_Write:INT]:=IN_nx;

IF index_Write >= IN_ucFitergrad THEN
index_Write:=1;

ELSE

index_Write:=index_Write+1;

END_IF;

(*zu filternder Wert im FIFO auslesen*)

IF index_Read < index_Write THEN
Sum:= Sum + Messwerte[index_Read];
index_Read:=index_Read+1;
Zähler:= Zähler+1;
Out_Pufferstand:= Zähler;
END_IF;

(*Mittelwert Berechnung*)
IF Zähler>= 20 THEN
OUT_y:=Sum\IN_ucFitergrad;
index_Read:=Zähler%20 +1;
Sum:=Sum-Messwerte[index_Read];

END_IF;
END_IF;
ich habe noch folgende Frage:
1) kann jemand mir den Befehl Schicken mit denen man die Code bei dem Post formatieren kann
2) Laut die Aufgabstellung soll die Variable IN_ucFitergrad ein BYTE groß sein d.h ein Wert zwischen 1 und und 2^8 -1 sein, wenn ich mich gut an meine Grundvorlesungen erinnert. Bei mir habe ich das Array größe auf 20 Werte beschränkt, welche meine Meinung nach die Aufgabestellung nicht entspricht, denn die Array Größe muss zwischen 1 und 2^8 -1 sein und nicht irgendwelche Kontante. Kann Jemand mir weiter helfen?
3) Zum Schluß bitte ich euch nochmal meine Code zu lesen, um zu überprüfern ob sie noch viele Lücke enthält.
 
Zuletzt bearbeitet:
Es kann vorkommen das der Mittelwert ein Real Wert ist. Gibt es bei ST eine implizite Konvertierung von Real to INT oder soll man explizit machen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ein codesys kompiler (V3.X) würde den code nicht akzeptieren.
ladt dir irgendwo eine demo oder ähnliches runter und jag ihn da durch. ist ja je egal was du nimmst aber er zeigt dir an was ihm nicht schmeckt. (ein beispiel:http://www.microinnovation.com/en/desktopdefault.aspx/tabid-8/26_view-374/ )
ä kann/macht nicht jeder kompiler
IF IN_ucFitergrad <= 20
fehlt then
Messwerte[index_Write:INT]:=IN_nx;
INT ist ein schlüsselwort
usw...

mein tipp
 
Du mußt den erweiterten Editor einstellen und öffnen (unten Rechts, zwischen Antworten und Abbrechen). Dann kannst du deinen Code markieren und oben bei den Funktionsicons die Raute (#) wählen. Daraufhin werden die Codetags vor und nach deinem Code eingefügt. Wenn du dien Code einrückst

Code:
IF XY = 1 THEN
   IF Z = 2 THEN
      tu_was := True;
   END_IF
END_IF

bleiben die Einrückungen erhalten, der Code ist besser lesbar.
 
2) Laut die Aufgabstellung soll die Variable IN_ucFitergrad ein BYTE groß sein d.h ein Wert zwischen 1 und und 2^8 -1 sein, wenn ich mich gut an meine Grundvorlesungen erinnert. Bei mir habe ich das Array größe auf 20 Werte beschränkt, welche meine Meinung nach die Aufgabestellung nicht entspricht, denn die Array Größe muss zwischen 1 und 2^8 -1 sein und nicht irgendwelche Kontante. Kann Jemand mir weiter helfen?
3) Zum Schluß bitte ich euch nochmal meine Code zu lesen, um zu überprüfern ob sie noch viele Lücke enthält.
Zu 2)
Du kannst die Arraygrösse nicht zur Laufzeit ändern, sondern musst sie schon vor dem Übersetzen festlegen. Das Array muss also von vornherein so gross sein wie maximal benötigt. Dann kann IN_ucFiltergrad auch nicht zu gross werden. Du solltest allerdings den Fall IN_ucFiltergrad = 0 bedenken. Ersetze mal gedanklich jedes Vorkommen dieser Variable durch den Wert 0 und überlege, was dann passiert. Oder noch besser, befolge den Rat von Fanta-Er und besorge Dir eine IEC61131-Entwicklungsumgebung, am besten eine wie Beckhoff TwinCat2, mit der Du das Programm auch auf Deinem PC laufen lassen kannst.
Zu 3)
Bei der Summen- und Mittelwertbildung ist Dir einiges durcheinandergeraten, das wird überhaupt nicht funktionieren. Da sah die erste Version noch besser aus. Die erfüllte zwar nicht ganz die Aufgabenstellung, hätte aber wohl das getan, was Du Dir vorgestellt hast. Auch dabei wirst Du besser vorankommen, wenn Du Dein Programm testen kannst.
 
Zurück
Oben