Step 7 Gesamtmenge aus Durchfluss berechnen

stinker06

Level-1
Beiträge
20
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

folgendes Problem liegt vor. Auf unserer Kläranlage bekommen wir den Durchfluss es Wassers als Analogwert in die SPS. Halt über Messumformer. Ganz klassisch. Der Messumformer gibt keine Impulse pro Kubikmeter. Der Durchfluss wird in m³/h oder l/s eingelesen. Gibt es einen Funktionsbaustein der mir aus dem Durchfluss die Gesamtmenge berechnet. Oder alle m³ einen Impuls bildet?
 
Volumen = Durchfluss x Zeit

Will heißen, Du liest (äquidistant) den Wert ein und multiplizierst mit der verstrichenen Zeit. Das wird aufsummiert und fertig. ;)
Das Zeitraster passt Du an die geforderte Genauigkeit und an das Abtastraster des Gebers an (falls der nicht kontinuierlich misst).
 
Bei diesem Baustein muss man aber aufpassen, falls man große Summen hat bei kleinen Mengen. Wegen der begrenzten Genauigkeit der Realwerte bleibt er irgendwann stehen und addiert nichts mehr dazu.
Spreche da aus Erfahrung.
Habe ihn intern auf Lint abgeändert.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
.. Real bei nem Zähler ist selten ne gute Idee ..
Joo, ich addiere bei so etwas die Durchlusswerte als Real und bilde einen Überlauf bei z.Bsp. bei 1m³. Beim Übertrag wird ein Integer (DInt, LInt) hochgezählt. Der Realwert wächst dann nicht ins unermessliche, wodurch die erwähnten Rechenfehler sehr sehr klein bleiben. Mit dem Übertrag kann man natürlich auch Zählimpulse ausgeben.

Bedenken sollte man noch dass man mit jedem addieren auch den Messfehler mit addiert. Also die Abtastzeit nicht zu klein wählen.
 
Wenn man sowieso schon Zählerbausteine hat, zb mit Tagesmengen oder ähnlichem , ist es praktisch Impulse zu generieren:

Code:
FUNCTION "FCMengenImpuls" : VOID
TITLE = Impulse aus Momentan-Messungen

VAR_INPUT
  Takt: BOOL;  // Impuls je Zeiteinheit
  Mess: REAL;  // Messung 
  IMenge : REAL;  // Menge je Impuls 
END_VAR

VAR_OUTPUT
 AImp: BOOL ;  // Ausgangsimpuls
END_VAR


VAR_IN_OUT
  ZwWert : REAL ; //Zwischenwert
END_VAR


BEGIN
NETWORK
TITLE =

CLR;= #AImp; // VAR_OUTPUT muss immer initialisiert werden 

UN Takt;  BEB; // Außerhalb des Zeittakts nichts zu tun
 
L #ZwWert; L #Mess; +R; T #ZwWert;  // Addieren

L #IMenge; <R; BEB; // Ende, wenn Impulsmenge noch nicht erreicht

L #ZwWert; L #IMenge; -R; T #ZwWert;  // Zurücksetzen auf Rest 

SET;= #AImp; // Impuls generieren

END_FUNCTION

Bei der Maßeinheit l/s und 1 Impuls / m³ wird sie etwa so aufgerufen:

Code:
CALL "FCMengenImpuls"(Takt := "Impuls1Sek", Mess:= #MDurchfluss, IMenge := 1000.0, AImp:= #ZDurchflussMg.EImp, ZwWert:=#ZWDurchfluss);


Bei m³/h wäre IMenge 3600.0 ( Sekunden pro Stunde).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Stinker06: Um was für ein Durchflussmessgerät handelt es sich? (Hersteller, Typ) Normalerweise haben die alle einen Impulsausgang mit on board. Der muss halt nur an die SPS angeschlossen sein.

Gruß Ralf
 
Code:
[COLOR="#FF0000"]CLR;= #AImp;[/COLOR] // VAR_OUTPUT muss immer initialisiert werden 

UN Takt;  BEB; // Außerhalb des Zeittakts nichts zu tun
 
L #ZwWert; L #Mess; +R; [COLOR="#FF0000"]T #ZwWert;[/COLOR]  // Addieren

L #IMenge; <R; BEB; // Ende, wenn Impulsmenge noch nicht erreicht

[COLOR="#FF0000"]L #ZwWert; L #IMenge;[/COLOR] -R; [COLOR="#FF0000"]T #ZwWert;[/COLOR]  // Zurücksetzen auf Rest 

[COLOR="#FF0000"]SET;= #AImp;[/COLOR] // Impuls generieren
Die Idee, für die Pulserzeugung einen Baustein zu erstellen, ist löblich, allerdings ist die Ausführung ziemlich schlechter Programmierstil: Baustein-Ausgängen mehrmals Werte zuweisen und Baustein-Ausgänge zurücklesen.
Eine FUNCTION soll jeden Eingang nur 1x lesen und jeden Ausgang nur 1x schreiben. Beachtet man dies nicht, dann bekommt man Probleme mit Multitask-Prozessen (mehrere Tasks in der CPU, HMI-Zugriffe).

Harald
 
Eine FUNCTION soll jeden Eingang nur 1x lesen und jeden Ausgang nur 1x schreiben. Beachtet man dies nicht, dann bekommt man Probleme mit Multitask-Prozessen (mehrere Tasks in der CPU, HMI-Zugriffe).

Sei doch nicht so geheimnisvoll mit deinem Besserwissen. Sag mal konkret, was da geschehen könnte.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sei doch nicht so geheimnisvoll mit deinem Besserwissen. Sag mal konkret, was da geschehen könnte.
Sei doch nicht so begriffsstutzig - programmierst Du erst seit gestern? ;)

- wenn bei FC ein Parameter "per referenz" übergeben wird oder bei FB bei jeder Übergabe, dann kann zwischen dem ersten Lesen eines Eingangs und dem nächsten Lesen eine andere Task den Wert des Eingangs verändert haben
- wenn bei FC ein Parameter "per referenz" übergeben wird oder bei FB bei jeder Übergabe, dann kann zwischen dem ersten Schreiben eines Ausgangs und dem nächsten Schreiben oder Zurücklesen eine andere Task den Wert des Ausgangs gelesen haben oder gar verändert haben
- wenn bei FC mehrere Ausgänge per Referenz übergeben werden und beim Call mit der selben Variable verbunden sind, dann liest ein Zurücklesen nicht den Wert, der dem ersten Ausgang zugewiesen wurde, sondern den Wert, der zuletzt irgendeinem der "außen verbundenen" Ausgänge zugewiesen wurde. Das vergisst sogar Siemens manchmal und baut diesbezügliche Bugs als "Optimierung" in Step7-Compiler ein.

Eine besondere Falle stellen HMI-Zugriffe dar, wenn die HMI nicht im Zykluskontrollpunkt kommuniziert (weil das angeblich performanter ist). Betrifft S7-400/1200/1500 und S7-300 bei "priorisierter BuB-Kommunikation". Dann führt ein "erstmal 0 zuweisen" und "später was anderes zuweisen" zu sichtbarem Flackern oder gar überwiegend falsch-Anzeige auf dem HMI. Oder Tastendrücke HMI-->CPU funktionieren nur sporadisch. Diese Fallen besonders im Bezug zu HMI haben wir hier im Forum schon mehrfach diskutiert.

Harald
 
Sei doch nicht so begriffsstutzig - programmierst Du erst seit gestern? ;)

- wenn bei FC ein Parameter "per referenz" übergeben wird oder bei FB bei jeder Übergabe, dann kann zwischen dem ersten Lesen eines Eingangs und dem nächsten Lesen eine andere Task den Wert des Eingangs verändert haben
- wenn bei FC ein Parameter "per referenz" übergeben wird oder bei FB bei jeder Übergabe, dann kann zwischen dem ersten Schreiben eines Ausgangs und dem nächsten Schreiben oder Zurücklesen eine andere Task den Wert des Ausgangs gelesen haben oder gar verändert haben
- wenn bei FC mehrere Ausgänge per Referenz übergeben werden und beim Call mit der selben Variable verbunden sind, dann liest ein Zurücklesen nicht den Wert, der dem ersten Ausgang zugewiesen wurde, sondern den Wert, der zuletzt irgendeinem der "außen verbundenen" Ausgänge zugewiesen wurde. Das vergisst sogar Siemens manchmal und baut diesbezügliche Bugs als "Optimierung" in Step7-Compiler ein.

Eine besondere Falle stellen HMI-Zugriffe dar, wenn die HMI nicht im Zykluskontrollpunkt kommuniziert (weil das angeblich performanter ist). Betrifft S7-400/1200/1500 und S7-300 bei "priorisierter BuB-Kommunikation". Dann führt ein "erstmal 0 zuweisen" und "später was anderes zuweisen" zu sichtbarem Flackern oder gar überwiegend falsch-Anzeige auf dem HMI. Oder Tastendrücke HMI-->CPU funktionieren nur sporadisch. Diese Fallen besonders im Bezug zu HMI haben wir hier im Forum schon mehrfach diskutiert.

Harald

Das alles ist aber nur von Bedeutung, wenn auf diese Variablen verschiedene Tasks zugreifen. Die VAR_IN_OUT Variable ZwWert wird nur von der Funktion selbst verwendet, nicht mal vom aufrufenden FB. Der Ausgangsimpuls geht nur auf den Eingang eines Zählerbausteins. Was sollte da dazwischen funken? Und weder bei der einen noch der anderen ist es sinnvoll, sie über HMI zu ändern.

Der schlimmstmögliche Schaden wäre ein Impuls zuviel oder zuwenig. Gemessen an der extrem niedrigen Wahrscheinlichkeit, den Zeitraum zwischen beiden Zuweisungen zu treffen, halte ich das für verantwortbar.
 
Dass es nie vorkommt hab ich auch mal gedacht. Ich habe mir einen Zähler-FB geschrieben dem ich zwar einen extra Reset-Eingang verpasst habe, aber dann dachte ich mir zum Zurücksetzen kannst du auch vom HMI einfach den Wert auf 0 schreiben, spart schließlich die ein oder andere Variable in Summe.
Nach ein paar Monaten kam dann eine Mängelanmeldung, dass öfters das Rücksetzen der Zähler nicht funktioniere. Denn da setzt jeden Morgen jemand um 8 Uhr so um die 40 Zähler per Hand zurück. Und das bei einem ~800kB Programm in einer 400er, das Programm dürfte sich im Promillebereich der Zykluszeit in dem FB befinden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das alles ist aber nur von Bedeutung, wenn [...]
Ich habe nicht geschrieben, daß der Code für den angegebenen Zweck fehlerhaft funktionieren wird, sondern nur daß es ein schlechter Programmierstil ist.

Auch wenn dieser eine spezielle FC eher nicht mit HMI und anderen Tasks ins Gehege kommen wird, so kann man sich doch angewöhnen, einfach immer safe zu programmieren - man weiß ja nicht, wer den Code mal wofür benutzen wird (gerade wenn man Code hier im Forum zum Nachmachen präsentiert) - oder sollte man seine Bausteine auch noch gut sichtbar als "ist Tasksafe programmiert ja/nein" oder "Achtung quick'n'dirty" markieren?

"Extrem niedrige Wahrscheinlichkeit" - Meine Erfahrung: begünstigt dadurch, daß ein SPS-Programm zyklisch tausende Male pro Minute durchlaufen wird, wird jedes Ereignis, für das eine Wahrscheinlichkeit > 0 besteht, auch in erlebbarer Zeit auftreten.

Harald
 
Hallo zusammen,

der Verlauf ist schon ein paar Tage alt und ich nicht der beste Programmierer.
Kann mir jemand den Code in SCL übersetzen?

Ist es besser den Baustein als fb an zu legen um zwischenwerte ab zu speichern?

Welche Ein und Ausgänge muss ich dann anlegen?

Ich habe einen Durchfluss in der Einheit l/h und muss eigentlich einen puls pro Liter bekommen.
Die Menge ist nicht groß. es handelt sich um ca 20l/h.

Vielen Dank euch schon mal für die Hilfe
 
Hallo zusammen,

der Verlauf ist schon ein paar Tage alt und ich nicht der beste Programmierer.
Kann mir jemand den Code in SCL übersetzen?

Ist es besser den Baustein als fb an zu legen um zwischenwerte ab zu speichern?

Welche Ein und Ausgänge muss ich dann anlegen?

Ich habe einen Durchfluss in der Einheit l/h und muss eigentlich einen puls pro Liter bekommen.
Die Menge ist nicht groß. es handelt sich um ca 20l/h.

Vielen Dank euch schon mal für die Hilfe

IF „Taktmerker 1Hz“ and Not „Flanke Taktmerker 1Hz“ then
„ZW 1l Real“ := „ZW 1l Real“ + („IW L/h Real“ / 3600.0);
End_if;

If „ZW 1l Real“ > 1.0 then
„ZW 1l Real“ := „ZW 1l Real“ - 1.0;
„ZW Gesamt in l DINT“ := „ZW Gesamt in l DINT“ + 1;
End_if;

„Flanke Taktmerker 1Hz“ := „Taktmerker 1Hz“;



Ist jetzt schnell am Handy geschrieben, funktioniert aber 100%. Variablennamen kannst du durch Merker, DBs ersetzen. Kannst natürlich auch nen FB/FC daraus machen.
Ich nutze das, wenn ich ein MID ohne Impuls habe, bzw. wenn er mir nicht zur Verfügung steht. Da meine Zählwerte und Istwerte ohnehin immer in einem separarten DB liegen und jede Messung in einem eigenen DB programmiert ist, brauche ich eigentlich nur eine Variable für die Sekundenflanke und eine für den aufaddierten Zählwerte für den Liter Impuls.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
IF „Taktmerker_1Hz“ and Not „Flanke_Taktmerker_1Hz“ THEN
    „ZW_1l_Real“ := „ZW_1l_Real“ + („IW_L/h_Real“ / 3600.0);
    WHILE „ZW_1l_Real“ > 1.0 DO // WHILE statt IF, damit ggfs auch Überläufe >= 2.0 abgebaut werden
        „ZW_1l_Real“ := „ZW_1l_Real“ - 1.0;
        „ZW_Gesamt_in_l_DINT“ := „ZW_Gesamt_in_l_DINT“ + 1;
    END_WHILE;
END_IF;

„Flanke_Taktmerker_1Hz“ := „Taktmerker_1Hz“;
Ich habe mir 3 Änderungen erlaubt:
1. Die Leerzeichen in den VariablenNamen durch Unterstriche ersetzt.
2. Die zweite IF-Selektion in die erste integriert.
3. Die zweite IF-Selektion in eine WHILE-Schleife geändert.

Zu 1.:
"Unterbrechungen" in Namen (also auch VariablenNamen) sind bei SCL zwar zulässig, aber in sooo vielen anderen ProgrammierSprachen nicht, dass man die dort übliche Variante mit den Unterstrichen ohne Verlust an Lesbarkeit anwenden kann bzw. sollte.

Zu 2.:
Weil die Abfrage, ob die bedingte Ausführung des Übertrags erforderlich ist, nicht in allen Zyklen ausgeführt werden muss, sondern nur in den (wenigen) Zyklen, in denen sich der Zählerstand ändert.

Zu 3.:
Wegen 2. würde eine Differenz von >= 2.0 nicht mehr "nach und nach" abgebaut werden.
D.h., sollte sich - warum auch immer - eine grössere Differenz "angesammelt" haben, würde dieser Fehler beibehalten werden.

Nicht geändert:
'L' in 'l' in '„IW_L/h_Real“'.
Von der üblichen Gross-/KleinSchreibung von MassEinheiten sollte möglichst nicht abgewichen werden.
Leider hat man in diversen SchriftArten das Problem, dass z.B. 'I' (Klein-L) und 'l' (Gross-i) und evtl. auch '1' oder 'O' (Gross-o) und '0' (Null) kaum oder gar nicht zu unterscheiden *) sind, so dass Ausnahmen manchmal doch gerechtfertigt sein können.

*) Bei der Festlegung, wie die verschiedenen Zeichen in einer SchriftArt dargestellt werden, sollte m.E. der Eindeutigkeit endlich mal eine höhere Priorität vor dem Aspekt der "Schönheit" eingeräumt werden!
Ist diese Forderung denn nur in der AutomatisierungsTechnik relevant? Ich finde, man könnte sich auch in anderen Bereichen gut damit abfinden, ohne dafür grosse Opfer bringen zu müssen.
 
Nicht geändert:
'L' in 'l' in '„IW_L/h_Real“'.
Von der üblichen Gross-/KleinSchreibung von MassEinheiten sollte möglichst nicht abgewichen werden.
Leider hat man in diversen SchriftArten das Problem, dass z.B. 'I' (Klein-L) und 'l' (Gross-i) und evtl. auch '1' oder 'O' (Gross-o) und '0' (Null) kaum oder gar nicht zu unterscheiden *) sind, so dass Ausnahmen manchmal doch gerechtfertigt sein können.
Hallo Heinileini,

wo du dir bereits so viel Mühe gemacht hast, ist es nur konsequent, deine Auflistung wie folgt zu erweitern:

4) Allgemeine Regeln zur Bildung von Variablennamen
(Unabhängig davon, ob der Hersteller der Programmiersoftware den Blödsinn irrsinniger Weise zulässt)
  • der Variablennamen soll kurz aber auch möglichst selbsterklärend sein
  • Variablennamen dürfen keine Umlaute, Leerzeichen oder Sonderzeichen enthalten (einzige Ausnahme ist der Unterstrich für bessere Lesbarkeit/Strukturierung)
  • Variablennamen dürfen keine Rechenzeichen oder Klammern enthalten
  • der Name einer Variablen darf nicht mit einer Zahl beginnen
  • Schlüsselwörter und Funktionsnamen sind nicht erlaubt, können aber Bestandteil des Namens sein
 
Kurz und selbsterklärend schließt sich nur leider in der Regel gegenseitig aus.
Also macht es mehr Sinn sich für einen Weg zu entscheiden:

Man kreiert kryptische Namen, die man dann im Kommentar erläutert oder man nimmt gleich sprechende Variablennamen und spart sich den Kommentar.
Wobei ich, zwecks besserer Lesbarkeit, inzwischen auch gerne auf Unterstriche verzichte.
 
Zurück
Oben