Step 7 Mittelwertbildung aus n-Zahlen

mikraka

Level-1
Beiträge
14
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Abend zusammen,

da SCL für mich völlig neu ist, ich aber nicht länger darauf verzichten möchte, bin ich (lerne gerade VBA in der Technikerschule) dabei mich in die Materie einzuarbeiten.
Wir haben in VBA ein kleines Programm geschrieben um Mittelwerte zu berechnen. Zu erst wird man gefragt wie viele Werte eingegeben werden sollen. Der Wert wird dient der For/Next Schleife und anschließend beim dividieren der Summe aller Werte.
In SCL möchte ich die Mittelwertbildung möglichst flexibel halten. D.h. n-Werte lege ich als Input Operand an, ebenso eine Zeit.
Mit der Zeit generiere ich einen Takt. Ist die Zeit z.B. 10ms, kommt mein Timer_1 nach 10ms und nach weiteren 10ms geht er wieder, da er vom Timer_2 unterbrochen wird. Dieser Zyklus(müssten 50Hz sein) läuft solange wie von Außen der Start anliegt.
Dieses Taktsignal Timer_1.Q werte ich als Positive Flanke aus. Den Flankenmerker nutze ich in meiner For/ Next Schleife als Bedingung wann der Wert auf die vorherige Summe addiert werden soll.
Nachdem die For/ Next Schleife durchlaufen ist, teile ich den Wert und gebe ihn aus. Meinen i Parameter für die For/ Next Schleife setze ich dann auf Null und die While Schleife soll erneut durchlaufen werden, solange der Start anliegt.

So weit die Theorie...

Beim Übersetzen kommt es zu Fehlermeldungen die ich nicht interpretieren kann. Vielleicht könnt ihr mir dabei behilflich sein.

FUNCTION_BLOCK FB500
TITLE = 'Mittelwert aus n-Werten'
VERSION : '1.0'
AUTHOR : xxxxx
NAME : SCL
FAMILY : xxxxx


// Bausteinparameter
VAR_INPUT
I_Start :BOOL; //Start der Funktion
I_n_Werte :INT; //Anzahl der Werte
I_Wert :REAL; //Wert aus dem der Mittelwert gebildet werden soll
I_Takt_Zeit :TIME; //Taktzeit für den Aufzeichnungs-Timer
END_VAR


// Ausgangsparameter
VAR_OUTPUT
O_Mittelwert :REAL;
END_VAR


// Durchgangsparameter
VAR_IN_OUT

END_VAR


// Temporäre Variablen
VAR_TEMP


END_VAR


// Statische Variablen
VAR
Timer_1 :SFB4; //TON Timer
Timer_2 :SFB4; //TON Timer
i :INT; //Parametervariable für For/Next Schleife
n :INT; //Parametervariable für For/Next Schleife
L_Wert :REAL; //Summenvariable
Edge_Flag_Pos :BOOL; //Hilfsvariable Flankenbildung
FP :BOOL; //Flanke Aufzeichnungstakt
END_VAR




///////////////////////// Zuweisen & Initialisieren ///////////////////////
IF NOT I_Start THEN
n:=I_n_Werte;
i:=0;
END_IF;
////////////////////////////////////////////////////////////////////////////


//////////////////////////////// Timer //////////////////////////////////
Timer_1(IN:=(I_Start AND NOT (Timer_1.Q)), PT:=I_Takt_Zeit);
Timer_2(IN:=(Timer_1.Q), PT:=I_Takt_Zeit);
////////////////////////////////////////////////////////////////////////////


////////////////////////////// Pos. Flag ////////////////////////////////
FP := Timer_1.Q AND NOT Edge_Flag_Pos;
Edge_Flag_Pos := Timer_1.Q;
//////////////////////////////// Schleife //////////////////////////////////

WHILE (I_Start = True) DO
FOR i:= 1 TO n BY 1 DO
IF (FP = True) THEN
L_Wert:=(I_Wert+L_Wert);
END_IF;
END_FOR;
O_Mittelwert:=(L_Wert/n)
i:=0
END_WHILE;


END_FUNCTION_BLOCK

Vielen Dank im Voraus und einen schönen Abend noch;-)

Mikraka
 
Sorry,

irgendwie hat der Editor meine Eingerückten Zeilen gefressen!
Hier ein neuer Versuch.


FUNCTION_BLOCK FB500
TITLE = 'Mittelwert aus n-Werten'
VERSION : '1.0'
AUTHOR : xxxxx
NAME : SCL
FAMILY : xxxxx


// Bausteinparameter
VAR_INPUT
I_Start :BOOL; //Start der Funktion
I_n_Werte :INT; //Anzahl der Werte
I_Wert :REAL; //Wert aus dem der Mittelwert gebildet werden soll
I_Takt_Zeit :TIME; //Taktzeit für den Aufzeichnungs-Timer
END_VAR


// Ausgangsparameter
VAR_OUTPUT
O_Mittelwert :REAL;
END_VAR


// Durchgangsparameter
VAR_IN_OUT

END_VAR


// Temporäre Variablen
VAR_TEMP


END_VAR


// Statische Variablen
VAR
Timer_1 :SFB4; //TON Timer
Timer_2 :SFB4; //TON Timer
i :INT; //Parametervariable für For/Next Schleife
n :INT; //Parametervariable für For/Next Schleife
L_Wert :REAL; //Summenvariable
Edge_Flag_Pos :BOOL; //Hilfsvariable Flankenbildung
FP :BOOL; //Flanke Aufzeichnungstakt
END_VAR




///////////////////////// Zuweisen & Initialisieren ///////////////////////
IF NOT I_Start THEN
n:=I_n_Werte;
i:=0;
END_IF;
////////////////////////////////////////////////////////////////////////////


//////////////////////////////// Timer //////////////////////////////////
Timer_1(IN:=(I_Start AND NOT (Timer_1.Q)), PT:=I_Takt_Zeit);
Timer_2(IN:=(Timer_1.Q), PT:=I_Takt_Zeit);
////////////////////////////////////////////////////////////////////////////


////////////////////////////// Pos. Flag ////////////////////////////////
FP := Timer_1.Q AND NOT Edge_Flag_Pos;
Edge_Flag_Pos := Timer_1.Q;
//////////////////////////////// Schleife //////////////////////////////////

WHILE (I_Start = True) DO
FOR i:= 1 TO n BY 1 DO
IF (FP = True) THEN
L_Wert:=(I_Wert+L_Wert);
END_IF;
END_FOR;
O_Mittelwert:=(L_Wert/n)
i:=0
END_WHILE;


END_FUNCTION_BLOCK
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du mußt dir klarmachen, dass eine SPS-Programm in sich schon eine Schleife bildet. Das gesamte Programm wird abgearbeitet, es wird das Prozessabbild eingelesen, das Prozessabbild ausgegeben, dann beginnt der Zyklus von vorn.

Nun hast du in deinem Programm eine While-Schleife, die ist von einem Input im FB abhängig. Du setzt I_Start auf True und die Schleife beginnt. Wie wird die Schleife beendet???? Niemals, denn dein Programm hängt in der While-Schleife, weder I_Start, noch der Timer wird jemals wieder bearbeitet, kann also auch die Schleife nicht mehr beenden, oder eine Flanke bilden oder sonst was. Das Ende vom Lied ist ein SPS-STOP, denn die zulässige Zykluszeit wird überschritten.

Ein SPS-Programm ist kein VBA-Programm, auch wenn einiges in SCL so ähnlich aussieht. Es gibt kein Multitasking, d.h. du kannst keine Schleifen Programmieren, die von einem außen anliegenden Signal abhängig sind. Du kannst schon, aber es funktioniert dann nicht wie gedacht.

Insofern hat es im Moment gar keinen Sinn, nach weiteren Fehlern zu suchen. Du mußt das Programm so schreiben, dass alle Programmteile immer wieder durchlaufen werden. Wenn dann eine Flanke erkannt wird, kannst du einen Timer starten, wenn der Timer läuft oder abgelaufen ist, kannst du etwas berechnen etc., aber auch alle anderen Programmteile müssen immer bearbeitet werden.

PS: Die Fehlermeldungen hier anzugeben hätte durchaus auch Sinn gehabt, die sehe ich nirgends.
 
Zuletzt bearbeitet:
Moin Ralle,

danke für die schnelle Antwort.
Die Fehlermeldungen haben als Bezug im Programm die Zeilennummer. Dachte mir, es wäre etwas aufwendig das mit zu posten.
Ich schiebe das gleich mal hinterher.
Gibt es hier irgendwo eine Anleitung bzgl. des Code-Editors? Meine eingerückten Zeilen werden immer verschoben....

Wegen des SPS Zyklus und der Schleife mache ich mir mal Gedanken, oder hättest du eine Idee wie das lösbar wäre?
Für einen kleinen Ar***tritt wäre ich dankbar, den Rest würde ich dann versuchen weiter zu entwickeln.

Viele Grüße
Kai
 
Zuviel Werbung?
-> Hier kostenlos registrieren
irgendwie hat der Editor meine Eingerückten Zeilen gefressen!
Setz' mal Deinen Code in die Codetags (Button # in der 2. Iconreihe ganz rechts), dann klappts auch mit den Einrückungen.

Die Fehlermeldungen geben ja schon mit an, das wahrscheinlich irgendwo die Semikolons (Strichpunkt) vergessen wurden und in der Tat finden sich da mehrere Zeilen, wo das so ist, z.B.:
Code:
[COLOR=#333333]O_Mittelwert:=(L_Wert/n)[/COLOR][B][COLOR=#ff0000];[/COLOR][/B][COLOR=#333333][/COLOR]
Auch bei mir war das am Anfang (und ist es immer noch) der häufigste Fehler.
;)
 
Hey Hucki,

ja genau da waren zwei Semikolon die fehlten. Egal wie oft man hin schaut, man sieht den Wald vor lauter Bäumen nicht.
Jetzt ist die Übersetzung Fehlerfrei. Nun kann ich mir überlegen wie an das Problem mit der Endlosschleife ran gehe.
Simuliert habe ich das gerade und es passierte genau das was Ralle prophezeite, die CPU ging in Stopp.

Für den Tipp die Bool´sche Variable nicht auf true zu vergleichen auch noch Danke;-)

Besten Dank;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Auch Deine FOR-Schleife wird nicht so funktionieren, wie von Dir gedacht, da wie von Ralle erwähnt, das gesamte Programm in einem Zyklus durchlaufen wird (werden muss), aber sich der Input I_Wert dabei logischerweise nicht ändert.
Du addierst also dann n-mal den gleichen Wert.

Bei einem SPS-Programm mußt Du als Input wissen, wann ein neuer Wert vorliegt und wie dieser ist.
Dann musst Du diesen zur bisherigen Summe hinzufügen und die Anzahl der Werte um eins erhöhen.
(Beides musst Du für den nächsten Zyklusdurchlauf speichern, wo dann auf's Neue die beiden Inputs geprüft werden.)

Damit kannst Du den Mittelwert berechnen und ausgeben.


Für mich bedeutet das, dass Du normalerweise auch keinen Timer benötigst, es sei denn Du erwartest in einem genau Takt den neuen Wert.
Wenn man nie 2 gleiche Werte hintereinander erwartet, kann man auch in jedem Zyklus prüfen, ob der Wert sich gegenüber dem vorigen Zyklus geändert hat. Somit könnte man sich in diesem Fall den Input "Neuer Wert" sparen.
 
Zurück
Oben